diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 285a98e33..289c33aee 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -28,12 +28,10 @@ 8306B0AD20984552000302D4 /* blocked_caf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0922098454E000302D4 /* blocked_caf.c */; }; 8306B0AE20984552000302D4 /* blocked_filp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0932098454F000302D4 /* blocked_filp.c */; }; 8306B0AF20984552000302D4 /* blocked_rws.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0942098454F000302D4 /* blocked_rws.c */; }; - 8306B0B020984552000302D4 /* blocked_ps2_strlr.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0952098454F000302D4 /* blocked_ps2_strlr.c */; }; 8306B0B120984552000302D4 /* blocked_halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0962098454F000302D4 /* blocked_halpst.c */; }; 8306B0B220984552000302D4 /* blocked_mxch.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0972098454F000302D4 /* blocked_mxch.c */; }; 8306B0B320984552000302D4 /* blocked_thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09820984550000302D4 /* blocked_thp.c */; }; 8306B0B420984552000302D4 /* blocked_tra.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09920984550000302D4 /* blocked_tra.c */; }; - 8306B0B520984552000302D4 /* blocked_emff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09A20984550000302D4 /* blocked_emff.c */; }; 8306B0B620984552000302D4 /* blocked_hwas.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09B20984550000302D4 /* blocked_hwas.c */; }; 8306B0B720984552000302D4 /* blocked_str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09C20984550000302D4 /* blocked_str_snds.c */; }; 8306B0B820984552000302D4 /* blocked_ws_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09D20984551000302D4 /* blocked_ws_aud.c */; }; @@ -93,6 +91,31 @@ 832389521D224C0800482226 /* hca_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832389511D224C0800482226 /* hca_decoder.c */; }; 83299FD01E7660C7003A3242 /* bik.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCE1E7660C7003A3242 /* bik.c */; }; 83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCF1E7660C7003A3242 /* dsp_adx.c */; }; + 832BF7FF21E050B7006F50F1 /* circus_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF7FC21E050B6006F50F1 /* circus_decoder.c */; }; + 832BF80021E050B7006F50F1 /* mpeg_custom_utils_eamp3.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF7FD21E050B7006F50F1 /* mpeg_custom_utils_eamp3.c */; }; + 832BF80121E050B7006F50F1 /* pcfx_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF7FE21E050B7006F50F1 /* pcfx_decoder.c */; }; + 832BF80521E050DC006F50F1 /* blocked_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80221E050DB006F50F1 /* blocked_mul.c */; }; + 832BF80621E050DC006F50F1 /* blocked_vs_square.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80321E050DC006F50F1 /* blocked_vs_square.c */; }; + 832BF80721E050DC006F50F1 /* blocked_vs_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80421E050DC006F50F1 /* blocked_vs_str.c */; }; + 832BF80921E05135006F50F1 /* fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80821E05135006F50F1 /* fag.c */; }; + 832BF81C21E0514B006F50F1 /* xpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80A21E05148006F50F1 /* xpcm.c */; }; + 832BF81D21E0514B006F50F1 /* msf_tamasoft.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80B21E05148006F50F1 /* msf_tamasoft.c */; }; + 832BF81E21E0514B006F50F1 /* xps.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80C21E05148006F50F1 /* xps.c */; }; + 832BF81F21E0514B006F50F1 /* ps2_va3.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80D21E05148006F50F1 /* ps2_va3.c */; }; + 832BF82021E0514B006F50F1 /* zsnd_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 832BF80E21E05149006F50F1 /* zsnd_streamfile.h */; }; + 832BF82121E0514B006F50F1 /* zsnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF80F21E05149006F50F1 /* zsnd.c */; }; + 832BF82221E0514B006F50F1 /* vs_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81021E05149006F50F1 /* vs_str.c */; }; + 832BF82321E0514B006F50F1 /* imc.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81121E05149006F50F1 /* imc.c */; }; + 832BF82421E0514B006F50F1 /* mul.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81221E05149006F50F1 /* mul.c */; }; + 832BF82521E0514B006F50F1 /* ogg_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81321E05149006F50F1 /* ogg_opus.c */; }; + 832BF82621E0514B006F50F1 /* nwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81421E0514A006F50F1 /* nwav.c */; }; + 832BF82721E0514B006F50F1 /* xa.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81521E0514A006F50F1 /* xa.c */; }; + 832BF82821E0514B006F50F1 /* xwma.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81621E0514A006F50F1 /* xwma.c */; }; + 832BF82921E0514B006F50F1 /* msf_banpresto.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81721E0514A006F50F1 /* msf_banpresto.c */; }; + 832BF82A21E0514B006F50F1 /* vs_square.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81821E0514A006F50F1 /* vs_square.c */; }; + 832BF82B21E0514B006F50F1 /* xopus.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81921E0514A006F50F1 /* xopus.c */; }; + 832BF82C21E0514B006F50F1 /* hca_keys_awb.h in Headers */ = {isa = PBXBuildFile; fileRef = 832BF81A21E0514A006F50F1 /* hca_keys_awb.h */; }; + 832BF82D21E0514B006F50F1 /* nus3audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 832BF81B21E0514B006F50F1 /* nus3audio.c */; }; 832C70BF1E9335E400BD7B4E /* Vorbis.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83F4128F1E932F9A002E37D0 /* Vorbis.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83345A4F1F8AEB2800B2EAA4 /* nub_xma.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */; }; 83345A501F8AEB2800B2EAA4 /* pc_al2.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */; }; @@ -138,7 +161,6 @@ 834FE0B4215C798C000A5D3D /* ffmpeg_decoder_custom_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */; }; 834FE0B5215C798C000A5D3D /* acm_decoder_libacm.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */; }; 834FE0B6215C798C000A5D3D /* derf_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AD215C798B000A5D3D /* derf_decoder.c */; }; - 834FE0B7215C798C000A5D3D /* atrac9_decoder.c.orig in Resources */ = {isa = PBXBuildFile; fileRef = 834FE0AE215C798B000A5D3D /* atrac9_decoder.c.orig */; }; 834FE0B8215C798C000A5D3D /* acm_decoder_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AF215C798C000A5D3D /* acm_decoder_decode.c */; }; 834FE0B9215C798C000A5D3D /* xmd_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0B0215C798C000A5D3D /* xmd_decoder.c */; }; 834FE0BA215C798C000A5D3D /* ea_mt_decoder_utk.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FE0B1215C798C000A5D3D /* ea_mt_decoder_utk.h */; }; @@ -247,7 +269,6 @@ 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4318BDC2180095E648 /* dmsg_segh.c */; }; 836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4418BDC2180095E648 /* dsp_bdsp.c */; }; 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4618BDC2180095E648 /* ea_schl.c */; }; - 836F6F8418BDC2190095E648 /* emff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4818BDC2180095E648 /* emff.c */; }; 836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4918BDC2180095E648 /* exakt_sc.c */; }; 836F6F8618BDC2190095E648 /* excitebots.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4A18BDC2180095E648 /* excitebots.c */; }; 836F6F8718BDC2190095E648 /* ffw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4B18BDC2180095E648 /* ffw.c */; }; @@ -352,7 +373,6 @@ 836F6FFA18BDC2190095E648 /* ps2_spm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBE18BDC2190095E648 /* ps2_spm.c */; }; 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBF18BDC2190095E648 /* ps2_sps.c */; }; 836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC018BDC2190095E648 /* ps2_ster.c */; }; - 836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC318BDC2190095E648 /* ps2_strlr.c */; }; 836F700018BDC2190095E648 /* ps2_svag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC418BDC2190095E648 /* ps2_svag.c */; }; 836F700118BDC2190095E648 /* ps2_tec.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC518BDC2190095E648 /* ps2_tec.c */; }; 836F700218BDC2190095E648 /* ps2_tk5.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC618BDC2190095E648 /* ps2_tk5.c */; }; @@ -371,8 +391,6 @@ 836F701218BDC2190095E648 /* ps3_ivag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED618BDC2190095E648 /* ps3_ivag.c */; }; 836F701418BDC2190095E648 /* ps3_msf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED818BDC2190095E648 /* ps3_msf.c */; }; 836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.c */; }; - 836F701918BDC2190095E648 /* psx_cdxa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDD18BDC2190095E648 /* psx_cdxa.c */; }; - 836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; }; 836F701B18BDC2190095E648 /* psx_gms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDF18BDC2190095E648 /* psx_gms.c */; }; 836F701D18BDC2190095E648 /* raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE118BDC2190095E648 /* raw.c */; }; 836F701E18BDC2190095E648 /* redspark.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE218BDC2190095E648 /* redspark.c */; }; @@ -652,12 +670,10 @@ 8306B0922098454E000302D4 /* blocked_caf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_caf.c; sourceTree = ""; }; 8306B0932098454F000302D4 /* blocked_filp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_filp.c; sourceTree = ""; }; 8306B0942098454F000302D4 /* blocked_rws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_rws.c; sourceTree = ""; }; - 8306B0952098454F000302D4 /* blocked_ps2_strlr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ps2_strlr.c; sourceTree = ""; }; 8306B0962098454F000302D4 /* blocked_halpst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_halpst.c; sourceTree = ""; }; 8306B0972098454F000302D4 /* blocked_mxch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_mxch.c; sourceTree = ""; }; 8306B09820984550000302D4 /* blocked_thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_thp.c; sourceTree = ""; }; 8306B09920984550000302D4 /* blocked_tra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_tra.c; sourceTree = ""; }; - 8306B09A20984550000302D4 /* blocked_emff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_emff.c; sourceTree = ""; }; 8306B09B20984550000302D4 /* blocked_hwas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_hwas.c; sourceTree = ""; }; 8306B09C20984550000302D4 /* blocked_str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_str_snds.c; sourceTree = ""; }; 8306B09D20984551000302D4 /* blocked_ws_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ws_aud.c; sourceTree = ""; }; @@ -716,6 +732,31 @@ 832389511D224C0800482226 /* hca_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca_decoder.c; sourceTree = ""; }; 83299FCE1E7660C7003A3242 /* bik.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bik.c; sourceTree = ""; }; 83299FCF1E7660C7003A3242 /* dsp_adx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_adx.c; sourceTree = ""; }; + 832BF7FC21E050B6006F50F1 /* circus_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = circus_decoder.c; sourceTree = ""; }; + 832BF7FD21E050B7006F50F1 /* mpeg_custom_utils_eamp3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpeg_custom_utils_eamp3.c; sourceTree = ""; }; + 832BF7FE21E050B7006F50F1 /* pcfx_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcfx_decoder.c; sourceTree = ""; }; + 832BF80221E050DB006F50F1 /* blocked_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_mul.c; sourceTree = ""; }; + 832BF80321E050DC006F50F1 /* blocked_vs_square.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vs_square.c; sourceTree = ""; }; + 832BF80421E050DC006F50F1 /* blocked_vs_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vs_str.c; sourceTree = ""; }; + 832BF80821E05135006F50F1 /* fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fag.c; sourceTree = ""; }; + 832BF80A21E05148006F50F1 /* xpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xpcm.c; sourceTree = ""; }; + 832BF80B21E05148006F50F1 /* msf_tamasoft.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msf_tamasoft.c; sourceTree = ""; }; + 832BF80C21E05148006F50F1 /* xps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xps.c; sourceTree = ""; }; + 832BF80D21E05148006F50F1 /* ps2_va3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_va3.c; sourceTree = ""; }; + 832BF80E21E05149006F50F1 /* zsnd_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zsnd_streamfile.h; sourceTree = ""; }; + 832BF80F21E05149006F50F1 /* zsnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zsnd.c; sourceTree = ""; }; + 832BF81021E05149006F50F1 /* vs_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs_str.c; sourceTree = ""; }; + 832BF81121E05149006F50F1 /* imc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = imc.c; sourceTree = ""; }; + 832BF81221E05149006F50F1 /* mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mul.c; sourceTree = ""; }; + 832BF81321E05149006F50F1 /* ogg_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogg_opus.c; sourceTree = ""; }; + 832BF81421E0514A006F50F1 /* nwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwav.c; sourceTree = ""; }; + 832BF81521E0514A006F50F1 /* xa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xa.c; sourceTree = ""; }; + 832BF81621E0514A006F50F1 /* xwma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwma.c; sourceTree = ""; }; + 832BF81721E0514A006F50F1 /* msf_banpresto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msf_banpresto.c; sourceTree = ""; }; + 832BF81821E0514A006F50F1 /* vs_square.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs_square.c; sourceTree = ""; }; + 832BF81921E0514A006F50F1 /* xopus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xopus.c; sourceTree = ""; }; + 832BF81A21E0514A006F50F1 /* hca_keys_awb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hca_keys_awb.h; sourceTree = ""; }; + 832BF81B21E0514B006F50F1 /* nus3audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nus3audio.c; sourceTree = ""; }; 83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_xma.c; sourceTree = ""; }; 83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_al2.c; sourceTree = ""; }; 83345A4E1F8AEB2800B2EAA4 /* xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvag.c; sourceTree = ""; }; @@ -759,7 +800,6 @@ 834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_custom_opus.c; sourceTree = ""; }; 834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acm_decoder_libacm.h; sourceTree = ""; }; 834FE0AD215C798B000A5D3D /* derf_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = derf_decoder.c; sourceTree = ""; }; - 834FE0AE215C798B000A5D3D /* atrac9_decoder.c.orig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = atrac9_decoder.c.orig; sourceTree = ""; }; 834FE0AF215C798C000A5D3D /* acm_decoder_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm_decoder_decode.c; sourceTree = ""; }; 834FE0B0215C798C000A5D3D /* xmd_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xmd_decoder.c; sourceTree = ""; }; 834FE0B1215C798C000A5D3D /* ea_mt_decoder_utk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ea_mt_decoder_utk.h; sourceTree = ""; }; @@ -870,7 +910,6 @@ 836F6E4318BDC2180095E648 /* dmsg_segh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmsg_segh.c; sourceTree = ""; }; 836F6E4418BDC2180095E648 /* dsp_bdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_bdsp.c; sourceTree = ""; }; 836F6E4618BDC2180095E648 /* ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_schl.c; sourceTree = ""; }; - 836F6E4818BDC2180095E648 /* emff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff.c; sourceTree = ""; }; 836F6E4918BDC2180095E648 /* exakt_sc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exakt_sc.c; sourceTree = ""; }; 836F6E4A18BDC2180095E648 /* excitebots.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = excitebots.c; sourceTree = ""; }; 836F6E4B18BDC2180095E648 /* ffw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffw.c; sourceTree = ""; }; @@ -975,7 +1014,6 @@ 836F6EBE18BDC2190095E648 /* ps2_spm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_spm.c; sourceTree = ""; }; 836F6EBF18BDC2190095E648 /* ps2_sps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_sps.c; sourceTree = ""; }; 836F6EC018BDC2190095E648 /* ps2_ster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ster.c; sourceTree = ""; }; - 836F6EC318BDC2190095E648 /* ps2_strlr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_strlr.c; sourceTree = ""; }; 836F6EC418BDC2190095E648 /* ps2_svag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_svag.c; sourceTree = ""; }; 836F6EC518BDC2190095E648 /* ps2_tec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_tec.c; sourceTree = ""; }; 836F6EC618BDC2190095E648 /* ps2_tk5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_tk5.c; sourceTree = ""; }; @@ -994,8 +1032,6 @@ 836F6ED618BDC2190095E648 /* ps3_ivag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_ivag.c; sourceTree = ""; }; 836F6ED818BDC2190095E648 /* ps3_msf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_msf.c; sourceTree = ""; }; 836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.c; sourceTree = ""; }; - 836F6EDD18BDC2190095E648 /* psx_cdxa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_cdxa.c; sourceTree = ""; }; - 836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = ""; }; 836F6EDF18BDC2190095E648 /* psx_gms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_gms.c; sourceTree = ""; }; 836F6EE118BDC2190095E648 /* raw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw.c; sourceTree = ""; }; 836F6EE218BDC2190095E648 /* redspark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = redspark.c; sourceTree = ""; }; @@ -1284,8 +1320,8 @@ 8315958320FEC831007002F0 /* asf_decoder.c */, 8306B08120984517000302D4 /* at3plus_decoder.c */, 830EBE0F2004655D0023AA10 /* atrac9_decoder.c */, - 834FE0AE215C798B000A5D3D /* atrac9_decoder.c.orig */, 834FE0B2215C798C000A5D3D /* celt_fsb_decoder.c */, + 832BF7FC21E050B6006F50F1 /* circus_decoder.c */, 831BA6221EAC61CB00CF89B0 /* coding_utils.c */, 836F6DE518BDC2180095E648 /* coding.h */, 834FE0AD215C798B000A5D3D /* derf_decoder.c */, @@ -1309,6 +1345,7 @@ 839E21D91F2EDAF000EE54D7 /* mpeg_custom_utils_ahx.c */, 83AA5D141F6E2F600020821C /* mpeg_custom_utils_awc.c */, 83AA5D131F6E2F5F0020821C /* mpeg_custom_utils_ealayer3.c */, + 832BF7FD21E050B7006F50F1 /* mpeg_custom_utils_eamp3.c */, 839E21DD1F2EDAF000EE54D7 /* mpeg_custom_utils.c */, 836F6DEF18BDC2180095E648 /* mpeg_decoder.c */, 839E21DE1F2EDAF000EE54D7 /* mpeg_decoder.h */, @@ -1322,6 +1359,7 @@ 836F6DF618BDC2180095E648 /* nwa_decoder.c */, 836F6DF718BDC2180095E648 /* nwa_decoder.h */, 836F6DF818BDC2180095E648 /* ogg_vorbis_decoder.c */, + 832BF7FE21E050B7006F50F1 /* pcfx_decoder.c */, 836F6DF918BDC2180095E648 /* pcm_decoder.c */, 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */, 836F6DFA18BDC2180095E648 /* psx_decoder.c */, @@ -1360,7 +1398,6 @@ 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */, 8306B08B2098454D000302D4 /* blocked_ea_wve_ad10.c */, 8306B08A2098454D000302D4 /* blocked_ea_wve_au00.c */, - 8306B09A20984550000302D4 /* blocked_emff.c */, 8306B0932098454F000302D4 /* blocked_filp.c */, 8306B0A020984551000302D4 /* blocked_gsb.c */, 8342469520C4D23D00926E48 /* blocked_h4m.c */, @@ -1368,9 +1405,9 @@ 8306B09B20984550000302D4 /* blocked_hwas.c */, 8349A8E51FE6253800E26435 /* blocked_ivaud.c */, 8306B09E20984551000302D4 /* blocked_matx.c */, + 832BF80221E050DB006F50F1 /* blocked_mul.c */, 8306B0972098454F000302D4 /* blocked_mxch.c */, 8306B08D2098454D000302D4 /* blocked_ps2_iab.c */, - 8306B0952098454F000302D4 /* blocked_ps2_strlr.c */, 8306B0942098454F000302D4 /* blocked_rws.c */, 8306B08F2098454E000302D4 /* blocked_sthd.c */, 8306B09C20984550000302D4 /* blocked_str_snds.c */, @@ -1378,6 +1415,8 @@ 8306B09920984550000302D4 /* blocked_tra.c */, 8349A8E61FE6253900E26435 /* blocked_vawx.c */, 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */, + 832BF80321E050DC006F50F1 /* blocked_vs_square.c */, + 832BF80421E050DC006F50F1 /* blocked_vs_str.c */, 8306B0A120984551000302D4 /* blocked_vs.c */, 8306B09D20984551000302D4 /* blocked_ws_aud.c */, 8306B09F20984551000302D4 /* blocked_wsi.c */, @@ -1462,10 +1501,10 @@ 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */, 8306B0C42098458D000302D4 /* ea_wve_ad10.c */, 8306B0BF2098458C000302D4 /* ea_wve_au00.c */, - 836F6E4818BDC2180095E648 /* emff.c */, 836F6E4918BDC2180095E648 /* exakt_sc.c */, 836F6E4A18BDC2180095E648 /* excitebots.c */, 8349A8EF1FE6257C00E26435 /* ezw.c */, + 832BF80821E05135006F50F1 /* fag.c */, 838BDB6D1D3B043C0022CA6F /* ffmpeg.c */, 836F6E4B18BDC2180095E648 /* ffw.c */, 8349A8FD1FE6257F00E26435 /* flx.c */, @@ -1483,11 +1522,13 @@ 83709DFF1ECBC1A4005C03D3 /* gtd.c */, 8342469020C4D22F00926E48 /* h4m.c */, 836F6E5218BDC2180095E648 /* halpst.c */, + 832BF81A21E0514A006F50F1 /* hca_keys_awb.h */, 83AA5D211F6E2F9C0020821C /* hca_keys.h */, 8323894F1D2246C300482226 /* hca.c */, 834FE0DF215C79EB000A5D3D /* hd3_bd3.c */, 836F6E5318BDC2180095E648 /* his.c */, 834FE0E0215C79EB000A5D3D /* idsp_ie.c */, + 832BF81121E05149006F50F1 /* imc.c */, 836F6E5518BDC2180095E648 /* ios_psnd.c */, 836F6E5618BDC2180095E648 /* ish_isd.c */, 836F6E5718BDC2180095E648 /* ivaud.c */, @@ -1507,9 +1548,12 @@ 8349A9031FE6258100E26435 /* mogg.c */, 836F6E6018BDC2180095E648 /* mp4.c */, 8306B0CB2098458E000302D4 /* msb_msh.c */, + 832BF81721E0514A006F50F1 /* msf_banpresto.c */, + 832BF80B21E05148006F50F1 /* msf_tamasoft.c */, 83709E011ECBC1A4005C03D3 /* mss.c */, 834FE0E7215C79EC000A5D3D /* msv.c */, 836F6E6118BDC2180095E648 /* msvp.c */, + 832BF81221E05149006F50F1 /* mul.c */, 836F6E6218BDC2180095E648 /* mus_acm.c */, 836F6E6318BDC2180095E648 /* musc.c */, 836F6E6418BDC2180095E648 /* musx.c */, @@ -1545,10 +1589,13 @@ 834FE0E1215C79EB000A5D3D /* nub_idsp.c */, 83AB8C731E8072A100086084 /* nub_vag.c */, 83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */, + 832BF81B21E0514B006F50F1 /* nus3audio.c */, 834FE0D1215C79E9000A5D3D /* nus3bank.c */, 836F6E8118BDC2180095E648 /* nwa.c */, + 832BF81421E0514A006F50F1 /* nwav.c */, 834FE0DB215C79EA000A5D3D /* nxa.c */, 8306B0C02098458C000302D4 /* nxap.c */, + 832BF81321E05149006F50F1 /* ogg_opus.c */, 83A21F7F201D8980000F04B9 /* ogg_vorbis.c */, 831BA60F1EAC61A500CF89B0 /* ogl.c */, 8349A8FB1FE6257F00E26435 /* omu.c */, @@ -1619,11 +1666,11 @@ 836F6EBE18BDC2190095E648 /* ps2_spm.c */, 836F6EBF18BDC2190095E648 /* ps2_sps.c */, 836F6EC018BDC2190095E648 /* ps2_ster.c */, - 836F6EC318BDC2190095E648 /* ps2_strlr.c */, 8350C0591E071990009E0A93 /* ps2_svag_snk.c */, 836F6EC418BDC2190095E648 /* ps2_svag.c */, 836F6EC518BDC2190095E648 /* ps2_tec.c */, 836F6EC618BDC2190095E648 /* ps2_tk5.c */, + 832BF80D21E05148006F50F1 /* ps2_va3.c */, 836F6EC818BDC2190095E648 /* ps2_vas.c */, 836F6EC918BDC2190095E648 /* ps2_vbk.c */, 831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */, @@ -1642,8 +1689,6 @@ 836F6ED818BDC2190095E648 /* ps3_msf.c */, 8350270C1ED119D200C25929 /* ps3_mta2.c */, 836F6ED918BDC2190095E648 /* ps3_past.c */, - 836F6EDD18BDC2190095E648 /* psx_cdxa.c */, - 836F6EDE18BDC2190095E648 /* psx_fag.c */, 836F6EDF18BDC2190095E648 /* psx_gms.c */, 836F6EE118BDC2190095E648 /* raw.c */, 836F6EE218BDC2190095E648 /* redspark.c */, @@ -1707,6 +1752,8 @@ 836F6EFD18BDC2190095E648 /* vgs.c */, 834FE0CE215C79E8000A5D3D /* vis.c */, 834FE0D4215C79E9000A5D3D /* vpk.c */, + 832BF81821E0514A006F50F1 /* vs_square.c */, + 832BF81021E05149006F50F1 /* vs_str.c */, 836F6EFE18BDC2190095E648 /* vs.c */, 8349A8F91FE6257E00E26435 /* vsf_tta.c */, 836F6EFF18BDC2190095E648 /* vsf.c */, @@ -1733,6 +1780,7 @@ 831BA6151EAC61A500CF89B0 /* x360_cxs.c */, 831BA6171EAC61A500CF89B0 /* x360_pasx.c */, 836F6F0A18BDC2190095E648 /* x360_tra.c */, + 832BF81521E0514A006F50F1 /* xa.c */, 834FE0D2215C79E9000A5D3D /* xau_konami.c */, 833A7A2D1ED11961003EC53E /* xau.c */, 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */, @@ -1743,13 +1791,19 @@ 8350C0541E071881009E0A93 /* xma.c */, 834FE0DC215C79EA000A5D3D /* xmd.c */, 830EBE112004656E0023AA10 /* xnb.c */, + 832BF81921E0514A006F50F1 /* xopus.c */, + 832BF80A21E05148006F50F1 /* xpcm.c */, + 832BF80C21E05148006F50F1 /* xps.c */, 836F6F1218BDC2190095E648 /* xss.c */, 834FE0C6215C79E7000A5D3D /* xvag_streamfile.h */, 83345A4E1F8AEB2800B2EAA4 /* xvag.c */, 836F6F1318BDC2190095E648 /* xwb.c */, 83A21F7D201D8980000F04B9 /* xwc.c */, + 832BF81621E0514A006F50F1 /* xwma.c */, 836F6F1418BDC2190095E648 /* ydsp.c */, 836F6F1518BDC2190095E648 /* zsd.c */, + 832BF80E21E05149006F50F1 /* zsnd_streamfile.h */, + 832BF80F21E05149006F50F1 /* zsnd.c */, 836F6F1618BDC2190095E648 /* zwdsp.c */, ); path = meta; @@ -1797,8 +1851,10 @@ 834FE0ED215C79ED000A5D3D /* fsb_interleave_streamfile.h in Headers */, 8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */, 836F6F2718BDC2190095E648 /* g72x_state.h in Headers */, + 832BF82C21E0514B006F50F1 /* hca_keys_awb.h in Headers */, 8306B0E020984590000302D4 /* ppst_streamfile.h in Headers */, 834FE0BA215C798C000A5D3D /* ea_mt_decoder_utk.h in Headers */, + 832BF82021E0514B006F50F1 /* zsnd_streamfile.h in Headers */, 839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */, 836F705418BDC2190095E648 /* streamfile.h in Headers */, 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */, @@ -1974,7 +2030,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 834FE0B7215C798C000A5D3D /* atrac9_decoder.c.orig in Resources */, 836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1989,9 +2044,9 @@ 839E21E21F2EDAF100EE54D7 /* vorbis_custom_utils_wwise.c in Sources */, 83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */, 834FE104215C79ED000A5D3D /* nxa.c in Sources */, - 8306B0B020984552000302D4 /* blocked_ps2_strlr.c in Sources */, 8349A9071FE6258200E26435 /* dec.c in Sources */, 839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */, + 832BF80721E050DC006F50F1 /* blocked_vs_str.c in Sources */, 839E21E41F2EDAF100EE54D7 /* vorbis_custom_utils_fsb.c in Sources */, 839E21E11F2EDAF100EE54D7 /* vorbis_custom_decoder.c in Sources */, 839E21E71F2EDAF100EE54D7 /* mpeg_custom_utils.c in Sources */, @@ -2026,9 +2081,11 @@ 836F703218BDC2190095E648 /* str_asr.c in Sources */, 836F6FB218BDC2190095E648 /* ngc_gcub.c in Sources */, 836F702818BDC2190095E648 /* sat_dvi.c in Sources */, + 832BF82D21E0514B006F50F1 /* nus3audio.c in Sources */, 836F6F2F18BDC2190095E648 /* mtaf_decoder.c in Sources */, 83AA5D161F6E2F600020821C /* ea_xa_decoder.c in Sources */, 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */, + 832BF82821E0514B006F50F1 /* xwma.c in Sources */, 8306B0EB20984590000302D4 /* wave_segmented.c in Sources */, 836F6F9F18BDC2190095E648 /* musc.c in Sources */, 8349A9121FE6258200E26435 /* vsf_tta.c in Sources */, @@ -2043,6 +2100,7 @@ 836F6F2818BDC2190095E648 /* ima_decoder.c in Sources */, 8306B0DD20984590000302D4 /* waf.c in Sources */, 8306B0B320984552000302D4 /* blocked_thp.c in Sources */, + 832BF80921E05135006F50F1 /* fag.c in Sources */, 834FE0B6215C798C000A5D3D /* derf_decoder.c in Sources */, 836F702318BDC2190095E648 /* rsf.c in Sources */, 834FE109215C79ED000A5D3D /* idsp_ie.c in Sources */, @@ -2100,11 +2158,13 @@ 831BA61A1EAC61A500CF89B0 /* ps2_vds_vdm.c in Sources */, 836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */, 83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */, + 832BF80521E050DC006F50F1 /* blocked_mul.c in Sources */, 836F6FA818BDC2190095E648 /* nds_swav.c in Sources */, 8306B0D920984590000302D4 /* ngc_str_cauldron.c in Sources */, 834FE0FB215C79ED000A5D3D /* xau_konami.c in Sources */, 833A7A2E1ED11961003EC53E /* xau.c in Sources */, 836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */, + 832BF81E21E0514B006F50F1 /* xps.c in Sources */, 836F6F6C18BDC2190095E648 /* ahx.c in Sources */, 83AB8C751E8072A100086084 /* nub_vag.c in Sources */, 836F702D18BDC2190095E648 /* sfl.c in Sources */, @@ -2139,6 +2199,8 @@ 8349A9181FE6258200E26435 /* ea_1snh.c in Sources */, 83EED5D4203A8BC7008BEB45 /* aus.c in Sources */, 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */, + 832BF81D21E0514B006F50F1 /* msf_tamasoft.c in Sources */, + 832BF7FF21E050B7006F50F1 /* circus_decoder.c in Sources */, 83709E071ECBC1A4005C03D3 /* mss.c in Sources */, 836F6F8F18BDC2190095E648 /* his.c in Sources */, 834FE0E9215C79ED000A5D3D /* ao.c in Sources */, @@ -2161,7 +2223,6 @@ 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */, 836F6F7918BDC2190095E648 /* dc_asd.c in Sources */, 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, - 836F701A18BDC2190095E648 /* psx_fag.c in Sources */, 836F703B18BDC2190095E648 /* vsf.c in Sources */, 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */, 836F6F7318BDC2190095E648 /* bcstm.c in Sources */, @@ -2181,14 +2242,17 @@ 836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */, 836F6FA618BDC2190095E648 /* nds_sad.c in Sources */, 8306B0F120984590000302D4 /* ppst.c in Sources */, + 832BF81C21E0514B006F50F1 /* xpcm.c in Sources */, 836F702B18BDC2190095E648 /* sdt.c in Sources */, 836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */, 836F702C18BDC2190095E648 /* seg.c in Sources */, 836F700918BDC2190095E648 /* ps2_voi.c in Sources */, 836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */, 836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */, + 832BF82721E0514B006F50F1 /* xa.c in Sources */, 8306B0A220984552000302D4 /* blocked_bdsp.c in Sources */, 836F700118BDC2190095E648 /* ps2_tec.c in Sources */, + 832BF82121E0514B006F50F1 /* zsnd.c in Sources */, 836F703018BDC2190095E648 /* sqex_scd.c in Sources */, 8306B0A320984552000302D4 /* blocked_ast.c in Sources */, 836F6FD518BDC2190095E648 /* ps2_enth.c in Sources */, @@ -2197,7 +2261,6 @@ 8315958720FEC832007002F0 /* asf_decoder.c in Sources */, 836F705218BDC2190095E648 /* zwdsp.c in Sources */, 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */, - 836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */, 836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */, 8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */, 834FE0EA215C79ED000A5D3D /* aif_asobo.c in Sources */, @@ -2225,7 +2288,6 @@ 836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */, 836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */, 836F702118BDC2190095E648 /* rs03.c in Sources */, - 836F6F8418BDC2190095E648 /* emff.c in Sources */, 836F6F8818BDC2190095E648 /* fsb.c in Sources */, 836F6FE518BDC2190095E648 /* ps2_lpcm.c in Sources */, 836F6FB318BDC2190095E648 /* ngc_lps.c in Sources */, @@ -2241,12 +2303,14 @@ 834FE106215C79ED000A5D3D /* utk.c in Sources */, 831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */, 836F700218BDC2190095E648 /* ps2_tk5.c in Sources */, + 832BF80121E050B7006F50F1 /* pcfx_decoder.c in Sources */, 83AA5D271F6E2F9C0020821C /* stm.c in Sources */, 831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */, 836F703F18BDC2190095E648 /* wii_smp.c in Sources */, 8306B0A520984552000302D4 /* blocked_ea_wve_au00.c in Sources */, 836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */, 836F701518BDC2190095E648 /* ps3_past.c in Sources */, + 832BF80621E050DC006F50F1 /* blocked_vs_square.c in Sources */, 836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */, 836F6FED18BDC2190095E648 /* ps2_npsf.c in Sources */, 83A21F8B201D8982000F04B9 /* sps_n1.c in Sources */, @@ -2269,12 +2333,13 @@ 836F704618BDC2190095E648 /* x360_tra.c in Sources */, 834FE0F0215C79ED000A5D3D /* apc.c in Sources */, 836F6FFA18BDC2190095E648 /* ps2_spm.c in Sources */, - 836F701918BDC2190095E648 /* psx_cdxa.c in Sources */, 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */, 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */, 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */, + 832BF82A21E0514B006F50F1 /* vs_square.c in Sources */, 834FE0B4215C798C000A5D3D /* ffmpeg_decoder_custom_opus.c in Sources */, 8349A9091FE6258200E26435 /* pc_ast.c in Sources */, + 832BF81F21E0514B006F50F1 /* ps2_va3.c in Sources */, 8349A91C1FE6258200E26435 /* mogg.c in Sources */, 834FE0F5215C79ED000A5D3D /* wv2.c in Sources */, 836F703D18BDC2190095E648 /* wii_mus.c in Sources */, @@ -2298,10 +2363,12 @@ 836F6F7718BDC2190095E648 /* capdsp.c in Sources */, 836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */, 836F703318BDC2190095E648 /* str_snds.c in Sources */, + 832BF82221E0514B006F50F1 /* vs_str.c in Sources */, 8349A9191FE6258200E26435 /* afc.c in Sources */, 836F703718BDC2190095E648 /* tun.c in Sources */, 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */, 8349A9161FE6258200E26435 /* flx.c in Sources */, + 832BF82921E0514B006F50F1 /* msf_banpresto.c in Sources */, 834FE0BE215C79A9000A5D3D /* blocked_xa_aiff.c in Sources */, 831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */, 836F702A18BDC2190095E648 /* sd9.c in Sources */, @@ -2315,6 +2382,7 @@ 836F6F9518BDC2190095E648 /* kraw.c in Sources */, 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */, 8306B0E920984590000302D4 /* opus.c in Sources */, + 832BF80021E050B7006F50F1 /* mpeg_custom_utils_eamp3.c in Sources */, 83709E051ECBC1A4005C03D3 /* gtd.c in Sources */, 8306B0A420984552000302D4 /* segmented.c in Sources */, 83A21F86201D8981000F04B9 /* xwc.c in Sources */, @@ -2330,6 +2398,7 @@ 836F6F2518BDC2190095E648 /* g721_decoder.c in Sources */, 836F6FE818BDC2190095E648 /* ps2_mic.c in Sources */, 836F6F3C18BDC2190095E648 /* xa_decoder.c in Sources */, + 832BF82521E0514B006F50F1 /* ogg_opus.c in Sources */, 834FE10A215C79ED000A5D3D /* nub_idsp.c in Sources */, 83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */, 836F6F9118BDC2190095E648 /* ios_psnd.c in Sources */, @@ -2338,9 +2407,11 @@ 834FE0FF215C79ED000A5D3D /* sqex_scd_sscf.c in Sources */, 836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */, 831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */, + 832BF82621E0514B006F50F1 /* nwav.c in Sources */, 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */, 8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */, 831BA6181EAC61A500CF89B0 /* adx.c in Sources */, + 832BF82321E0514B006F50F1 /* imc.c in Sources */, 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */, 8306B0B620984552000302D4 /* blocked_hwas.c in Sources */, 836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */, @@ -2387,7 +2458,6 @@ 8306B0B420984552000302D4 /* blocked_tra.c in Sources */, 836F6FDD18BDC2190095E648 /* ps2_ikm.c in Sources */, 834FE0B8215C798C000A5D3D /* acm_decoder_decode.c in Sources */, - 8306B0B520984552000302D4 /* blocked_emff.c in Sources */, 836F6FBD18BDC2190095E648 /* nwa.c in Sources */, 834FE0F7215C79ED000A5D3D /* vis.c in Sources */, 83A21F8C201D8982000F04B9 /* kma9.c in Sources */, @@ -2399,6 +2469,7 @@ 836F6F4118BDC2190095E648 /* blocked.c in Sources */, 836F6F3B18BDC2190095E648 /* ws_decoder.c in Sources */, 838BDB6E1D3B043C0022CA6F /* ffmpeg.c in Sources */, + 832BF82B21E0514B006F50F1 /* xopus.c in Sources */, 836F6F3418BDC2190095E648 /* nwa_decoder.c in Sources */, 836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */, 836F6F9218BDC2190095E648 /* ish_isd.c in Sources */, @@ -2417,6 +2488,7 @@ 832389501D2246C300482226 /* hca.c in Sources */, 836F701B18BDC2190095E648 /* psx_gms.c in Sources */, 8306B0F020984590000302D4 /* atsl.c in Sources */, + 832BF82421E0514B006F50F1 /* mul.c in Sources */, 836F700518BDC2190095E648 /* ps2_vbk.c in Sources */, 836F6FDF18BDC2190095E648 /* ps2_int.c in Sources */, 8306B0AC20984552000302D4 /* blocked_xa.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c index c0b301115..5a7ae9623 100644 --- a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c +++ b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c @@ -26,7 +26,7 @@ #include #include -#define HCA_MASK 0x7F7F7F7F /* chunk obfuscation when the HCA is encrypted (ciph type > 0) */ +#define HCA_MASK 0x7F7F7F7F /* chunk obfuscation when the HCA is encrypted with key */ #define HCA_SUBFRAMES_PER_FRAME 8 #define HCA_SAMPLES_PER_SUBFRAME 128 #define HCA_SAMPLES_PER_FRAME (HCA_SUBFRAMES_PER_FRAME*HCA_SAMPLES_PER_SUBFRAME) @@ -34,6 +34,13 @@ #define HCA_MAX_CHANNELS 16 /* internal max? in practice only 8 can be encoded */ +#define HCA_ERROR_PARAMS -1 +#define HCA_ERROR_HEADER -2 +#define HCA_ERROR_CHECKSUM -3 +#define HCA_ERROR_SYNC -4 +#define HCA_ERROR_UNPACK -5 +#define HCA_ERROR_BITREADER -6 + //-------------------------------------------------- // Decoder config/state //-------------------------------------------------- @@ -239,7 +246,7 @@ int clHCA_isOurFile(const void *data, unsigned int size) { unsigned int header_size = 0; if (!data || size < 0x08) - return -1; + return HCA_ERROR_PARAMS; bitreader_init(&br, data, 8); if ((bitreader_peek(&br, 32) & HCA_MASK) == 0x48434100) {/*'HCA\0'*/ @@ -248,13 +255,13 @@ int clHCA_isOurFile(const void *data, unsigned int size) { } if (header_size == 0) - return -1; + return HCA_ERROR_HEADER; return header_size; } int clHCA_getInfo(clHCA *hca, clHCA_stInfo *info) { if (!hca || !info || !hca->is_valid) - return -1; + return HCA_ERROR_PARAMS; info->version = hca->version; info->headerSize = hca->header_size; @@ -286,10 +293,10 @@ void clHCA_ReadSamples16(clHCA *hca, signed short *samples) { for (k = 0; k < hca->channels; k++) { f = hca->channel[k].wave[i][j]; //f = f * hca->rva_volume; /* rare, won't apply for now */ - if (f > 1) { - f = 1; - } else if (f < -1) { - f = -1; + if (f > 1.0f) { + f = 1.0f; + } else if (f < -1.0f) { + f = -1.0f; } s = (signed int) (f * scale); if ((unsigned) (s + 0x8000) & 0xFFFF0000) @@ -424,7 +431,7 @@ static int ath_init(unsigned char *ath_curve, int type, unsigned int sample_rate ath_init1(ath_curve, sample_rate); break; default: - return -1; + return HCA_ERROR_HEADER; } return 0; } @@ -455,7 +462,7 @@ static void cipher_init1(unsigned char *cipher_table) { const int add = 11; unsigned int i, v = 0; - /* keyless encryption (unused?) */ + /* keyless encryption (rare) */ for (i = 1; i < 256 - 1; i++) { v = (v * mul + add) & 0xFF; if (v == 0 || v == 0xFF) @@ -542,7 +549,7 @@ static void cipher_init56(unsigned char *cipher_table, unsigned long long keycod } static int cipher_init(unsigned char *cipher_table, int type, unsigned long long keycode) { - if (!(keycode)) + if (type == 56 && !(keycode)) type = 0; switch (type) { @@ -556,7 +563,7 @@ static int cipher_init(unsigned char *cipher_table, int type, unsigned long long cipher_init56(cipher_table, keycode); break; default: - return -1; + return HCA_ERROR_HEADER; } return 0; } @@ -568,16 +575,17 @@ static unsigned int header_ceil2(unsigned int a, unsigned int b) { return (b > 0) ? (a / b + ((a % b) ? 1 : 0)) : 0; } -int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { +int clHCA_DecodeHeader(clHCA *hca, const void *data, unsigned int size) { clData br; + int res; - if (!hca || !data ) - return -1; + if (!hca || !data) + return HCA_ERROR_PARAMS; hca->is_valid = 0; if (size < 0x08) - return -1; + return HCA_ERROR_PARAMS; bitreader_init(&br, data, size); @@ -594,18 +602,18 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { hca->version != 0x0102 && hca->version != 0x0103 && hca->version != 0x0200) - return -1; + return HCA_ERROR_HEADER; #endif if (size < hca->header_size) - return -1; + return HCA_ERROR_PARAMS; if (crc16_checksum(data,hca->header_size)) - return -1; + return HCA_ERROR_CHECKSUM; size -= 0x08; } else { - return -1; + return HCA_ERROR_HEADER; } /* format info */ @@ -618,18 +626,18 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { hca->encoder_padding = bitreader_read(&br, 16); if (!(hca->channels >= 1 && hca->channels <= HCA_MAX_CHANNELS)) - return -1; + return HCA_ERROR_HEADER; if (hca->frame_count == 0) - return -1; + return HCA_ERROR_HEADER; if (!(hca->sample_rate >= 1 && hca->sample_rate <= 0x7FFFFF)) /* encoder max seems 48000 */ - return -1; + return HCA_ERROR_HEADER; size -= 0x10; } else { - return -1; + return HCA_ERROR_HEADER; } /* compression (v2.0) or decode (v1.x) info */ @@ -668,7 +676,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { size -= 0x0c; } else { - return -1; + return HCA_ERROR_HEADER; } /* VBR (variable bit rate) info */ @@ -678,7 +686,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { hca->vbr_noise_Level = bitreader_read(&br, 16); if (!(hca->frame_size == 0 && hca->vbr_max_frame_size > 8 && hca->vbr_max_frame_size <= 0x1FF)) - return -1; + return HCA_ERROR_HEADER; size -= 0x08; } @@ -710,7 +718,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { if (!(hca->loop_start_frame >= 0 && hca->loop_start_frame <= hca->loop_end_frame && hca->loop_end_frame < hca->frame_count)) - return -1; + return HCA_ERROR_HEADER; size -= 0x10; } @@ -729,7 +737,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { hca->ciph_type = bitreader_read(&br, 16); if (!(hca->ciph_type == 0 || hca->ciph_type == 1 || hca->ciph_type == 56)) - return -1; + return HCA_ERROR_HEADER; size -= 0x06; } @@ -760,11 +768,11 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { hca->comment_len = bitreader_read(&br, 8); if (hca->comment_len > size) - return -1; + return HCA_ERROR_HEADER; temp = realloc(hca->comment, hca->comment_len + 1); if (!temp) - return -1; + return HCA_ERROR_HEADER; hca->comment = temp; for (i = 0; i < hca->comment_len; ++i) hca->comment[i] = bitreader_read(&br, 8); @@ -782,17 +790,17 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { size -= (size - 0x02); /* fills up to header_size, sans checksum */ } - /* should be fully read, but allow data buffer may be bigger than header_size */ + /* should be fully read, but allow as data buffer may be bigger than header_size */ //if (size != 0x02) - // return -1; + // return HCA_ERROR_HEADER; /* extra validations */ if (!(hca->frame_size >= 0x08 && hca->frame_size <= 0xFFFF)) /* actual max seems 0x155*channels */ - return -1; /* theoretically can be 0 if VBR (not seen) */ + return HCA_ERROR_HEADER; /* theoretically can be 0 if VBR (not seen) */ if (!(hca->min_resolution == 1 && hca->max_resolution == 15)) - return -1; + return HCA_ERROR_HEADER; /* inits state */ @@ -803,10 +811,12 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) { hca->total_band_count - hca->base_band_count - hca->stereo_band_count, hca->bands_per_hfr_group); - if (ath_init(hca->ath_curve, hca->ath_type, hca->sample_rate) < 0) - return -1; - if (cipher_init(hca->cipher_table, hca->ciph_type, hca->keycode) < 0) - return -1; + res = ath_init(hca->ath_curve, hca->ath_type, hca->sample_rate); + if (res < 0) + return res; + res = cipher_init(hca->cipher_table, hca->ciph_type, hca->keycode); + if (res < 0) + return res; /* init channels */ @@ -919,43 +929,62 @@ int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size) { unsigned int ch, sf, s; int status; int clips = 0, blanks = 0; - float fsample; - signed int psample; - /* return if decode fails (happens sometimes with wrong keys) */ + + /* first blocks can be empty/silent, check all bytes but sync/crc */ + { + int i; + int is_empty = 1; + const unsigned char *buf = data; + + for (i = 2; i < size - 0x02; i++) { + if (buf[i] != 0) { + is_empty = 0; + break; + } + } + + if (is_empty) { + return 0; + } + } + + /* return if decode fails (happens often with wrong keys due to bad bitstream values) */ status = clHCA_DecodeBlock(hca, data, size); if (status < 0) return -1; - /* check decode results */ + /* check decode results as bad keys may still get here */ for (ch = 0; ch < hca->channels; ch++) { for (sf = 0; sf < HCA_SUBFRAMES_PER_FRAME; sf++) { for (s = 0; s < HCA_SAMPLES_PER_SUBFRAME; s++) { - fsample = hca->channel[ch].wave[sf][s]; - psample = (signed int) (fsample * scale); - if (fsample > 1.0f || fsample < -1.0f) + float fsample = hca->channel[ch].wave[sf][s]; + + if (fsample > 1.0f || fsample < -1.0f) { //improve? clips++; - else if (psample == 0 || psample == -1) - blanks++; + } + else { + signed int psample = (signed int) (fsample * scale); + if (psample == 0 || psample == -1) + blanks++; + } } } } /* the more clips the less likely block was correctly decrypted */ - if (clips > 0) + if (clips == 1) + clips++; + if (clips > 1) return clips; /* if block is silent result is not useful */ if (blanks == hca->channels * HCA_SUBFRAMES_PER_FRAME * HCA_SAMPLES_PER_SUBFRAME) return 0; - /* block may be correct (but wrong keys can get this too) */ + /* block may be correct (but wrong keys can get this too and should test more blocks) */ return 1; } - -#if 0 -// it'd seem like resetting IMDCT (others get overwritten) would matter when restarting the -// stream from 0, but doesn't seem any different, maybe because the first frame acts as setup/empty void clHCA_DecodeReset(clHCA * hca) { unsigned int i; @@ -965,18 +994,18 @@ void clHCA_DecodeReset(clHCA * hca) { for (i = 0; i < hca->channels; i++) { stChannel *ch = &hca->channel[i]; - memset(ch->intensity, 0, sizeof(ch->intensity[0]) * HCA_SUBFRAMES_PER_FRAME); - memset(ch->scalefactors, 0, sizeof(ch->scalefactors[0]) * HCA_SAMPLES_PER_SUBFRAME); - memset(ch->resolution, 0, sizeof(ch->resolution[0]) * HCA_SAMPLES_PER_SUBFRAME); - memset(ch->gain, 0, sizeof(ch->gain[0]) * HCA_SAMPLES_PER_SUBFRAME); - memset(ch->spectra, 0, sizeof(ch->spectra[0]) * HCA_SAMPLES_PER_SUBFRAME); - memset(ch->temp, 0, sizeof(ch->temp[0]) * HCA_SAMPLES_PER_SUBFRAME); - memset(ch->dct, 0, sizeof(ch->dct[0]) * HCA_SAMPLES_PER_SUBFRAME); + /* most values get overwritten during decode */ + //memset(ch->intensity, 0, sizeof(ch->intensity[0]) * HCA_SUBFRAMES_PER_FRAME); + //memset(ch->scalefactors, 0, sizeof(ch->scalefactors[0]) * HCA_SAMPLES_PER_SUBFRAME); + //memset(ch->resolution, 0, sizeof(ch->resolution[0]) * HCA_SAMPLES_PER_SUBFRAME); + //memset(ch->gain, 0, sizeof(ch->gain[0]) * HCA_SAMPLES_PER_SUBFRAME); + //memset(ch->spectra, 0, sizeof(ch->spectra[0]) * HCA_SAMPLES_PER_SUBFRAME); + //memset(ch->temp, 0, sizeof(ch->temp[0]) * HCA_SAMPLES_PER_SUBFRAME); + //memset(ch->dct, 0, sizeof(ch->dct[0]) * HCA_SAMPLES_PER_SUBFRAME); memset(ch->imdct_previous, 0, sizeof(ch->imdct_previous[0]) * HCA_SAMPLES_PER_SUBFRAME); - memset(ch->wave, 0, sizeof(ch->wave[0][0]) * HCA_SUBFRAMES_PER_FRAME * HCA_SUBFRAMES_PER_FRAME); + //memset(ch->wave, 0, sizeof(ch->wave[0][0]) * HCA_SUBFRAMES_PER_FRAME * HCA_SUBFRAMES_PER_FRAME); } } -#endif //-------------------------------------------------- // Decode @@ -1002,19 +1031,19 @@ int clHCA_DecodeBlock(clHCA *hca, void *data, unsigned int size) { unsigned int subframe, ch; if (!data || !hca || !hca->is_valid) - return -1; + return HCA_ERROR_PARAMS; if (size < hca->frame_size) - return -1; + return HCA_ERROR_PARAMS; bitreader_init(&br, data, hca->frame_size); /* test sync (not encrypted) */ sync = bitreader_read(&br, 16); if (sync != 0xFFFF) - return -1; + return HCA_ERROR_SYNC; if (crc16_checksum(data, hca->frame_size)) - return -1; + return HCA_ERROR_CHECKSUM; cipher_decrypt(hca->cipher_table, data, hca->frame_size); @@ -1029,7 +1058,7 @@ int clHCA_DecodeBlock(clHCA *hca, void *data, unsigned int size) { int unpack = decode1_unpack_channel(&hca->channel[ch], &br, hca->hfr_group_count, packed_noise_level, hca->ath_curve); if (unpack < 0) - return -1; + return unpack; } } @@ -1059,9 +1088,12 @@ int clHCA_DecodeBlock(clHCA *hca, void *data, unsigned int size) { } } - /* should read all frame sans checksum at most */ - if (br.bit > br.size - 16) { - return -1; + /* should read all frame sans checksum (16b) at most */ + /* one frame was found to read up to 14b left (cross referenced with CRI's tools), + * perhaps some encoding hiccup [World of Final Fantasy Maxima (Switch) am_ev21_0170 video], + * though this validation makes more sense when testing keys and isn't normally done on decode */ + if (br.bit + 14 > br.size) { /* relax validation a bit for that case */ + return HCA_ERROR_BITREADER; } return 0; @@ -1131,8 +1163,8 @@ static int decode1_unpack_channel(stChannel *ch, clData *br, if (delta != expected_delta) { /* may happen with bad keycodes, scalefactors must be 6b indexes */ int scalefactor_test = (int)scalefactor_prev + ((int)delta - (int)extra_delta); - if (scalefactor_test < 0 || scalefactor_test > 64) { - return -1; + if (scalefactor_test < 0 || scalefactor_test >= 64) { + return HCA_ERROR_UNPACK; } scalefactor_prev += delta - extra_delta; @@ -1160,7 +1192,7 @@ static int decode1_unpack_channel(stChannel *ch, clData *br, } /* 15 may be an invalid value? */ //else { - // return -1; + // return HCA_ERROR_INSENSITY; //} } else { @@ -1519,9 +1551,9 @@ static const unsigned int decode5_imdct_window_int[128] = { static const float *decode5_imdct_window = (const float *)decode5_imdct_window_int; static void decoder5_run_imdct(stChannel *ch, int subframe) { - const static unsigned int size = HCA_SAMPLES_PER_SUBFRAME; - const static unsigned int half = HCA_SAMPLES_PER_SUBFRAME / 2; - const static unsigned int mdct_bits = HCA_MDCT_BITS; + static const unsigned int size = HCA_SAMPLES_PER_SUBFRAME; + static const unsigned int half = HCA_SAMPLES_PER_SUBFRAME / 2; + static const unsigned int mdct_bits = HCA_MDCT_BITS; /* apply DCT-IV to dequantized spectra */ diff --git a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h index 071e3a2b4..df2b71a80 100644 --- a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h +++ b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h @@ -27,7 +27,7 @@ void clHCA_delete(clHCA *); * the header length with clHCA_isOurFile, then read data and call this. * May be called multiple times to reset decoder state. * Returns 0 on success, <0 on failure. */ -int clHCA_DecodeHeader(clHCA *, void *data, unsigned int size); +int clHCA_DecodeHeader(clHCA *, const void *data, unsigned int size); typedef struct clHCA_stInfo { unsigned int version; @@ -61,6 +61,7 @@ int clHCA_getInfo(clHCA *, clHCA_stInfo *out); /* Decodes a single frame, from data after headerSize. Should be called after * clHCA_DecodeHeader and size must be at least blockSize long. + * Data may be modified if encrypted. * Returns 0 on success, <0 on failure. */ int clHCA_DecodeBlock(clHCA *, void *data, unsigned int size); @@ -81,6 +82,10 @@ void clHCA_SetKey(clHCA *, unsigned long long keycode); * and select the key with scores closer to 1. */ int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size); +/* Resets the internal decode state, used when restarting to decode the file from the beginning. + * Without it there are minor differences, mainly useful when testing a new key. */ +void clHCA_DecodeReset(clHCA * hca); + #ifdef __cplusplus } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c index 420c450ab..58594bb64 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c @@ -128,7 +128,7 @@ void decode_atrac9(VGMSTREAM *vgmstream, sample * outbuf, int32_t samples_to_do, decode_fail: /* on error just put some 0 samples */ - VGM_LOG("ATRAC9: decode fail at %"PRIx64", missing %i samples\n", (off64_t)stream->offset, (samples_to_do - samples_done)); + VGM_LOG("ATRAC9: decode fail at %x, missing %i samples\n", (uint32_t)stream->offset, (samples_to_do - samples_done)); memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample) * channels); } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c.orig b/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c.orig deleted file mode 100644 index d46a7c433..000000000 --- a/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c.orig +++ /dev/null @@ -1,259 +0,0 @@ -#include "coding.h" - -#ifdef VGM_USE_ATRAC9 -#include "libatrac9.h" - - -/* opaque struct */ -struct atrac9_codec_data { - uint8_t *data_buffer; - size_t data_buffer_size; - - sample *sample_buffer; - size_t samples_filled; /* number of samples in the buffer */ - size_t samples_used; /* number of samples extracted from the buffer */ - - int samples_to_discard; - - atrac9_config config; - - void *handle; /* decoder handle */ - Atrac9CodecInfo info; /* decoder info */ -}; - - -atrac9_codec_data *init_atrac9(atrac9_config *cfg) { - int status; - uint8_t config_data[4]; - atrac9_codec_data *data = NULL; - - data = calloc(1, sizeof(atrac9_codec_data)); - if (!data) goto fail; - - data->handle = Atrac9GetHandle(); - if (!data->handle) goto fail; - - put_32bitBE(config_data, cfg->config_data); - status = Atrac9InitDecoder(data->handle, config_data); - if (status < 0) goto fail; - - status = Atrac9GetCodecInfo(data->handle, &data->info); - if (status < 0) goto fail; - //;VGM_LOG("ATRAC9: config=%x, sf-size=%x, sub-frames=%i x %i samples\n", cfg->config_data, info.superframeSize, info.framesInSuperframe, info.frameSamples); - - if (cfg->channels && cfg->channels != data->info.channels) { - VGM_LOG("ATRAC9: channels in header %i vs config %i don't match\n", cfg->channels, data->info.channels); - goto fail; /* unknown multichannel layout */ - } - - - /* must hold at least one superframe and its samples */ - data->data_buffer_size = data->info.superframeSize; - data->data_buffer = calloc(sizeof(uint8_t), data->data_buffer_size); - data->sample_buffer = calloc(sizeof(sample), data->info.channels * data->info.frameSamples * data->info.framesInSuperframe); - - data->samples_to_discard = cfg->encoder_delay; - - memcpy(&data->config, cfg, sizeof(atrac9_config)); - - return data; - -fail: - free_atrac9(data); - return NULL; -} - -void decode_atrac9(VGMSTREAM *vgmstream, sample * outbuf, int32_t samples_to_do, int channels) { - VGMSTREAMCHANNEL *stream = &vgmstream->ch[0]; - atrac9_codec_data * data = vgmstream->codec_data; - int samples_done = 0; - - - while (samples_done < samples_to_do) { - - if (data->samples_filled) { /* consume samples */ - int samples_to_get = data->samples_filled; - - if (data->samples_to_discard) { - /* discard samples for looping */ - if (samples_to_get > data->samples_to_discard) - samples_to_get = data->samples_to_discard; - data->samples_to_discard -= samples_to_get; - } - else { - /* get max samples and copy */ - if (samples_to_get > samples_to_do - samples_done) - samples_to_get = samples_to_do - samples_done; - - memcpy(outbuf + samples_done*channels, - data->sample_buffer + data->samples_used*channels, - samples_to_get*channels * sizeof(sample)); - - samples_done += samples_to_get; - } - - /* mark consumed samples */ - data->samples_used += samples_to_get; - data->samples_filled -= samples_to_get; - } - else { /* decode data */ - int iframe, status; - int bytes_used = 0; - uint8_t *buffer = data->data_buffer; - size_t bytes; - - data->samples_used = 0; - - /* ATRAC9 is made of decodable superframes with several sub-frames. AT9 config data gives - * superframe size, number of frames and samples (~100-200 bytes and ~256/1024 samples). */ - - /* read one raw block (superframe) and advance offsets */ - bytes = read_streamfile(data->data_buffer,stream->offset, data->info.superframeSize,stream->streamfile); - if (bytes != data->data_buffer_size) goto decode_fail; - - stream->offset += bytes; - - /* decode all frames in the superframe block */ - for (iframe = 0; iframe < data->info.framesInSuperframe; iframe++) { - status = Atrac9Decode(data->handle, buffer, data->sample_buffer + data->samples_filled*channels, &bytes_used); - if (status < 0) goto decode_fail; - - buffer += bytes_used; - data->samples_filled += data->info.frameSamples; - } - } - } - - return; - -decode_fail: - /* on error just put some 0 samples */ - VGM_LOG("ATRAC9: decode fail at %"PRIx64", missing %i samples\n", (off64_t)stream->offset, (samples_to_do - samples_done)); - memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample) * channels); -} - -void reset_atrac9(VGMSTREAM *vgmstream) { - atrac9_codec_data *data = vgmstream->codec_data; - if (!data) return; - - if (!data->handle) - goto fail; - -#if 0 - /* reopen/flush, not needed as superframes decode separatedly and there is no carried state */ - { - int status; - uint8_t config_data[4]; - - Atrac9ReleaseHandle(data->handle); - data->handle = Atrac9GetHandle(); - if (!data->handle) goto fail; - - put_32bitBE(config_data, data->config.config_data); - status = Atrac9InitDecoder(data->handle, config_data); - if (status < 0) goto fail; - } -#endif - - data->samples_used = 0; - data->samples_filled = 0; - data->samples_to_discard = data->config.encoder_delay; - - return; - -fail: - return; /* decode calls should fail... */ -} - -void seek_atrac9(VGMSTREAM *vgmstream, int32_t num_sample) { - atrac9_codec_data *data = vgmstream->codec_data; - if (!data) return; - - reset_atrac9(vgmstream); - - /* find closest offset to desired sample, and samples to discard after that offset to reach loop */ - { - int32_t seek_sample = data->config.encoder_delay + num_sample; - off_t seek_offset; - int32_t seek_discard; - int32_t superframe_samples = data->info.frameSamples * data->info.framesInSuperframe; - size_t superframe_number, superframe_back; - - superframe_number = (seek_sample / superframe_samples); /* closest */ - - /* decoded frames affect each other slightly, so move offset back to make PCM stable - * and equivalent to a full discard loop */ - superframe_back = 1; /* 1 seems enough (even when only 1 subframe in superframe) */ - if (superframe_back > superframe_number) - superframe_back = superframe_number; - - seek_discard = (seek_sample % superframe_samples) + (superframe_back * superframe_samples); - seek_offset = (superframe_number - superframe_back) * data->info.superframeSize; - - data->samples_to_discard = seek_discard; /* already includes encoder delay */ - - if (vgmstream->loop_ch) - vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + seek_offset; - } - -#if 0 - //old full discard loop - { - data->samples_to_discard = num_sample; - data->samples_to_discard += data->config.encoder_delay; - - /* loop offsets are set during decode; force them to stream start so discard works */ - if (vgmstream->loop_ch) - vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset; - } -#endif - -} - -void free_atrac9(atrac9_codec_data *data) { - if (!data) return; - - if (data->handle) Atrac9ReleaseHandle(data->handle); - free(data->data_buffer); - free(data->sample_buffer); - free(data); -} - - -size_t atrac9_bytes_to_samples(size_t bytes, atrac9_codec_data *data) { - return bytes / data->info.superframeSize * (data->info.frameSamples * data->info.framesInSuperframe); -} - -#if 0 //not needed (for now) -int atrac9_parse_config(uint32_t atrac9_config, int *out_sample_rate, int *out_channels, size_t *out_frame_size) { - static const int sample_rate_table[16] = { - 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, - 44100, 48000, 64000, 88200, 96000,128000,176400,192000 - }; - static const int channel_table[8] = { - 1, 2, 2, 6, 8, 4, 0, 0 - }; - - uint32_t sync = (atrac9_config >> 24) & 0xff; /* 8b */ - uint8_t sample_rate_index = (atrac9_config >> 20) & 0x0f; /* 4b */ - uint8_t channels_index = (atrac9_config >> 17) & 0x07; /* 3b */ - /* uint8_t validation bit = (atrac9_config >> 16) & 0x01; */ /* 1b */ - size_t frame_size = (atrac9_config >> 5) & 0x7FF; /* 11b */ - size_t superframe_index = (atrac9_config >> 3) & 0x3; /* 2b */ - /* uint8_t unused = (atrac9_config >> 0) & 0x7);*/ /* 3b */ - - if (sync != 0xFE) - goto fail; - if (out_sample_rate) - *out_sample_rate = sample_rate_table[sample_rate_index]; - if (out_channels) - *out_channels = channel_table[channels_index]; - if (out_frame_size) - *out_frame_size = (frame_size+1) * (1 << superframe_index); - - return 1; -fail: - return 0; -} -#endif -#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/celt_fsb_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/celt_fsb_decoder.c index dbf3ba2fc..b2805ccce 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/celt_fsb_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/celt_fsb_decoder.c @@ -157,7 +157,7 @@ void decode_celt_fsb(VGMSTREAM *vgmstream, sample * outbuf, int32_t samples_to_d decode_fail: /* on error just put some 0 samples */ - VGM_LOG("CELT: decode fail at %"PRIx64", missing %i samples\n", (off64_t)stream->offset, (samples_to_do - samples_done)); + VGM_LOG("CELT: decode fail at %x, missing %i samples\n", (uint32_t)stream->offset, (samples_to_do - samples_done)); memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample) * channels); } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c new file mode 100644 index 000000000..54dde1a7e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c @@ -0,0 +1,29 @@ +#include "coding.h" + + +/* Circus XPCM mode 2 decoding, verified vs EF.exe (info from foo_adpcm/libpcm and https://github.com/lioncash/ExtractData) */ +void decode_circus_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_pos = 0; + int32_t hist = stream->adpcm_history1_32; + int scale = stream->adpcm_scale; + off_t frame_offset = stream->offset; /* frame size is 1 */ + + + for (i = first_sample; i < first_sample + samples_to_do; i++) { + int8_t code = read_8bit(frame_offset+i,stream->streamfile); + + hist += code << scale; + if (code == 0) { + if (scale > 0) + scale--; + } + else if (code == 127 || code == -128) { + if (scale < 8) + scale++; + } + outbuf[sample_pos] = hist; + } + + stream->adpcm_history1_32 = hist; + stream->adpcm_scale = scale; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index 977cfdf0a..676a313f8 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -21,6 +21,7 @@ void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_wv6_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_ffta2_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); @@ -164,6 +165,12 @@ void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, /* derf_decoder */ void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +/* circus_decoder */ +void decode_circus_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* pcfx_decoder */ +void decode_pcfx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode); +size_t pcfx_bytes_to_samples(size_t bytes, int channels); /* ea_mt_decoder*/ ea_mt_codec_data *init_ea_mt(int channels, int type); @@ -267,6 +274,7 @@ void free_celt_fsb(celt_codec_data *data); /* ffmpeg_decoder */ ffmpeg_codec_data *init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); ffmpeg_codec_data *init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size); +ffmpeg_codec_data *init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong); void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels); void reset_ffmpeg(VGMSTREAM *vgmstream); @@ -278,9 +286,14 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples); /* ffmpeg_decoder_custom_opus.c (helper-things) */ ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); -size_t ffmpeg_make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate); -size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile); -size_t ue4_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile); +ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); +ffmpeg_codec_data * init_ffmpeg_x_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); + +size_t switch_opus_get_samples(off_t offset, size_t data_size, STREAMFILE *streamFile); + +size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile); +size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile); +size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile); #endif @@ -314,7 +327,6 @@ typedef struct { /* output */ int32_t num_samples; - int32_t skip_samples; int32_t loop_start_sample; int32_t loop_end_sample; } ms_sample_data; @@ -325,6 +337,9 @@ void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ali void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * loop_start_b, int32_t * loop_end_b, int32_t * loop_subframe, int be); void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_loop_end_sample, int be); void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample); + +void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples); + int riff_get_fact_skip_samples(STREAMFILE * streamFile, off_t start_offset); size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align); @@ -345,4 +360,8 @@ typedef struct { int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value); int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value); + +/* helper to pass a wrapped, clamped, fake extension-ed, SF to another meta */ +STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* extension); + #endif /*_CODING_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c index aa5bb57c8..8b601ccd2 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c @@ -328,6 +328,35 @@ int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data if (buf_size < riff_size) return -1; + /* XWMA encoder only allows a few channel/sample rate/bitrate combinations, + * but some create identical files with fake bitrate (1ch 22050hz at + * 20/48/192kbps are all 20kbps, with the exact same codec data). + * Decoder needs correct bitrate to work, so it's normalized here. */ + /* (may be removed once FFmpeg fixes this) */ + if (codec == 0x161) { /* WMAv2 only */ + int ch = channels; + int sr = sample_rate; + int br = avg_bps * 8; + + /* Must be a bug in MS's encoder, as later versions of xWMAEncode remove these bitrates */ + if (ch == 1) { + if (sr == 22050 && (br==48000 || br==192000)) + br = 20000; + else if (sr == 32000 && (br==48000 || br==192000)) + br = 20000; + else if (sr == 44100 && (br==96000 || br==192000)) + br = 48000; + } + else if (ch == 2) { + if (sr == 22050 && (br==48000 || br==192000)) + br = 32000; + else if (sr == 32000 && (br==192000)) + br = 48000; + } + + avg_bps = br / 8; + } + memcpy(buf+0x00, "RIFF", 4); put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */ memcpy(buf+0x08, "XWMA", 4); @@ -341,7 +370,7 @@ int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data put_16bitLE(buf+0x20, block_align); /* block align */ put_16bitLE(buf+0x22, 16); /* bits per sample */ put_16bitLE(buf+0x24, 0); /* extra size */ - /* here goes the "dpds" table, but it's optional and not needed by FFmpeg */ + /* here goes the "dpds" seek table, but it's optional and not needed by FFmpeg (and also buggy) */ memcpy(buf+0x26, "data", 4); put_32bitLE(buf+0x2a, data_size); /* data size */ @@ -410,85 +439,93 @@ fail: /* XMA PARSING */ /* ******************************************** */ +static void ms_audio_parse_header(STREAMFILE *streamFile, int xma_version, off_t offset_b, int bits_frame_size, size_t *first_frame_b, size_t *packet_skip_count, size_t *header_size_b) { + if (xma_version == 1) { /* XMA1 */ + //packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */ + //unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */ + *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */ + *packet_skip_count = read_bitsBE_b(offset_b+21, 11, streamFile); /* packets to skip for next packet of this stream */ + *header_size_b = 32; + } else if (xma_version == 2) { /* XMA2 */ + //frame_count = read_bitsBE_b(offset_b+0, 6, streamFile); /* frames that begin in this packet */ + *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside this packet */ + //packet_metadata = read_bitsBE_b(offset_b+21, 3, streamFile); /* packet_metadata (always 1) */ + *packet_skip_count = read_bitsBE_b(offset_b+24, 8, streamFile); /* packets to skip for next packet of this stream */ + *header_size_b = 32; + } else { /* WMAPRO(v3) */ + //packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */ + //unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */ + *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */ + *packet_skip_count = 0; /* xwma has no need to skip packets since it uses real multichannel audio */ + *header_size_b = 4+2+bits_frame_size; /* variable-sized header */ + } + + + /* XMA2 packets with XMA1 RIFF (transmogrified), remove the packet metadata flag */ + if (xma_version == 1 && (*packet_skip_count & 0x700) == 0x100) { + //VGM_LOG("MS_SAMPLES: XMA1 transmogrified packet header at 0x%lx\n", (off_t)offset_b/8); + *packet_skip_count &= ~0x100; + } + + /* full packet skip, no new frames start in this packet (prev frames can end here) + * standardized to some value */ + if (*packet_skip_count == 0x7FF) { /* XMA1, 11b */ + VGM_LOG("MS_SAMPLES: XMA1 full packet_skip at 0x%x\n", (uint32_t)offset_b/8); + *packet_skip_count = 0x800; + } + else if (*packet_skip_count == 0xFF) { /* XMA2, 8b*/ + VGM_LOG("MS_SAMPLES: XMA2 full packet_skip at 0x%x\n", (uint32_t)offset_b/8); + *packet_skip_count = 0x800; + } + + /* unusual but not impossible, as the encoder can interleave packets in any way */ + VGM_ASSERT((*packet_skip_count > 10 && *packet_skip_count < 0x800), + "MS_SAMPLES: found big packet skip %i at 0x%x\n", *packet_skip_count, (uint32_t)offset_b/8); +} + /** * Find total and loop samples of Microsoft audio formats (WMAPRO/XMA1/XMA2) by reading frame headers. * * The stream is made of packets, each containing N small frames of X samples. Frames are further divided into subframes. * XMA1/XMA2 can divided into streams for multichannel (1/2ch ... 1/2ch). From the file start, packet 1..N is owned by * stream 1..N. Then must follow "packet_skip" value to find the stream next packet, as they are arbitrarily interleaved. + * We only need to follow the first stream, as all must contain the same number of samples. + * * XMA1/XMA2/WMAPRO data only differs in the packet headers. */ -static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int start_packet, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) { - int frames = 0, samples = 0, loop_start_frame = 0, loop_end_frame = 0, start_skip = 0, end_skip = 0; +static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) { + int frames = 0, samples = 0, loop_start_frame = 0, loop_end_frame = 0; - size_t first_frame_b, packet_skip_count = 0, frame_size_b, packet_size_b, header_size_b; + size_t first_frame_b, packet_skip_count, header_size_b, frame_size_b; off_t offset_b, packet_offset_b, frame_offset_b; size_t packet_size = bytes_per_packet; + size_t packet_size_b = packet_size * 8; off_t offset = msd->data_offset; off_t max_offset = msd->data_offset + msd->data_size; off_t stream_offset_b = msd->data_offset * 8; - offset += start_packet * packet_size; - packet_size_b = packet_size * 8; - /* read packets */ while (offset < max_offset) { offset_b = offset * 8; /* global offset in bits */ offset += packet_size; /* global offset in bytes */ /* packet header */ - if (msd->xma_version == 1) { /* XMA1 */ - //packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */ - //unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */ - first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */ - packet_skip_count = read_bitsBE_b(offset_b+21, 11, streamFile); /* packets to skip for next packet of this stream */ - header_size_b = 32; - } else if (msd->xma_version == 2) { /* XMA2 */ - //frame_count = read_bitsBE_b(offset_b+0, 6, streamFile); /* frames that begin in this packet */ - first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside this packet */ - //packet_metadata = read_bitsBE_b(offset_b+21, 3, streamFile); /* packet_metadata (always 1) */ - packet_skip_count = read_bitsBE_b(offset_b+24, 8, streamFile); /* packets to skip for next packet of this stream */ - header_size_b = 32; - } else { /* WMAPRO(v3) */ - //packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */ - //unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */ - first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */ - packet_skip_count = 0; /* xwma has no need to skip packets since it uses real multichannel audio */ - header_size_b = 4+2+bits_frame_size; /* variable-sized header */ + ms_audio_parse_header(streamFile, msd->xma_version, offset_b, bits_frame_size, &first_frame_b, &packet_skip_count, &header_size_b); + if (packet_skip_count > 0x7FF) { + continue; /* full skip */ } - - /* XMA2 packets with XMA1 RIFF (transmogrified), remove the packet metadata flag */ - if (msd->xma_version == 1 && (packet_skip_count & 0x700) == 0x100) { - //VGM_LOG("MS_SAMPLES: XMA1 transmogrified packet header at 0x%lx\n", (off_t)offset_b/8); - packet_skip_count &= ~0x100; - } - - /* full packet skip, no new frames start in this packet (prev frames can end here) */ - if (packet_skip_count == 0x7FF) { /* XMA1, 11b */ - VGM_LOG("MS_SAMPLES: XMA1 full packet_skip %i at 0x%"PRIx64"\n", packet_skip_count, (off64_t)offset_b/8); - packet_skip_count = 0; - continue; - } - else if (packet_skip_count == 0xFF) { /* XMA2, 8b*/ - VGM_LOG("MS_SAMPLES: XMA2 full packet_skip %i at 0x%"PRIx64"\n", packet_skip_count, (off64_t)offset_b/8); - packet_skip_count = 0; - continue; - } - offset += packet_size * (packet_skip_count); /* skip packets not owned by the first stream, since we only need samples from it */ - - /* unusual but not impossible, as the encoder can interleave packets in any way */ - VGM_ASSERT(packet_skip_count > 10, "MS_SAMPLES: found big packet skip %i at 0x%"PRIx64"\n", packet_skip_count, (off64_t)offset_b/8); - packet_offset_b = header_size_b + first_frame_b; + /* skip packets not owned by the first stream for next time */ + offset += packet_size * (packet_skip_count); /* read packet frames */ while (packet_offset_b < packet_size_b) { frame_offset_b = offset_b + packet_offset_b; /* in bits for aligment stuff */ - /* loops, later adjusted with subframe (seems correct vs tests) */ + /* frame loops, later adjusted with subframes (seems correct vs tests) */ if (msd->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == msd->loop_start_b) loop_start_frame = frames; if (msd->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == msd->loop_end_b) @@ -497,7 +534,6 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i /* frame header */ frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, streamFile); frame_offset_b += bits_frame_size; - //;VGM_LOG("MS_SAMPLES: frame_offset=0x%lx (0b%lx), frame_size=0x%x (0b%x)\n", (off_t)frame_offset_b/8,(off_t)frame_offset_b, frame_size_b/8, frame_size_b); /* stop when packet padding starts (0x00 for XMA1 or 0xFF in XMA2) */ if (frame_size_b == 0 || frame_size_b == (0xffffffff >> (32 - bits_frame_size))) { @@ -506,12 +542,77 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i packet_offset_b += frame_size_b; /* including header */ - /* find skips (info from FFmpeg) */ - if (channels_per_packet && (msd->xma_version == 1 || msd->xma_version == 2)) { - int flag; - int tilehdr_size = 15; //todo incorrect but usable for XMA, fix for WMAPro (complex calcs, see ffmpeg decode_tilehdr) + samples += samples_per_frame; + frames++; - frame_offset_b += tilehdr_size; + /* last bit in frame = more frames flag, end packet to avoid reading garbage in some cases + * (last frame spilling to other packets also has this flag, though it's ignored here) */ + if (packet_offset_b < packet_size_b && !read_bitsBE_b(offset_b + packet_offset_b - 1, 1, streamFile)) { + break; + } + } + } + + /* result */ + msd->num_samples = samples; + if (msd->loop_flag && loop_end_frame > loop_start_frame) { + msd->loop_start_sample = loop_start_frame * samples_per_frame + msd->loop_start_subframe * samples_per_subframe; + msd->loop_end_sample = loop_end_frame * samples_per_frame + (msd->loop_end_subframe) * samples_per_subframe; + } + + /* the above can't properly read skips for WMAPro ATM, but should fixed to 1 frame anyway */ + if (msd->xma_version == 0) { + msd->num_samples -= samples_per_frame; /* FFmpeg does skip this */ +#if 0 + msd->num_samples += (samples_per_frame / 2); /* but doesn't add extra samples */ +#endif + } +} + +/* simlar to the above but only gets skips */ +static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t data_offset, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int bits_frame_size, int *out_start_skip, int *out_end_skip) { + int start_skip = 0, end_skip = 0; + + size_t first_frame_b, packet_skip_count, header_size_b, frame_size_b; + off_t offset_b, packet_offset_b, frame_offset_b; + + size_t packet_size = bytes_per_packet; + size_t packet_size_b = packet_size * 8; + off_t offset = data_offset; + + /* read packet */ + { + offset_b = offset * 8; /* global offset in bits */ + offset += packet_size; /* global offset in bytes */ + + /* packet header */ + ms_audio_parse_header(streamFile, 2, offset_b, bits_frame_size, &first_frame_b, &packet_skip_count, &header_size_b); + if (packet_skip_count > 0x7FF) { + return; /* full skip */ + } + + packet_offset_b = header_size_b + first_frame_b; + + /* read packet frames */ + while (packet_offset_b < packet_size_b) { + frame_offset_b = offset_b + packet_offset_b; /* in bits for aligment stuff */ + + /* frame header */ + frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, streamFile); + frame_offset_b += bits_frame_size; + + /* stop when packet padding starts (0x00 for XMA1 or 0xFF in XMA2) */ + if (frame_size_b == 0 || frame_size_b == (0xffffffff >> (32 - bits_frame_size))) { + break; + } + packet_offset_b += frame_size_b; /* including header */ + + /* find skips (info from FFmpeg) */ + if (channels_per_packet && (xma_version == 1 || xma_version == 2)) { + int flag; + int len_tilehdr_size = 15; //todo incorrect but usable for XMA, fix for WMAPro (complex, see ffmpeg decode_tilehdr) + + frame_offset_b += len_tilehdr_size; /* ignore "postproc transform" */ if (channels_per_packet > 1) { @@ -526,7 +627,7 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i } } - /* get start/end skips to get the proper number of samples */ + /* get start/end skips to get the proper number of samples (both can be 0) */ flag = read_bitsBE_b(frame_offset_b, 1, streamFile); frame_offset_b += 1; if (flag) { @@ -535,14 +636,13 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i frame_offset_b += 1; if (flag) { int new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile); - VGM_LOG("MS_SAMPLES: start_skip %i at 0x%"PRIx64" (bit 0x%"PRIx64")\n", new_skip, (off64_t)frame_offset_b/8, (off64_t)frame_offset_b); - VGM_ASSERT(start_skip, "MS_SAMPLES: more than one start_skip (%i)\n", new_skip); //ignore, happens due to incorrect tilehdr_size + //;VGM_LOG("MS_SAMPLES: start_skip %i at 0x%x (bit 0x%x)\n", new_skip, (uint32_t)frame_offset_b/8, (uint32_t)frame_offset_b); frame_offset_b += 10; if (new_skip > samples_per_frame) /* from xmaencode */ new_skip = samples_per_frame; - if (start_skip==0) + if (start_skip==0) /* only use first skip */ start_skip = new_skip; } @@ -551,46 +651,25 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i frame_offset_b += 1; if (flag) { int new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile); - VGM_LOG("MS_SAMPLES: end_skip %i at 0x%"PRIx64" (bit 0x%"PRIx64")\n", new_skip, (off64_t)frame_offset_b/8, (off64_t)frame_offset_b); - VGM_ASSERT(end_skip, "MS_SAMPLES: more than one end_skip (%i)\n", new_skip);//ignore, happens due to incorrect tilehdr_size + //;VGM_LOG("MS_SAMPLES: end_skip %i at 0x%x (bit 0x%x)\n", new_skip, (uint32_t)frame_offset_b/8, (uint32_t)frame_offset_b); frame_offset_b += 10; if (new_skip > samples_per_frame) /* from xmaencode */ new_skip = samples_per_frame; - end_skip = new_skip; + end_skip = new_skip; /* always use last skip */ } } } - - - samples += samples_per_frame; - frames++; - - /* last bit in frame = more frames flag, end packet to avoid reading garbage in some cases - * (last frame spilling to other packets also has this flag, though it's ignored here) */ - if (packet_offset_b < packet_size_b && !read_bitsBE_b(offset_b + packet_offset_b - 1, 1, streamFile)) { - break; - } } } - - //todo FFmpeg seems to decode 1 subframe late vs xmaencode, and doesn't write 128 init samples, so skips are not useful ATM - //samples = samples + 128 - start_skip - end_skip; /* 128 init samples added by xmaencode */ - msd->num_samples = samples; - msd->skip_samples = start_skip; - - if (msd->loop_flag && loop_end_frame > loop_start_frame) { - msd->loop_start_sample = loop_start_frame * samples_per_frame + msd->loop_start_subframe * samples_per_subframe; - msd->loop_end_sample = loop_end_frame * samples_per_frame + msd->loop_end_subframe * samples_per_subframe; - - //todo maybe this is needed - //msd->loop_start_sample -= start_skip; - //msd->loop_end_sample -= start_skip; - } + /* output results */ + if (out_start_skip) *out_start_skip = start_skip; + if (out_end_skip) *out_end_skip = end_skip; } + static int wma_get_samples_per_frame(int version, int sample_rate, uint32_t decode_flags) { int frame_len_bits; @@ -618,33 +697,40 @@ static int wma_get_samples_per_frame(int version, int sample_rate, uint32_t deco return 1 << frame_len_bits; } -void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile) { - const int bytes_per_packet = 2048; - const int samples_per_frame = 512; - const int samples_per_subframe = 128; - +static int xma_get_channels_per_stream(STREAMFILE* streamFile, off_t chunk_offset, int channels) { int start_stream = 0; int channels_per_stream = 0; /* get from stream config (needed to find skips) */ - if (msd->chunk_offset) { - int format = read_16bitLE(msd->chunk_offset,streamFile); + if (chunk_offset) { + int format = read_16bitLE(chunk_offset,streamFile); if (format == 0x0165 || format == 0x6501) { /* XMA1 */ - channels_per_stream = read_8bit(msd->chunk_offset + 0x0C + 0x14*start_stream + 0x11,streamFile); + channels_per_stream = read_8bit(chunk_offset + 0x0C + 0x14*start_stream + 0x11,streamFile); } else if (format == 0x0166 || format == 0x6601) { /* new XMA2 */ - channels_per_stream = msd->channels > 1 ? 2 : 1; + channels_per_stream = channels > 1 ? 2 : 1; } else { /* old XMA2 */ - int version = read_8bit(msd->chunk_offset,streamFile); - channels_per_stream = read_8bit(msd->chunk_offset + 0x20 + (version==3 ? 0x00 : 0x08) + 0x4*start_stream + 0x00,streamFile); + int version = read_8bit(chunk_offset,streamFile); + channels_per_stream = read_8bit(chunk_offset + 0x20 + (version==3 ? 0x00 : 0x08) + 0x4*start_stream + 0x00,streamFile); } } - else if (msd->channels) { - channels_per_stream = msd->channels > 1 ? 2 : 1; + else if (channels) { + channels_per_stream = channels == 1 ? 1 : 2; /* default for XMA without RIFF chunks, most common */ } + if (channels_per_stream > 2) channels_per_stream = 0; - ms_audio_get_samples(msd, streamFile, start_stream, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, 15); + return channels_per_stream; +} + +void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile) { + const int bytes_per_packet = 2048; + const int samples_per_frame = 512; + const int samples_per_subframe = 128; + const int bits_frame_size = 15; + int channels_per_stream = xma_get_channels_per_stream(streamFile, msd->chunk_offset, msd->channels); + + ms_audio_get_samples(msd, streamFile, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); } void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) { @@ -653,7 +739,6 @@ void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ int samples_per_frame = 0; int samples_per_subframe = 0; int bits_frame_size = 0; - int start_packet = 0; int channels_per_stream = msd->channels; if (!(decode_flags & 0x40)) { @@ -663,10 +748,10 @@ void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ } samples_per_frame = wma_get_samples_per_frame(version, sample_rate, decode_flags); bits_frame_size = (int)floor(log(block_align) / log(2)) + 4; /* max bits needed to represent this block_align */ - samples_per_subframe = 0; /* not really needed WMAPro can't use loop subframes (complex subframe lengths) */ + samples_per_subframe = 0; /* not needed as WMAPro can't use loop subframes (complex subframe lengths) */ msd->xma_version = 0; /* signal it's not XMA */ - ms_audio_get_samples(msd, streamFile, start_packet, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); + ms_audio_get_samples(msd, streamFile, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); } void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) { @@ -703,9 +788,89 @@ void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ali } msd->num_samples = num_frames * samples_per_frame; + +#if 0 //todo apply once FFmpeg decode is ok + msd->num_samples += (samples_per_frame / 2); /* last IMDCT samples */ + msd->num_samples -= (samples_per_frame * 2); /* WMA default encoder delay */ +#endif } +/* XMA hell for precise looping and gapless support, fixes raw sample values from headers + * that don't count XMA's final subframe/encoder delay/encoder padding, and FFmpeg stuff. + * Configurable since different headers vary for maximum annoyance. */ +void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) { + const int bytes_per_packet = 2048; + const int samples_per_frame = 512; + const int samples_per_subframe = 128; + const int bits_frame_size = 15; + + int xma_version = 2; /* works ok even for XMA1 */ + int channels_per_stream = xma_get_channels_per_stream(streamFile, chunk_offset, vgmstream->channels); + off_t first_packet = stream_offset; + off_t last_packet = stream_offset + stream_size - bytes_per_packet; + int32_t start_skip = 0, end_skip = 0; + + if (stream_offset + stream_size > get_streamfile_size(streamFile)) { + VGM_LOG("XMA SKIPS: ignoring bad stream offset+size vs real size\n"); + return; + } + + /* find delay/padding values in the bitstream (should be safe even w/ multistreams + * as every stream repeats them). Theoretically every packet could contain skips, + * doesn't happen in practice though. */ + ms_audio_get_skips(streamFile, xma_version, first_packet, channels_per_stream, bytes_per_packet, samples_per_frame, bits_frame_size, &start_skip, NULL); + ms_audio_get_skips(streamFile, xma_version, last_packet, channels_per_stream, bytes_per_packet, samples_per_frame, bits_frame_size, NULL, &end_skip); + + //;VGM_LOG("XMA SKIPS: apply start=%i, end=%i\n", start_skip, end_skip); + VGM_ASSERT(start_skip < samples_per_frame, "XMA SKIPS: small start skip\n"); + + if (end_skip == 512) { /* most likely a read bug */ + VGM_LOG("XMA SKIPS: ignoring big end_skip\n"); + end_skip = 0; + } + + + /* apply XMA extra samples */ + if (fix_num_samples) { + vgmstream->num_samples += samples_per_subframe; /* final extra IMDCT samples */ + vgmstream->num_samples -= start_skip; /* first samples skipped at the beginning */ + vgmstream->num_samples -= end_skip; /* last samples discarded at the end */ + } + + /* from xma2encode tests this is correct (probably encodes/decodes loops considering all skips), ex.- + * full loop wav to xma makes start=384 (0 + ~512 delay - 128 padding), then xma to wav has "smpl" start=0 */ + if (fix_loop_samples && vgmstream->loop_flag) { + vgmstream->loop_start_sample += samples_per_subframe; + vgmstream->loop_start_sample -= start_skip; + vgmstream->loop_end_sample += samples_per_subframe; + vgmstream->loop_end_sample -= start_skip; + /* since loops are adjusted this shouldn't happen (often loop_end == num_samples after applying all) */ + if (vgmstream->loop_end_sample > vgmstream->num_samples && + vgmstream->loop_end_sample - end_skip <= vgmstream->loop_end_sample) { + VGM_LOG("XMA SAMPLES: adjusted loop end\n"); + vgmstream->loop_end_sample -= end_skip; + } + } + +#ifdef VGM_USE_FFMPEG + /* also fix FFmpeg, since we now know exact skips */ + { + ffmpeg_codec_data* data = vgmstream->codec_data; + + /* FFmpeg doesn't XMA apply encoder delay ATM so here we fix it manually. + * XMA delay is part if the bitstream and while theoretically it could be any + * value (and is honored by xmaencoder), basically it's always 512. + * + * Somehow also needs to skip 64 extra samples (looks like another FFmpeg bug + * where XMA outputs half a subframe samples late, WMAPRO isn't affected), + * which sometimes makes FFmpeg complain (=reads after end) but doesn't seem audible. */ + if (data->skipSamples == 0) { + ffmpeg_set_skip_samples(data, start_skip+64); + } + } +#endif +} /* ******************************************** */ /* HEADER PARSING */ @@ -718,7 +883,8 @@ void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * chan int32_t (*read_32bit)(off_t,STREAMFILE*) = be ? read_32bitBE : read_32bitLE; int i, num_streams, total_channels = 0; - if (read_16bit(chunk_offset+0x00,streamFile) != 0x165) return; + if (read_16bit(chunk_offset+0x00,streamFile) != 0x165) + return; num_streams = read_16bit(chunk_offset+0x08,streamFile); if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0xA,streamFile) > 0; @@ -737,71 +903,79 @@ void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * chan } /* Read values from a 'new' XMA2 RIFF "fmt" chunk (XMA2WAVEFORMATEX), starting from an offset *after* chunk type+size. - * Useful as custom X360 headers commonly have it lurking inside. Only the extra data, the first part is a normal WAVEFORMATEX. */ + * Useful as custom X360 headers commonly have it lurking inside. Only parses the extra data (before is a normal WAVEFORMATEX). */ void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * out_loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_loop_end_sample, int be) { int16_t (*read_16bit)(off_t,STREAMFILE*) = be ? read_16bitBE : read_16bitLE; int32_t (*read_32bit)(off_t,STREAMFILE*) = be ? read_32bitBE : read_32bitLE; int num_samples, loop_start_sample, loop_end_sample, loop_flag; - if (read_16bit(chunk_offset+0x00,streamFile) != 0x166) return; - /* up to extra data is a WAVEFORMATEX */ - if (read_16bit(chunk_offset+0x10,streamFile) < 0x22) return; /* expected extra data size */ + if (read_16bit(chunk_offset+0x00,streamFile) != 0x166) + return; + if (read_16bit(chunk_offset+0x10,streamFile) < 0x22) + return; /* expected extra data size */ - num_samples = read_32bit(chunk_offset+0x18,streamFile); /* max samples from all frames */ + num_samples = read_32bit(chunk_offset+0x18,streamFile); loop_start_sample = read_32bit(chunk_offset+0x28,streamFile); loop_end_sample = loop_start_sample + read_32bit(chunk_offset+0x2C,streamFile); loop_flag = (uint8_t)read_8bit(chunk_offset+0x30,streamFile) != 0; - /* num_samples isn't used by xmaencode, so final_num_samples = num_samples + setup_samples (128) - start_skip (~512) - end_skip (0..512) */ - /* loop values seem to be after applying skips, so loop_end wouldn't be higher than final_num_samples */ + /* may need loop end +1, though some header doesn't need it (ex.- Sonic and Sega All Stars Racing .str) */ /* flag rarely set, use loop_end as marker */ if (!loop_flag) { loop_flag = loop_end_sample > 0; - /* loop_end_sample - 128 + start_skip + end_skip = num_samples, use approx */ - if (loop_start_sample == 384 && loop_end_sample - 128 + 512 + 512 >= num_samples) { + /* some XMA incorrectly do full loops for every song/jingle [Shadows of the Damned (X360)] */ + if ((loop_start_sample + 128 - 512) == 0 && (loop_end_sample + 128 - 512) + 256 >= (num_samples + 128 - 512)) { VGM_LOG("XMA2 PARSE: disabling full loop\n"); - loop_flag = 0; /* some XMA have full loop set without loop flag and shouldn't loop */ + loop_flag = 0; } } + /* samples are "raw" values, must be fixed externally (see xma_fix_raw_samples) */ if(out_num_samples) *out_num_samples = num_samples; if(out_loop_start_sample) *out_loop_start_sample = loop_start_sample; if(out_loop_end_sample) *out_loop_end_sample = loop_end_sample; if(out_loop_flag) *out_loop_flag = loop_flag; - /* play_begin+end = pcm_samples in original sample rate (not usable when resampled = looped) */ + /* play_begin+end = pcm_samples in original sample rate (not usable as file may be resampled) */ /* int32_t play_begin_sample = read_32bit(xma->chunk_offset+0x20,streamFile); */ /* int32_t play_end_sample = play_begin_sample + read_32bit(xma->chunk_offset+0x24,streamFile); */ } /* Read values from an 'old' XMA2 RIFF "XMA2" chunk (XMA2WAVEFORMAT), starting from an offset *after* chunk type+size. * Useful as custom X360 headers commonly have it lurking inside. */ -void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample) { +void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * out_channels, int * out_sample_rate, int * out_loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_loop_end_sample) { int32_t (*read_32bit)(off_t,STREAMFILE*) = read_32bitBE; /* XMA2WAVEFORMAT is always big endian */ - int i, xma2_chunk_version, num_streams, total_channels = 0; - off_t off; + int i, xma2_chunk_version, num_streams; + int channels, sample_rate, loop_flag, num_samples, loop_start_sample, loop_end_sample; + off_t offset; xma2_chunk_version = read_8bit(chunk_offset+0x00,streamFile); num_streams = read_8bit(chunk_offset+0x01,streamFile); - if(loop_start_sample) *loop_start_sample = read_32bit(chunk_offset+0x04,streamFile); - if(loop_end_sample) *loop_end_sample = read_32bit(chunk_offset+0x08,streamFile); - if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0x03,streamFile) > 0 /* rarely not set, encoder default */ - || read_32bit(chunk_offset+0x08,streamFile); /* loop_end_sample */ - if(sample_rate) *sample_rate = read_32bit(chunk_offset+0x0c,streamFile);; + loop_start_sample = read_32bit(chunk_offset+0x04,streamFile); + loop_end_sample = read_32bit(chunk_offset+0x08,streamFile); + loop_flag = (uint8_t)read_8bit(chunk_offset+0x03,streamFile) > 0 || loop_end_sample; /* rarely not set, encoder default */ + sample_rate = read_32bit(chunk_offset+0x0c,streamFile); + /* may need loop end +1 */ - off = xma2_chunk_version == 3 ? 0x14 : 0x1C; - if(num_samples) *num_samples = read_32bit(chunk_offset+off,streamFile); - /*xma->pcm_samples = read_32bitBE(xma->chunk_offset+off+0x04,streamFile)*/ - /* num_samples is the max samples in the file (apparently not including encoder delay) */ - /* pcm_samples are original WAV's; not current since samples and sample rate may be adjusted for looping purposes */ + offset = xma2_chunk_version == 3 ? 0x14 : 0x1C; + num_samples = read_32bit(chunk_offset+offset+0x00,streamFile); + /* pcm_samples in original sample rate (not usable as file may be resampled) */ + /* pcm_samples = read_32bitBE(chunk_offset+offset+0x04,streamFile)*/ - off = xma2_chunk_version == 3 ? 0x20 : 0x28; - /* channels is the sum of all streams */ + offset = xma2_chunk_version == 3 ? 0x20 : 0x28; + channels = 0; /* channels is the sum of all streams */ for (i = 0; i < num_streams; i++) { - total_channels += read_8bit(chunk_offset+off+i*0x04,streamFile); + channels += read_8bit(chunk_offset+offset+i*0x04,streamFile); } - if (channels) *channels = total_channels; + + /* samples are "raw" values, must be fixed externally (see xma_fix_raw_samples) */ + if(out_channels) *out_channels = channels; + if(out_sample_rate) *out_sample_rate = sample_rate; + if(out_num_samples) *out_num_samples = num_samples; + if(out_loop_start_sample) *out_loop_start_sample = loop_start_sample; + if(out_loop_end_sample) *out_loop_end_sample = loop_end_sample; + if(out_loop_flag) *out_loop_flag = loop_flag; } /* manually read from "fact" chunk */ @@ -983,3 +1157,31 @@ int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) { else return w_bits_msf(ob,num_bits,value); } + +/* ******************************************** */ +/* CUSTOM STREAMFILES */ +/* ******************************************** */ + +STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* extension) { + STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; + + new_streamFile = open_wrap_streamfile(streamFile); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + if (extension) { + new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,extension); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + } + + return temp_streamFile; + +fail: + close_streamfile(temp_streamFile); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c index f037d1834..9178d3ae1 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c @@ -30,7 +30,7 @@ static const int EA_XA_TABLE[20] = { }; /* EA XA v2 (always mono); like ea_xa_int but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */ -void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { +void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { uint8_t frame_info; int32_t coef1, coef2; int i, sample_count, shift; @@ -83,6 +83,106 @@ void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac } } +#if 0 +/* later PC games use float math, though in the end sounds basically the same (decompiled from various exes) */ +static const double XA_K0[16] = { 0.0, 0.9375, 1.796875, 1.53125 }; +static const double XA_K1[16] = { 0.0, 0.0, -0.8125, -0.859375 }; +/* code uses look-up table but it's be equivalent to: + * (double)((nibble << 28) >> (shift + 8) >> 8) or (double)(signed_nibble << (12 - shift)) */ +static const uint32_t FLOAT_TABLE_INT[256] = { + 0x00000000,0x45800000,0x46000000,0x46400000,0x46800000,0x46A00000,0x46C00000,0x46E00000, + 0xC7000000,0xC6E00000,0xC6C00000,0xC6A00000,0xC6800000,0xC6400000,0xC6000000,0xC5800000, + 0x00000000,0x45000000,0x45800000,0x45C00000,0x46000000,0x46200000,0x46400000,0x46600000, + 0xC6800000,0xC6600000,0xC6400000,0xC6200000,0xC6000000,0xC5C00000,0xC5800000,0xC5000000, + 0x00000000,0x44800000,0x45000000,0x45400000,0x45800000,0x45A00000,0x45C00000,0x45E00000, + 0xC6000000,0xC5E00000,0xC5C00000,0xC5A00000,0xC5800000,0xC5400000,0xC5000000,0xC4800000, + 0x00000000,0x44000000,0x44800000,0x44C00000,0x45000000,0x45200000,0x45400000,0x45600000, + 0xC5800000,0xC5600000,0xC5400000,0xC5200000,0xC5000000,0xC4C00000,0xC4800000,0xC4000000, + 0x00000000,0x43800000,0x44000000,0x44400000,0x44800000,0x44A00000,0x44C00000,0x44E00000, + 0xC5000000,0xC4E00000,0xC4C00000,0xC4A00000,0xC4800000,0xC4400000,0xC4000000,0xC3800000, + 0x00000000,0x43000000,0x43800000,0x43C00000,0x44000000,0x44200000,0x44400000,0x44600000, + 0xC4800000,0xC4600000,0xC4400000,0xC4200000,0xC4000000,0xC3C00000,0xC3800000,0xC3000000, + 0x00000000,0x42800000,0x43000000,0x43400000,0x43800000,0x43A00000,0x43C00000,0x43E00000, + 0xC4000000,0xC3E00000,0xC3C00000,0xC3A00000,0xC3800000,0xC3400000,0xC3000000,0xC2800000, + 0x00000000,0x42000000,0x42800000,0x42C00000,0x43000000,0x43200000,0x43400000,0x43600000, + 0xC3800000,0xC3600000,0xC3400000,0xC3200000,0xC3000000,0xC2C00000,0xC2800000,0xC2000000, + 0x00000000,0x41800000,0x42000000,0x42400000,0x42800000,0x42A00000,0x42C00000,0x42E00000, + 0xC3000000,0xC2E00000,0xC2C00000,0xC2A00000,0xC2800000,0xC2400000,0xC2000000,0xC1800000, + 0x00000000,0x41000000,0x41800000,0x41C00000,0x42000000,0x42200000,0x42400000,0x42600000, + 0xC2800000,0xC2600000,0xC2400000,0xC2200000,0xC2000000,0xC1C00000,0xC1800000,0xC1000000, + 0x00000000,0x40800000,0x41000000,0x41400000,0x41800000,0x41A00000,0x41C00000,0x41E00000, + 0xC2000000,0xC1E00000,0xC1C00000,0xC1A00000,0xC1800000,0xC1400000,0xC1000000,0xC0800000, + 0x00000000,0x40000000,0x40800000,0x40C00000,0x41000000,0x41200000,0x41400000,0x41600000, + 0xC1800000,0xC1600000,0xC1400000,0xC1200000,0xC1000000,0xC0C00000,0xC0800000,0xC0000000, + 0x00000000,0x3F800000,0x40000000,0x40400000,0x40800000,0x40A00000,0x40C00000,0x40E00000, + 0xC1000000,0xC0E00000,0xC0C00000,0xC0A00000,0xC0800000,0xC0400000,0xC0000000,0xBF800000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +}; +static const float *FLOAT_TABLE = (const float *)FLOAT_TABLE_INT; + +void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + uint8_t frame_info; + int i, sample_count, shift; + + int pcm_frame_size = 0x01 + 2*0x02 + 28*0x02; + int xa_frame_size = 0x0f; + int frame_samples = 28; + first_sample = first_sample % frame_samples; + + /* header */ + frame_info = read_8bit(stream->offset,stream->streamfile); + + if (frame_info == 0xEE) { /* PCM frame (used in later revisions), samples always BE */ + stream->adpcm_history1_double = read_16bitBE(stream->offset + 0x01 + 0x00,stream->streamfile); + stream->adpcm_history2_double = read_16bitBE(stream->offset + 0x01 + 0x02,stream->streamfile); + + for (i=first_sample,sample_count=0; ioffset + 0x01 + 2*0x02 + i*0x02,stream->streamfile); + } + + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += pcm_frame_size; + } + else { /* ADPCM frame */ + double coef1, coef2, hist1, hist2, new_sample; + + coef1 = XA_K0[(frame_info >> 4)]; + coef2 = XA_K1[(frame_info >> 4)]; + shift = (frame_info & 0x0F) + 8;// << 4; + hist1 = stream->adpcm_history1_double; + hist2 = stream->adpcm_history2_double; + + for (i=first_sample,sample_count=0; ioffset + 0x01 + i/2); + int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */ + + sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile); + sample_nibble = (sample_byte >> nibble_shift) & 0x0F; + new_sample = (double)FLOAT_TABLE[sample_nibble + shift]; + new_sample = new_sample + coef1 * hist1 + coef2 * hist2; + + outbuf[sample_count] = clamp16((int)new_sample); + hist2 = hist1; + hist1 = new_sample; + } + + stream->adpcm_history1_double = hist1; + stream->adpcm_history2_double = hist2; + + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += xa_frame_size; + } +} +#endif + /* EA XA v1 stereo */ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { uint8_t frame_info; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c index aa9822494..148bfff88 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c @@ -9,8 +9,9 @@ static const int EA_XA_TABLE[20] = { 0, -1, -3, -4 }; -/* EA-XAS, evolution of EA-XA and cousin of MTA2. Layout: blocks of 0x4c per channel (128 samples), - * divided into 4 headers + 4 vertical groups of 15 bytes (for parallelism?). +/* EA-XAS, evolution of EA-XA and cousin of MTA2. From FFmpeg (general info) + MTA2 (layout) + EA-XA (decoding) + * + * Layout: blocks of 0x4c per channel (128 samples), divided into 4 headers + 4 vertical groups of 15 bytes (for parallelism?). * To simplify, always decodes the block and discards unneeded samples, so doesn't use external hist. */ void decode_ea_xas(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { int group, row, i; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c index 2f6b833d5..90c2b5b98 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c @@ -29,35 +29,32 @@ static void g_init_ffmpeg() { } /* converts codec's samples (can be in any format, ex. Ogg's float32) to PCM16 */ -static void convert_audio(sample *outbuf, const uint8_t *inbuf, int sampleCount, int bitsPerSample, int floatingPoint) { +static void convert_audio_pcm16(sample *outbuf, const uint8_t *inbuf, int fullSampleCount, int bitsPerSample, int floatingPoint) { int s; switch (bitsPerSample) { - case 8: - { - for (s = 0; s < sampleCount; ++s) { + case 8: { + for (s = 0; s < fullSampleCount; s++) { *outbuf++ = ((int)(*(inbuf++))-0x80) << 8; } - } break; - case 16: - { + } + case 16: { int16_t *s16 = (int16_t *)inbuf; - for (s = 0; s < sampleCount; ++s) { + for (s = 0; s < fullSampleCount; s++) { *outbuf++ = *(s16++); } - } break; - case 32: - { + } + case 32: { if (!floatingPoint) { int32_t *s32 = (int32_t *)inbuf; - for (s = 0; s < sampleCount; ++s) { + for (s = 0; s < fullSampleCount; s++) { *outbuf++ = (*(s32++)) >> 16; } } else { float *s32 = (float *)inbuf; - for (s = 0; s < sampleCount; ++s) { + for (s = 0; s < fullSampleCount; s++) { float sample = *s32++; int s16 = (int)(sample * 32768.0f); if ((unsigned)(s16 + 0x8000) & 0xFFFF0000) { @@ -66,13 +63,12 @@ static void convert_audio(sample *outbuf, const uint8_t *inbuf, int sampleCount, *outbuf++ = s16; } } - } break; - case 64: - { + } + case 64: { if (floatingPoint) { double *s64 = (double *)inbuf; - for (s = 0; s < sampleCount; ++s) { + for (s = 0; s < fullSampleCount; s++) { double sample = *s64++; int s16 = (int)(sample * 32768.0f); if ((unsigned)(s16 + 0x8000) & 0xFFFF0000) { @@ -81,8 +77,8 @@ static void convert_audio(sample *outbuf, const uint8_t *inbuf, int sampleCount, *outbuf++ = s16; } } - } break; + } } } @@ -97,30 +93,31 @@ static void convert_audio(sample *outbuf, const uint8_t *inbuf, int sampleCount, * Fortunately seek_frame_generic can use an index to find the correct position. This function reads the * first frame/packet and sets up index to timestamp 0. This ensures faulty demuxers will seek to 0 correctly. * Some formats may not seek to 0 even with this, though. - * - * todo: some formats don't work with the current index values */ static int init_seek(ffmpeg_codec_data * data) { int ret, ts_index, found_first = 0; - int64_t ts = 0; - int64_t pos = 0; /* offset */ - int size = 0; /* coded size */ - int distance = 0; /* always? */ + int64_t ts = 0; /* seek timestamp */ + int64_t pos = 0; /* data offset */ + int size = 0; /* data size (block align) */ + int distance = 0; /* always 0 ("duration") */ - AVStream * stream; - AVPacket * pkt; + AVStream * stream = data->formatCtx->streams[data->streamIndex]; + AVPacket * pkt = data->lastReadPacket; - stream = data->formatCtx->streams[data->streamIndex]; - pkt = data->lastReadPacket; /* read_seek shouldn't need this index, but direct access to FFmpeg's internals is no good */ /* if (data->formatCtx->iformat->read_seek || data->formatCtx->iformat->read_seek2) return 0; */ - /* some formats already have a proper index (e.g. M4A) */ - ts_index = av_index_search_timestamp(stream, ts, AVSEEK_FLAG_ANY); - if (ts_index>=0) + /* A few formats may have a proper index (e.g. CAF/MP4/MPC/ASF/WAV/XWMA/FLAC/MP3), but some don't + * work with our custom index (CAF/MPC/MP4) and must skip it. Most formats need flag AVSEEK_FLAG_ANY, + * while XWMA (with index 0 not pointing to ts 0) needs AVSEEK_FLAG_BACKWARD to seek properly, but it + * makes OGG use the index and seek wrong instead. So for XWMA we forcefully remove the index on it's own meta. */ + ts_index = av_index_search_timestamp(stream, 0, /*AVSEEK_FLAG_BACKWARD |*/ AVSEEK_FLAG_ANY); + if (ts_index >= 0) { + VGM_LOG("FFMPEG: index found for init_seek\n"); goto test_seek; + } /* find the first + second packets to get pos/size */ @@ -132,7 +129,7 @@ static int init_seek(ffmpeg_codec_data * data) { if (pkt->stream_index != data->streamIndex) continue; /* ignore non-selected streams */ - if (!found_first) { /* first found */ + if (!found_first) { found_first = 1; pos = pkt->pos; ts = pkt->dts; @@ -144,28 +141,28 @@ static int init_seek(ffmpeg_codec_data * data) { } if (!found_first) goto fail; - /* in rare cases there is only one packet */ - /* if (size == 0) { size = data_end - pos; } */ /* no easy way to know, ignore (most formats don's need size) */ + //if (size == 0) size = data_end - pos; /* no easy way to know, ignore (most formats don's need size) */ - /* some formats (XMA1) don't seem to have packet.dts, pretend it's 0 */ + /* some formats don't seem to have packet.dts, pretend it's 0 */ if (ts == INT64_MIN) ts = 0; - /* Some streams start with negative DTS (observed in Ogg). For Ogg seeking to negative or 0 doesn't alter the output. - * It does seem seeking before decoding alters a bunch of (inaudible) +-1 lower bytes though. */ + /* Some streams start with negative DTS (OGG/OPUS). For Ogg seeking to negative or 0 doesn't seem different. + * It does seem seeking before decoding alters a bunch of (inaudible) +-1 lower bytes though. + * Output looks correct (encoder delay, num_samples, etc) compared to libvorbis's output. */ VGM_ASSERT(ts != 0, "FFMPEG: negative start_ts (%li)\n", (long)ts); if (ts != 0) ts = 0; + /* add index 0 */ ret = av_add_index_entry(stream, pos, ts, size, distance, AVINDEX_KEYFRAME); if ( ret < 0 ) return ret; - test_seek: - /* seek to 0 test / move back to beginning, since we just consumed packets */ + /* seek to 0 test + move back to beginning, since we just consumed packets */ ret = avformat_seek_file(data->formatCtx, data->streamIndex, ts, ts, ts, AVSEEK_FLAG_ANY); if ( ret < 0 ) return ret; /* we can't even reset_vgmstream the file */ @@ -275,6 +272,10 @@ ffmpeg_codec_data * init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, u return init_ffmpeg_header_offset(streamFile, NULL,0, start,size); } +ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) { + return init_ffmpeg_header_offset_subsong(streamFile, header, header_size, start, size, 0); +} + /** * Manually init FFmpeg, from a fake header / offset. * @@ -282,13 +283,12 @@ ffmpeg_codec_data * init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, u * This header will be seamlessly inserted before 'start' offset, and total filesize will be 'header_size' + 'size'. * The header buffer will be copied and memory-managed internally. * NULL header can used given if the stream has internal data recognized by FFmpeg at offset. - * Stream index can be passed to FFmpeg in the streamFile, if the format has multiple streams (1=first). + * Stream index can be passed if the file has multiple audio streams that FFmpeg can demux (1=first). */ -ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) { +ffmpeg_codec_data * init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong) { char filename[PATH_LIMIT]; ffmpeg_codec_data * data; int errcode, i; - int targetSubsong = streamFile->stream_index; int streamIndex, streamCount; AVStream *stream; @@ -355,7 +355,7 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * streamCount++; /* select Nth audio stream if specified, or first one */ - if (streamIndex < 0 || (targetSubsong > 0 && streamCount == targetSubsong)) { + if (streamIndex < 0 || (target_subsong > 0 && streamCount == target_subsong)) { codecPar = stream->codecpar; streamIndex = i; } @@ -364,7 +364,7 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * if (i != streamIndex) stream->discard = AVDISCARD_ALL; /* disable demuxing for other streams */ } - if (streamCount < targetSubsong) goto fail; + if (streamCount < target_subsong) goto fail; if (streamIndex < 0 || !codecPar) goto fail; data->streamIndex = streamIndex; @@ -459,7 +459,25 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * /* setup decent seeking for faulty formats */ errcode = init_seek(data); - if (errcode < 0) goto fail; + if (errcode < 0) { + VGM_LOG("FFMPEG: can't init_seek\n"); + goto fail; + } + + /* check ways to skip encoder delay/padding, for debugging purposes (some may be old/unused/encoder only/etc) */ + VGM_ASSERT(data->codecCtx->delay > 0, "FFMPEG: delay %i\n", (int)data->codecCtx->delay);//delay: OPUS + //VGM_ASSERT(data->codecCtx->internal->skip_samples > 0, ...); /* for codec use, not accessible */ + VGM_ASSERT(stream->codecpar->initial_padding > 0, "FFMPEG: initial_padding %i\n", (int)stream->codecpar->initial_padding);//delay: OPUS + VGM_ASSERT(stream->codecpar->trailing_padding > 0, "FFMPEG: trailing_padding %i\n", (int)stream->codecpar->trailing_padding); + VGM_ASSERT(stream->codecpar->seek_preroll > 0, "FFMPEG: seek_preroll %i\n", (int)stream->codecpar->seek_preroll);//seek delay: OPUS + VGM_ASSERT(stream->skip_samples > 0, "FFMPEG: skip_samples %i\n", (int)stream->skip_samples); //delay: MP4 + VGM_ASSERT(stream->start_skip_samples > 0, "FFMPEG: start_skip_samples %i\n", (int)stream->start_skip_samples); //delay: MP3 + VGM_ASSERT(stream->first_discard_sample > 0, "FFMPEG: first_discard_sample %i\n", (int)stream->first_discard_sample); //padding: MP3 + VGM_ASSERT(stream->last_discard_sample > 0, "FFMPEG: last_discard_sample %i\n", (int)stream->last_discard_sample); //padding: MP3 + /* also negative timestamp for formats like OGG/OPUS */ + /* not using it: BINK, FLAC, ATRAC3, XMA, MPC, WMA (may use internal skip samples) */ + //todo: double check Opus behavior + /* expose start samples to be skipped (encoder delay, usually added by MDCT-based encoders like AAC/MP3/ATRAC3/XMA/etc) * get after init_seek because some demuxers like AAC only fill skip_samples for the first packet */ @@ -478,173 +496,178 @@ fail: /* decode samples of any kind of FFmpeg format */ void decode_ffmpeg(VGMSTREAM *vgmstream, sample * outbuf, int32_t samples_to_do, int channels) { - ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; - - int bytesPerSample, bytesPerFrame, frameSize; - int bytesToRead, bytesRead; - - uint8_t *targetBuf; - - AVFormatContext *formatCtx; - AVCodecContext *codecCtx; - AVPacket *lastReadPacket; - AVFrame *lastDecodedFrame; - - int bytesConsumedFromDecodedFrame; - - int readNextPacket, endOfStream, endOfAudio; - int framesReadNow; - + ffmpeg_codec_data *data = vgmstream->codec_data; + int samplesReadNow; + //todo use either channels / data->channels / codecCtx->channels - /* ignore decode attempts at EOF */ - if (data->endOfStream || data->endOfAudio) { + AVFormatContext *formatCtx = data->formatCtx; + AVCodecContext *codecCtx = data->codecCtx; + AVPacket *packet = data->lastReadPacket; + AVFrame *frame = data->lastDecodedFrame; + int planar = av_sample_fmt_is_planar(data->codecCtx->sample_fmt); + + int readNextPacket = data->readNextPacket; + int endOfStream = data->endOfStream; + int endOfAudio = data->endOfAudio; + int bytesConsumedFromDecodedFrame = data->bytesConsumedFromDecodedFrame; + + int bytesPerSample = data->bitsPerSample / 8; + int bytesRead, bytesToRead; + + + /* ignore once file is done (but not at endOfStream as FFmpeg can still output samples until endOfAudio) */ + if (/*endOfStream ||*/ endOfAudio) { + VGM_LOG("FFMPEG: decode after end of audio\n"); memset(outbuf, 0, samples_to_do * channels * sizeof(sample)); return; } - - bytesPerSample = data->bitsPerSample / 8; - bytesPerFrame = channels * bytesPerSample; - frameSize = data->channels * bytesPerSample; - - bytesToRead = samples_to_do * frameSize; + bytesRead = 0; - - targetBuf = data->sampleBuffer; - memset(targetBuf, 0, bytesToRead); - - formatCtx = data->formatCtx; - codecCtx = data->codecCtx; - lastReadPacket = data->lastReadPacket; - lastDecodedFrame = data->lastDecodedFrame; - - bytesConsumedFromDecodedFrame = data->bytesConsumedFromDecodedFrame; - - readNextPacket = data->readNextPacket; - endOfStream = data->endOfStream; - endOfAudio = data->endOfAudio; + bytesToRead = samples_to_do * (bytesPerSample * codecCtx->channels); - /* keep reading and decoding packets until the requested number of samples (in bytes) */ + + /* keep reading and decoding packets until the requested number of samples (in bytes for FFmpeg calcs) */ while (bytesRead < bytesToRead) { - int planeSize, planar, dataSize, toConsume, errcode; + int dataSize, toConsume, errcode; - /* size of previous frame */ - dataSize = av_samples_get_buffer_size(&planeSize, codecCtx->channels, lastDecodedFrame->nb_samples, codecCtx->sample_fmt, 1); + /* get sample data size from current frame (dataSize will be < 0 when nb_samples = 0) */ + dataSize = av_samples_get_buffer_size(NULL, codecCtx->channels, frame->nb_samples, codecCtx->sample_fmt, 1); if (dataSize < 0) dataSize = 0; - - /* read new frame + packets when requested */ + + /* read new data packet when requested */ while (readNextPacket && !endOfAudio) { if (!endOfStream) { - av_packet_unref(lastReadPacket); - if ((errcode = av_read_frame(formatCtx, lastReadPacket)) < 0) { + /* reset old packet */ + av_packet_unref(packet); + + /* get compressed data from demuxer into packet */ + errcode = av_read_frame(formatCtx, packet); + if (errcode < 0) { if (errcode == AVERROR_EOF) { - endOfStream = 1; + endOfStream = 1; /* no more data, but may still output samples */ } - if (formatCtx->pb && formatCtx->pb->error) + else { + VGM_LOG("FFMPEG: av_read_frame errcode %i\n", errcode); + } + + if (formatCtx->pb && formatCtx->pb->error) { break; + } } - if (lastReadPacket->stream_index != data->streamIndex) + + if (packet->stream_index != data->streamIndex) continue; /* ignore non-selected streams */ } - - /* send compressed packet to decoder (NULL at EOF to "drain") */ - if ((errcode = avcodec_send_packet(codecCtx, endOfStream ? NULL : lastReadPacket)) < 0) { + + /* send compressed data to decoder in packet (NULL at EOF to "drain") */ + errcode = avcodec_send_packet(codecCtx, endOfStream ? NULL : packet); + if (errcode < 0) { if (errcode != AVERROR(EAGAIN)) { + VGM_LOG("FFMPEG: avcodec_send_packet errcode %i\n", errcode); goto end; } } - readNextPacket = 0; + readNextPacket = 0; /* got compressed data */ } - - /* decode packets into frame (checking if we have bytes to consume from previous frame) */ + + /* decode packet into frame's sample data (if we don't have bytes to consume from previous frame) */ if (dataSize <= bytesConsumedFromDecodedFrame) { - if (endOfStream && endOfAudio) + if (endOfAudio) { break; - + } + bytesConsumedFromDecodedFrame = 0; - - /* receive uncompressed data from decoder */ - if ((errcode = avcodec_receive_frame(codecCtx, lastDecodedFrame)) < 0) { + + /* receive uncompressed sample data from decoder in frame */ + errcode = avcodec_receive_frame(codecCtx, frame); + if (errcode < 0) { if (errcode == AVERROR_EOF) { - endOfAudio = 1; + endOfAudio = 1; /* no more samples, file is fully decoded */ break; } else if (errcode == AVERROR(EAGAIN)) { - readNextPacket = 1; + readNextPacket = 1; /* request more compressed data */ continue; } else { + VGM_LOG("FFMPEG: avcodec_receive_frame errcode %i\n", errcode); goto end; } } - - /* size of current frame */ - dataSize = av_samples_get_buffer_size(&planeSize, codecCtx->channels, lastDecodedFrame->nb_samples, codecCtx->sample_fmt, 1); + + /* get sample data size of current frame */ + dataSize = av_samples_get_buffer_size(NULL, codecCtx->channels, frame->nb_samples, codecCtx->sample_fmt, 1); if (dataSize < 0) dataSize = 0; } - + toConsume = FFMIN((dataSize - bytesConsumedFromDecodedFrame), (bytesToRead - bytesRead)); - + + /* discard decoded frame if needed (fully or partially) */ if (data->samplesToDiscard) { - int samplesDataSize = dataSize / bytesPerFrame; + int samplesDataSize = dataSize / (bytesPerSample * channels); if (data->samplesToDiscard >= samplesDataSize) { /* discard all of the frame's samples and continue to the next */ - bytesConsumedFromDecodedFrame = dataSize; data->samplesToDiscard -= samplesDataSize; - continue; } else { /* discard part of the frame and copy the rest below */ - int bytesToDiscard = data->samplesToDiscard * bytesPerFrame; + int bytesToDiscard = data->samplesToDiscard * (bytesPerSample * channels); int dataSizeLeft = dataSize - bytesToDiscard; bytesConsumedFromDecodedFrame += bytesToDiscard; data->samplesToDiscard = 0; if (toConsume > dataSizeLeft) - toConsume = dataSizeLeft; /* consume at most dataSize left */ + toConsume = dataSizeLeft; } } - /* copy decoded frame to buffer (mux channels if needed) */ - planar = av_sample_fmt_is_planar(codecCtx->sample_fmt); - if (!planar || channels == 1) { - memmove(targetBuf + bytesRead, (lastDecodedFrame->data[0] + bytesConsumedFromDecodedFrame), toConsume); + + /* copy decoded sample data to buffer */ + if (!planar || channels == 1) { /* 1 sample per channel, already mixed */ + memmove(data->sampleBuffer + bytesRead, (frame->data[0] + bytesConsumedFromDecodedFrame), toConsume); } - else { - uint8_t * out = (uint8_t *) targetBuf + bytesRead; + else { /* N samples per channel, mix to 1 sample per channel */ + uint8_t * out = (uint8_t *) data->sampleBuffer + bytesRead; int bytesConsumedPerPlane = bytesConsumedFromDecodedFrame / channels; int toConsumePerPlane = toConsume / channels; int s, ch; for (s = 0; s < toConsumePerPlane; s += bytesPerSample) { for (ch = 0; ch < channels; ++ch) { - memcpy(out, lastDecodedFrame->extended_data[ch] + bytesConsumedPerPlane + s, bytesPerSample); + memcpy(out, frame->extended_data[ch] + bytesConsumedPerPlane + s, bytesPerSample); out += bytesPerSample; } } } - + /* consume */ bytesConsumedFromDecodedFrame += toConsume; bytesRead += toConsume; } - + + end: - framesReadNow = bytesRead / frameSize; - - /* Convert the audio */ - convert_audio(outbuf, data->sampleBuffer, framesReadNow * channels, data->bitsPerSample, data->floatingPoint); - - /* Output the state back to the structure */ - data->bytesConsumedFromDecodedFrame = bytesConsumedFromDecodedFrame; + /* convert native sample format into PCM16 outbuf */ + samplesReadNow = bytesRead / (bytesPerSample * channels); + convert_audio_pcm16(outbuf, data->sampleBuffer, samplesReadNow * channels, data->bitsPerSample, data->floatingPoint); + + /* clean buffer when requested more samples than possible */ + if (endOfAudio && samplesReadNow < samples_to_do) { + VGM_LOG("FFMPEG: decode after end of audio %i samples\n", (samples_to_do - samplesReadNow)); + memset(outbuf + (samplesReadNow * channels), 0, (samples_to_do - samplesReadNow) * channels * sizeof(sample)); + } + + /* copy state back */ data->readNextPacket = readNextPacket; data->endOfStream = endOfStream; data->endOfAudio = endOfAudio; + data->bytesConsumedFromDecodedFrame = bytesConsumedFromDecodedFrame; } @@ -682,7 +705,8 @@ void reset_ffmpeg(VGMSTREAM *vgmstream) { void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample) { ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; int64_t ts; - if (!data) return; + if (!data) + return; /* Start from 0 and discard samples until loop_start (slower but not too noticeable). * Due to various FFmpeg quirks seeking to a sample is erratic in many formats (would need extra steps). */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c index 0815ecfae..92e0513d4 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c @@ -16,8 +16,9 @@ static size_t make_oggs_first(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate); static size_t make_oggs_page(uint8_t * buf, int buf_size, size_t data_size, int page_sequence, int granule); static size_t opus_get_packet_samples(const uint8_t * buf, int len); +static size_t get_xopus_packet_size(int packet, STREAMFILE * streamfile); -typedef enum { OPUS_SWITCH, OPUS_UE4 } opus_type_t; +typedef enum { OPUS_SWITCH, OPUS_UE4, OPUS_EA, OPUS_X } opus_type_t; typedef struct { /* config */ opus_type_t type; @@ -100,6 +101,14 @@ static size_t opus_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, data_size = (uint16_t)read_16bitLE(data->physical_offset, streamfile); skip_size = 0x02; break; + case OPUS_EA: + data_size = (uint16_t)read_16bitBE(data->physical_offset, streamfile); + skip_size = 0x02; + break; + case OPUS_X: + data_size = get_xopus_packet_size(data->sequence - 2, streamfile); + skip_size = 0; + break; default: return 0; } @@ -110,7 +119,7 @@ static size_t opus_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, data->page_size = oggs_size + data_size; if (data->page_size > sizeof(data->page_buffer)) { /* happens on bad reads/EOF too */ - VGM_LOG("OPUS: buffer can't hold OggS at %"PRIx64"\n", (off64_t)data->physical_offset); + VGM_LOG("OPUS: buffer can't hold OggS at %x\n", (uint32_t)data->physical_offset); data->page_size = 0; break; } @@ -158,12 +167,13 @@ static size_t opus_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, static size_t opus_io_size(STREAMFILE *streamfile, opus_io_data* data) { off_t physical_offset, max_physical_offset; size_t logical_size = 0; + int packet = 0; if (data->logical_size) return data->logical_size; if (data->stream_offset + data->stream_size > get_streamfile_size(streamfile)) { - VGM_LOG("OPUS: wrong streamsize %"PRIx64" + %x vs %x\n", (off64_t)data->stream_offset, data->stream_size, get_streamfile_size(streamfile)); + VGM_LOG("OPUS: wrong streamsize %x + %x vs %x\n", (uint32_t)data->stream_offset, data->stream_size, get_streamfile_size(streamfile)); return 0; } @@ -184,13 +194,28 @@ static size_t opus_io_size(STREAMFILE *streamfile, opus_io_data* data) { data_size = (uint16_t)read_16bitLE(physical_offset, streamfile); skip_size = 0x02; break; + case OPUS_EA: + data_size = (uint16_t)read_16bitBE(physical_offset, streamfile); + skip_size = 0x02; + break; + case OPUS_X: + data_size = get_xopus_packet_size(packet, streamfile); + skip_size = 0x00; + break; default: return 0; } + + if (data_size == 0 ) { + VGM_LOG("OPUS: data_size is 0 at %x\n", (uint32_t)physical_offset); + return 0; /* bad rip? or could 'break' and truck along */ + } + oggs_size = 0x1b + (int)(data_size / 0xFF + 1); /* OggS page: base size + lacing values */ physical_offset += data_size + skip_size; logical_size += oggs_size + data_size; + packet++; } /* logical size can be bigger though */ @@ -382,6 +407,24 @@ fail: static size_t make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate) { size_t header_size = 0x13; + int mapping_family = 0; /* channel config: 0=standard (single stream mono/stereo), 1=vorbis, 255: not defined */ +#if 0 + int stream_count = 1; /* number of internal mono/stereo streams (N mono/stereo streams form M channels) */ + int coupled_count = channels - 1; /* number of stereo streams (packet has which one is mono or stereo) */ + + /* special multichannel config */ + if (channels > 2) { + header_size += 0x01+0x01+channels; + switch(type) { + + case ...: + ... + break; + default: + goto fail; + } + } +#endif if (header_size > buf_size) { VGM_LOG("OPUS: buffer can't hold header\n"); @@ -395,7 +438,19 @@ static size_t make_opus_header(uint8_t * buf, int buf_size, int channels, int sk put_16bitLE(buf+0x0A, skip); put_32bitLE(buf+0x0c, sample_rate); put_16bitLE(buf+0x10, 0); /* output gain */ - put_8bit (buf+0x12, 0); /* channel mapping family */ + put_8bit (buf+0x12, mapping_family); + +#if 0 + if (mapping_family > 0) { + int 0; + + put_8bit(buf+0x13, stream_count); + put_8bit(buf+0x14, coupled_count); + for (i = 0; i < channels; i++) { + put_8bit(buf+0x15+i, i); /* channel mapping (may need to change per family) */ + } + } +#endif return header_size; fail: @@ -452,17 +507,26 @@ fail: return 0; } -/************************** */ - -#ifdef VGM_USE_FFMPEG - static size_t opus_get_packet_samples(const uint8_t * buf, int len) { return opus_packet_get_nb_frames(buf, len) * opus_packet_get_samples_per_frame(buf, 48000); } -static size_t custom_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile, opus_type_t type) { +/************************** */ + +static size_t get_xopus_packet_size(int packet, STREAMFILE * streamfile) { + /* XOPUS has a packet size table at the beginning, get size from there. + * Maybe should copy the table during setup to avoid IO, but all XOPUS are + * quite small so it isn't very noticeable. */ + return (uint16_t)read_16bitLE(0x20 + packet*0x02, streamfile); +} + + +#ifdef VGM_USE_FFMPEG + +static size_t custom_opus_get_samples(off_t offset, size_t data_size, STREAMFILE *streamFile, opus_type_t type) { size_t num_samples = 0; off_t end_offset = offset + data_size; + int packet = 0; if (end_offset > get_streamfile_size(streamFile)) { VGM_LOG("OPUS: wrong end offset found\n"); @@ -483,6 +547,14 @@ static size_t custom_opus_get_samples(off_t offset, size_t data_size, int sample data_size = (uint16_t)read_16bitLE(offset, streamFile); skip_size = 0x02; break; + case OPUS_EA: + data_size = (uint16_t)read_16bitBE(offset, streamFile); + skip_size = 0x02; + break; + case OPUS_X: + data_size = get_xopus_packet_size(packet, streamFile); + skip_size = 0x00; + break; default: return 0; } @@ -491,19 +563,56 @@ static size_t custom_opus_get_samples(off_t offset, size_t data_size, int sample num_samples += opus_get_packet_samples(buf, 0x04); offset += skip_size + data_size; + packet++; } return num_samples; } -size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile) { - return custom_opus_get_samples(offset, data_size, sample_rate, streamFile, OPUS_SWITCH); -} -size_t ue4_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile) { - return custom_opus_get_samples(offset, data_size, sample_rate, streamFile, OPUS_UE4); +size_t switch_opus_get_samples(off_t offset, size_t data_size, STREAMFILE *streamFile) { + return custom_opus_get_samples(offset, data_size, streamFile, OPUS_SWITCH); } +static size_t custom_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile, opus_type_t type) { + uint8_t buf[4]; + size_t skip_size; + + switch(type) { + case OPUS_SWITCH: + skip_size = 0x08; + break; + case OPUS_UE4: + skip_size = 0x02; + break; + case OPUS_EA: + skip_size = 0x02; + break; + case OPUS_X: + skip_size = 0x00; + break; + default: + return 0; + } + + /* encoder delay seems fixed to 1/8 of samples per frame, but may need more testing */ + read_streamfile(buf, offset+skip_size, 0x04, streamFile); /* at least 0x02 */ + return opus_get_packet_samples(buf, 0x04) / 8; +} +size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) { + return custom_opus_get_encoder_delay(offset, streamFile, OPUS_SWITCH); +} +size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) { + return custom_opus_get_encoder_delay(offset, streamFile, OPUS_UE4); +} +size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) { + return custom_opus_get_encoder_delay(offset, streamFile, OPUS_EA); +} + + + +/* ******************************************************* */ + static ffmpeg_codec_data * init_ffmpeg_custom_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate, opus_type_t type) { ffmpeg_codec_data * ffmpeg_data = NULL; STREAMFILE *temp_streamFile = NULL; @@ -514,9 +623,12 @@ static ffmpeg_codec_data * init_ffmpeg_custom_opus(STREAMFILE *streamFile, off_t ffmpeg_data = init_ffmpeg_offset(temp_streamFile, 0x00,get_streamfile_size(temp_streamFile)); if (!ffmpeg_data) goto fail; - if (ffmpeg_data->skipSamples <= 0) { - ffmpeg_set_skip_samples(ffmpeg_data, skip); - } + /* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay (not in stream->skip_samples) + * FFmpeg + opus: *doesn't* skip, also notifies skip in codecCtx->delay, hurray (possibly fixed in recent versions) + * FFmpeg + opus is audibly buggy with some low bitrate SSB Ultimate files too */ + //if (ffmpeg_data->skipSamples <= 0) { + // ffmpeg_set_skip_samples(ffmpeg_data, skip); + //} close_streamfile(temp_streamFile); return ffmpeg_data; @@ -529,9 +641,14 @@ fail: ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_SWITCH); } - ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_UE4); } +ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { + return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_EA); +} +ffmpeg_codec_data * init_ffmpeg_x_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { + return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_X); +} #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c index 1f7938925..3ff8d717d 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c @@ -2,15 +2,14 @@ #ifdef VGM_USE_G719 #include - -#define G719_MAX_FRAME_SIZE 0x1000 /* arbitrary max (samples per frame seems to always be 960) */ +#define G719_MAX_CODES ((1280/8)) /* in int16, so max frame size is (value/8)*2 (0xF0=common, 0x140=decoder max 2560b, rare) */ g719_codec_data *init_g719(int channel_count, int frame_size) { int i; g719_codec_data *data = NULL; - if (frame_size / sizeof(int16_t) > G719_MAX_FRAME_SIZE) + if (frame_size / sizeof(int16_t) > G719_MAX_CODES) goto fail; data = calloc(channel_count, sizeof(g719_codec_data)); /* one decoder per channel */ @@ -19,10 +18,6 @@ g719_codec_data *init_g719(int channel_count, int frame_size) { for (i = 0; i < channel_count; i++) { data[i].handle = g719_init(frame_size); /* Siren 22 == 22khz bandwidth */ if (!data[i].handle) goto fail; - - /* known values: 0xF0=common (sizeof(int16) * 960/8), 0x140=rare (sizeof(int16) * 1280/8) */ - data[i].code_buffer = malloc(sizeof(int16_t) * frame_size); - if (!data[i].code_buffer) goto fail; } return data; @@ -46,8 +41,10 @@ void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int int i; if (0 == vgmstream->samples_into_block) { - read_streamfile((uint8_t*)ch_data->code_buffer, ch->offset, vgmstream->interleave_block_size, ch->streamfile); - g719_decode_frame(ch_data->handle, ch_data->code_buffer, ch_data->buffer); + int16_t code_buffer[G719_MAX_CODES]; + + read_streamfile((uint8_t*)code_buffer, ch->offset, vgmstream->interleave_block_size, ch->streamfile); + g719_decode_frame(ch_data->handle, code_buffer, ch_data->buffer); } for (i = 0; i < samples_to_do; i++) { @@ -71,7 +68,6 @@ void free_g719(g719_codec_data * data, int channels) { for (i = 0; i < channels; i++) { g719_free(data[i].handle); - free(data[i].code_buffer); } free(data); } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c index 61c824fb7..88a3e6479 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c @@ -99,14 +99,14 @@ void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do) { /* read frame */ bytes = read_streamfile(data->data_buffer, offset, blockSize, data->streamfile); if (bytes != blockSize) { - VGM_LOG("HCA: read %x vs expected %x bytes at %"PRIx64"\n", bytes, blockSize, (off64_t)offset); + VGM_LOG("HCA: read %x vs expected %x bytes at %x\n", bytes, blockSize, (uint32_t)offset); break; } /* decode frame */ status = clHCA_DecodeBlock(data->handle, (void*)(data->data_buffer), blockSize); if (status < 0) { - VGM_LOG("HCA: decode fail at %"PRIx64", code=%i\n", (off64_t)offset, status); + VGM_LOG("HCA: decode fail at %x, code=%i\n", (uint32_t)offset, status); break; } @@ -123,6 +123,7 @@ void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do) { void reset_hca(hca_codec_data * data) { if (!data) return; + clHCA_DecodeReset(data->handle); data->current_block = 0; data->samples_filled = 0; data->samples_consumed = 0; @@ -150,59 +151,83 @@ void free_hca(hca_codec_data * data) { } -#define HCA_KEY_MAX_BLANK_FRAMES 15 /* ignored up to N blank frames (not uncommon to have ~10, if more something is off) */ -#define HCA_KEY_MAX_TEST_FRAMES 10 /* 5~15 should be enough, but mostly silent or badly mastered files may need more */ -#define HCA_KEY_MAX_ACCEPTABLE_SCORE 300 /* unlikely to work correctly, 10~30 may be ok */ +/* arbitrary scale to simplify score comparisons */ +#define HCA_KEY_SCORE_SCALE 10 +/* ignores beginning frames (~10 is not uncommon, Dragalia Lost vocal layers have lots) */ +#define HCA_KEY_MAX_SKIP_BLANKS 1200 +/* 5~15 should be enough, but almost silent or badly mastered files may need tweaks */ +#define HCA_KEY_MIN_TEST_FRAMES 5 +#define HCA_KEY_MAX_TEST_FRAMES 10 +/* score of 10~30 isn't uncommon in a single frame, too many frames over that is unlikely */ +#define HCA_KEY_MAX_FRAME_SCORE 150 +#define HCA_KEY_MAX_TOTAL_SCORE (HCA_KEY_MAX_TEST_FRAMES * 50*HCA_KEY_SCORE_SCALE) /* Test a number of frames if key decrypts correctly. - * Returns score: <0: error/wrong, 0: unknown/silent file, >0: good (the closest to 1 the better) */ + * Returns score: <0: error/wrong, 0: unknown/silent file, >0: good (the closest to 1 the better). */ int test_hca_key(hca_codec_data * data, unsigned long long keycode) { - size_t test_frame = 0, current_frame = 0, blank_frames = 0; - int total_score = 0; + size_t test_frames = 0, current_frame = 0, blank_frames = 0; + int total_score = 0, found_regular_frame = 0; const unsigned int blockSize = data->info.blockSize; + /* Due to the potentially large number of keys this must be tuned for speed. + * Buffered IO seems fast enough (not very different reading a large block once vs frame by frame). + * clHCA_TestBlock could be optimized a bit more. */ clHCA_SetKey(data->handle, keycode); - while (test_frame < HCA_KEY_MAX_TEST_FRAMES && current_frame < data->info.blockCount) { + /* Test up to N non-blank frames or until total frames. */ + /* A final score of 0 (=silent) is only possible for short files with all blank frames */ + + while (test_frames < HCA_KEY_MAX_TEST_FRAMES && current_frame < data->info.blockCount) { off_t offset = data->info.headerSize + current_frame * blockSize; int score; size_t bytes; - /* read frame */ + /* read and test frame */ bytes = read_streamfile(data->data_buffer, offset, blockSize, data->streamfile); if (bytes != blockSize) { total_score = -1; break; } - /* test frame */ score = clHCA_TestBlock(data->handle, (void*)(data->data_buffer), blockSize); - if (score < 0) { + if (score < 0 || score > HCA_KEY_MAX_FRAME_SCORE) { total_score = -1; break; } current_frame++; - /* skip blank block at the beginning */ - if (score == 0 && blank_frames < HCA_KEY_MAX_BLANK_FRAMES) { + /* ignore silent frames at the beginning, up to a point */ + if (score == 0 && blank_frames < HCA_KEY_MAX_SKIP_BLANKS && !found_regular_frame) { blank_frames++; continue; } - test_frame++; + found_regular_frame = 1; + test_frames++; + + /* scale values to make scores of perfect frames more detectable */ + switch(score) { + case 1: score = 1; break; + case 0: score = 3*HCA_KEY_SCORE_SCALE; break; /* blanks after non-blacks aren't very trustable */ + default: score = score*HCA_KEY_SCORE_SCALE; + } + total_score += score; - /* too far, don't bother checking more frames */ - if (total_score > HCA_KEY_MAX_ACCEPTABLE_SCORE) + + /* don't bother checking more frames, other keys will get better scores */ + if (total_score > HCA_KEY_MAX_TOTAL_SCORE) break; } + //;VGM_LOG("HCA KEY: blanks=%i, tests=%i, score=%i\n", blank_frames, test_frames, total_score); - /* signal best possible score */ - if (total_score > 0 && total_score <= HCA_KEY_MAX_TEST_FRAMES) { + /* signal best possible score (many perfect frames and few blank frames) */ + if (test_frames > HCA_KEY_MIN_TEST_FRAMES && total_score > 0 && total_score <= test_frames) { total_score = 1; } + clHCA_DecodeReset(data->handle); return total_score; } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c index b7c3015b3..13213ed02 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -207,6 +207,35 @@ static void alp_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, if (*step_index > 88) *step_index=88; } +/* FFTA2 IMA, different hist and sample rounding, reverse engineered from the ROM */ +static void ffta2_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample) { + int sample_nibble, sample_decoded, step, delta; + + sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; /* ADPCM code */ + sample_decoded = *hist1; /* predictor value */ + step = ADPCMTable[*step_index] * 0x100; /* current step (table in ROM is pre-multiplied though) */ + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) delta = -delta; + sample_decoded += delta; + + /* custom clamp16 */ + if (sample_decoded > 0x7FFF00) + sample_decoded = 0x7FFF00; + else if (sample_decoded < -0x800000) + sample_decoded = -0x800000; + + *hist1 = sample_decoded; + *out_sample = (short)((sample_decoded + 128) / 256); /* int16 sample rounding, hist is kept as int32 */ + + *step_index += IMA_IndexTable[sample_nibble]; + if (*step_index < 0) *step_index=0; + if (*step_index > 88) *step_index=88; +} + /* ************************************ */ /* DVI/IMA */ /* ************************************ */ @@ -351,6 +380,29 @@ void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci stream->adpcm_step_index = step_index; } +/* FFTA2 IMA, DVI IMA with custom nibble expand/rounding */ +void decode_ffta2_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count; + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + int16_t out_sample; + + //external interleave + + //no header + + for (i=first_sample,sample_count=0; ioffset + i/2; + int nibble_shift = (i&1?0:4); //high nibble first + + ffta2_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index, &out_sample); + outbuf[sample_count] = out_sample; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + /* ************************************ */ /* MS-IMA */ /* ************************************ */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c index 990c28732..a7a6b817f 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c @@ -157,7 +157,7 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d } VGM_ASSERT(data->streams_size > 1 && current_interleave != current_data_size+current_padding, - "MPEG FSB: %i streams with non-constant interleave found @ 0x%08"PRIx64"\n", data->streams_size, (off64_t)stream->offset); + "MPEG FSB: %i streams with non-constant interleave found @ 0x%08x\n", data->streams_size, (uint32_t)stream->offset); break; case MPEG_P3D: /* fixed interleave, not frame-aligned (ie. blocks may end/start in part of a frame) */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c index 24b2c5b83..7bfd542ec 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c @@ -59,7 +59,7 @@ static size_t get_repeated_data_size(STREAMFILE *streamFile, off_t new_offset, o } fail: - VGM_LOG("AWC: can't find repeat size, new=0x%08"PRIx64", last=0x%08"PRIx64"\n", (off64_t)new_offset, (off64_t)last_offset); + VGM_LOG("AWC: can't find repeat size, new=0x%08x, last=0x%08x\n", (uint32_t)new_offset, (uint32_t)last_offset); return 0; /* keep on truckin' */ } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c index f21c09f5d..4a544b4f2 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c @@ -529,7 +529,7 @@ static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* if (os->b_off/8 > expected_frame_size) { /* bit reservoir! shouldn't happen with free bitrate, otherwise it's hard to fix as needs complex buffering/calcs */ - VGM_LOG("MPEG EAL3: written 0x%"PRIx64" but expected less than 0x%x at 0x%"PRIx64"\n", (off64_t)(os->b_off/8), expected_frame_size, (off64_t)os->info_offset); + VGM_LOG("MPEG EAL3: written 0x%x but expected less than 0x%x at 0x%x\n", (uint32_t)(os->b_off/8), expected_frame_size, (uint32_t)os->info_offset); } else { /* fill ancillary data (should be ignored, but 0x00 seems to improve mpg123's free bitrate detection) */ @@ -564,8 +564,8 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d if (!eaf->pcm_size) return 1; - VGM_ASSERT(eaf->v1_pcm_decode_discard > 576, "MPEG EAL3: big discard %i at 0x%"PRIx64"\n", eaf->v1_pcm_decode_discard, (off64_t)stream->offset); - VGM_ASSERT(eaf->v1_pcm_number > 0x100, "MPEG EAL3: big samples %i at 0x%"PRIx64"\n", eaf->v1_pcm_number, (off64_t)stream->offset); + VGM_ASSERT(eaf->v1_pcm_decode_discard > 576, "MPEG EAL3: big discard %i at 0x%x\n", eaf->v1_pcm_decode_discard, (uint32_t)stream->offset); + VGM_ASSERT(eaf->v1_pcm_number > 0x100, "MPEG EAL3: big samples %i at 0x%x\n", eaf->v1_pcm_number, (uint32_t)stream->offset); /* read + write PCM block samples (always BE) */ for (i = 0; i < eaf->v1_pcm_number * data->channels_per_frame; i++) { diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_eamp3.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_eamp3.c new file mode 100644 index 000000000..5925ccc1d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_eamp3.c @@ -0,0 +1,175 @@ +#include "mpeg_decoder.h" + +#ifdef VGM_USE_MPEG + +/* parsed info from a single EAMP3 frame */ +typedef struct { + uint32_t extended_flag; + uint32_t stereo_flag; /* assumed */ + uint32_t unknown_flag; /* unused? */ + uint32_t frame_size; /* full size including headers and pcm block */ + uint32_t pcm_number; /* samples in the PCM block (typically 1 MPEG frame, 1152) */ + + uint32_t pre_size; /* size of the header part */ + uint32_t mpeg_size; /* size of the MPEG part */ + uint32_t pcm_size; /* size of the PCM block */ +} eamp3_frame_info; + +static int eamp3_parse_frame(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, eamp3_frame_info * eaf); +static int eamp3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, eamp3_frame_info * eaf); +static int eamp3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start); + +/* init config and validate */ +int mpeg_custom_setup_init_eamp3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) { + mpeg_frame_info info; + uint16_t frame_header; + size_t header_size; + + + /* test unknown stuff */ + frame_header = (uint16_t)read_16bitLE(start_offset+0x00, streamFile); + if (frame_header & 0x2000) { + VGM_LOG("EAMP3: found unknown bit 13\n"); + goto fail; + } + if ((frame_header & 0x8000) && (uint32_t)read_32bitLE(start_offset+0x02, streamFile) > 0xFFFF) { + VGM_LOG("EAMP3: found big PCM block\n"); + goto fail; + } + + /* get frame info at offset */ + header_size = (frame_header & 0x8000) ? 0x06 : 0x02; + if (!mpeg_get_frame_info(streamFile, start_offset+header_size, &info)) + goto fail; + switch(info.layer) { + case 1: *coding_type = coding_MPEG_layer1; break; + case 2: *coding_type = coding_MPEG_layer2; break; + case 3: *coding_type = coding_MPEG_layer3; break; + default: goto fail; + } + data->channels_per_frame = info.channels; + data->samples_per_frame = info.frame_samples; + data->bitrate_per_frame = info.bit_rate; + data->sample_rate_per_frame = info.sample_rate; + + + return 1; +fail: + return 0; +} + +/* reads custom frame header + MPEG data + (optional) PCM block */ +int mpeg_custom_parse_frame_eamp3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) { + mpeg_custom_stream *ms = data->streams[num_stream]; + eamp3_frame_info eaf; + int ok; + + + if (!eamp3_skip_data(stream, data, num_stream, 1)) + goto fail; + + ok = eamp3_parse_frame(stream, data, &eaf); + if (!ok) goto fail; + + ok = eamp3_write_pcm_block(stream, data, num_stream, &eaf); + if (!ok) goto fail; + + ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset + eaf.pre_size, eaf.mpeg_size, stream->streamfile); + stream->offset += eaf.frame_size; + + if (!eamp3_skip_data(stream, data, num_stream, 0)) + goto fail; + + return 1; +fail: + return 0; +} + + +static int eamp3_parse_frame(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, eamp3_frame_info * eaf) { + uint16_t current_header = (uint16_t)read_16bitLE(stream->offset+0x00, stream->streamfile); + + eaf->extended_flag = (current_header & 0x8000); + eaf->stereo_flag = (current_header & 0x4000); + eaf->unknown_flag = (current_header & 0x2000); + eaf->frame_size = (current_header & 0x1FFF); /* full size including PCM block */ + eaf->pcm_number = 0; + if (eaf->extended_flag > 0) { + eaf->pcm_number = (uint32_t)read_32bitLE(stream->offset+0x02, stream->streamfile); + eaf->pcm_size = sizeof(sample) * eaf->pcm_number * data->channels_per_frame; + eaf->pre_size = 0x06; + eaf->mpeg_size = eaf->frame_size - eaf->pre_size - eaf->pcm_size; + if (eaf->frame_size < eaf->pre_size + eaf->pcm_size) { + VGM_LOG("EAMP3: bad pcm size at %x\n", (uint32_t)stream->offset); + goto fail; + } + } + else { + eaf->pcm_size = 0; + eaf->pre_size = 0x02; + eaf->mpeg_size = eaf->frame_size - eaf->pre_size; + } + + return 1; +fail: + return 0; +} + +/* write PCM block directly to sample buffer and setup decode discard (see EALayer3). */ +static int eamp3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, eamp3_frame_info * eaf) { + mpeg_custom_stream *ms = data->streams[num_stream]; + size_t bytes_filled; + int i; + + + bytes_filled = sizeof(sample) * ms->samples_filled * data->channels_per_frame; + if (bytes_filled + eaf->pcm_size > ms->output_buffer_size) { + VGM_LOG("EAMP3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size); + goto fail; + } + + + if (eaf->pcm_number) { + + /* read + write PCM block samples (always LE) */ + for (i = 0; i < eaf->pcm_number * data->channels_per_frame; i++) { + off_t pcm_offset = stream->offset + eaf->pre_size + eaf->mpeg_size + sizeof(sample)*i; + int16_t pcm_sample = read_16bitLE(pcm_offset,stream->streamfile); + put_16bitLE(ms->output_buffer + bytes_filled + sizeof(sample)*i, pcm_sample); + } + ms->samples_filled += eaf->pcm_number; + + /* modify decoded samples */ + { + size_t decode_to_discard = eaf->pcm_number; //todo guessed + ms->decode_to_discard += decode_to_discard; + } + } + + return 1; +fail: + return 0; +} + +/* Skip EA-frames from other streams for .sns/sps multichannel (see EALayer3). */ +static int eamp3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start) { + int ok, i; + eamp3_frame_info eaf; + int skips = at_start ? num_stream : data->streams_size - 1 - num_stream; + + + for (i = 0; i < skips; i++) { + ok = eamp3_parse_frame(stream, data, &eaf); + if (!ok) goto fail; + + //;VGM_LOG("s%i: skipping %x, now at %lx\n", num_stream,eaf.frame_size,stream->offset); + stream->offset += eaf.frame_size; + } + //;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset); + + return 1; +fail: + return 0; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c index d006a7d8f..50517b68a 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c @@ -3,6 +3,7 @@ #include "../vgmstream.h" #ifdef VGM_USE_MPEG +#include #include "mpeg_decoder.h" @@ -139,6 +140,7 @@ mpeg_codec_data *init_mpeg_custom(STREAMFILE *streamFile, off_t start_offset, co case MPEG_EAL32P: case MPEG_EAL32S: ok = mpeg_custom_setup_init_ealayer3(streamFile, start_offset, data, coding_type); break; case MPEG_AWC: ok = mpeg_custom_setup_init_awc(streamFile, start_offset, data, coding_type); break; + case MPEG_EAMP3: ok = mpeg_custom_setup_init_eamp3(streamFile, start_offset, data, coding_type); break; default: ok = mpeg_custom_setup_init_default(streamFile, start_offset, data, coding_type); break; } if (!ok) @@ -398,10 +400,11 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data case MPEG_EAL32S: ok = mpeg_custom_parse_frame_ealayer3(stream, data, num_stream); break; case MPEG_AHX: ok = mpeg_custom_parse_frame_ahx(stream, data, num_stream); break; case MPEG_AWC: ok = mpeg_custom_parse_frame_awc(stream, data, num_stream); break; + case MPEG_EAMP3: ok = mpeg_custom_parse_frame_eamp3(stream, data, num_stream); break; default: ok = mpeg_custom_parse_frame_default(stream, data, num_stream); break; } if (!ok) { - VGM_LOG("MPEG: cannot parse frame @ around %"PRIx64"\n",(off64_t)stream->offset); + VGM_LOG("MPEG: cannot parse frame @ around %x\n",(uint32_t)stream->offset); goto decode_fail; /* mpg123 could resync but custom MPEGs wouldn't need that */ } //;VGM_LOG("MPEG: read results: bytes_in_buffer=0x%x, new offset=%lx\n", ms->bytes_in_buffer, stream->offset); @@ -500,24 +503,29 @@ void free_mpeg(mpeg_codec_data *data) { * someone else in another thread is using it. */ } +/* seeks stream to 0 */ void reset_mpeg(VGMSTREAM *vgmstream) { off_t input_offset; mpeg_codec_data *data = vgmstream->codec_data; if (!data) return; - /* reset multistream */ //todo check if stream offsets are properly reset if (!data->custom) { - /* input_offset is ignored as we can assume it will be 0 for a seek to sample 0 */ mpg123_feedseek(data->m,0,SEEK_SET,&input_offset); + /* input_offset is ignored as we can assume it will be 0 for a seek to sample 0 */ } else { int i; /* re-start from 0 */ - for (i=0; i < data->streams_size; i++) { + for (i = 0; i < data->streams_size; i++) { mpg123_feedseek(data->streams[i]->m,0,SEEK_SET,&input_offset); + data->streams[i]->bytes_in_buffer = 0; + data->streams[i]->buffer_full = 0; + data->streams[i]->buffer_used = 0; data->streams[i]->samples_filled = 0; data->streams[i]->samples_used = 0; + data->streams[i]->current_size_count = 0; + data->streams[i]->current_size_target = 0; data->streams[i]->decode_to_discard = 0; } @@ -525,29 +533,33 @@ void reset_mpeg(VGMSTREAM *vgmstream) { } } +/* seeks to a point */ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) { off_t input_offset; mpeg_codec_data *data = vgmstream->codec_data; if (!data) return; - /* seek multistream */ + if (!data->custom) { mpg123_feedseek(data->m, num_sample,SEEK_SET,&input_offset); - /* force first offset as discard-looping needs to start from the beginning */ + /* adjust loop with mpg123's offset (useful?) */ if (vgmstream->loop_ch) vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + input_offset; } else { int i; /* re-start from 0 */ - for (i=0; i < data->streams_size; i++) { + for (i = 0; i < data->streams_size; i++) { mpg123_feedseek(data->streams[i]->m,0,SEEK_SET,&input_offset); - data->streams[i]->samples_filled = 0; - data->streams[i]->samples_used = 0; - data->streams[i]->decode_to_discard = 0; + data->streams[i]->bytes_in_buffer = 0; data->streams[i]->buffer_full = 0; data->streams[i]->buffer_used = 0; + data->streams[i]->samples_filled = 0; + data->streams[i]->samples_used = 0; + data->streams[i]->current_size_count = 0; + data->streams[i]->current_size_target = 0; + data->streams[i]->decode_to_discard = 0; /* force first offset as discard-looping needs to start from the beginning */ if (vgmstream->loop_ch) @@ -559,33 +571,36 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) { data->samples_to_discard += data->skip_samples; } + data->bytes_in_buffer = 0; data->buffer_full = 0; data->buffer_used = 0; } -/* resets mpg123 decoder and its internals (with mpg123_open_feed as mpg123_feedseek won't work) */ +/* resets mpg123 decoder and its internals without seeking, useful when a new MPEG substream starts */ void flush_mpeg(mpeg_codec_data * data) { if (!data) return; if (!data->custom) { /* input_offset is ignored as we can assume it will be 0 for a seek to sample 0 */ - mpg123_open_feed(data->m); + mpg123_open_feed(data->m); /* mpg123_feedseek won't work */ } else { int i; /* re-start from 0 */ for (i=0; i < data->streams_size; i++) { mpg123_open_feed(data->streams[i]->m); - data->streams[i]->samples_filled = 0; - data->streams[i]->samples_used = 0; - data->streams[i]->decode_to_discard = 0; data->streams[i]->bytes_in_buffer = 0; data->streams[i]->buffer_full = 0; data->streams[i]->buffer_used = 0; + data->streams[i]->samples_filled = 0; + data->streams[i]->samples_used = 0; + data->streams[i]->current_size_count = 0; + data->streams[i]->current_size_target = 0; + data->streams[i]->decode_to_discard = 0; } - data->samples_to_discard = data->skip_samples; /* initial delay */ + data->samples_to_discard = data->skip_samples; } data->bytes_in_buffer = 0; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h index 94e31b13c..a8f117335 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h @@ -21,11 +21,13 @@ int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info * int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); int mpeg_custom_setup_init_awc(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); +int mpeg_custom_setup_init_eamp3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); +int mpeg_custom_parse_frame_eamp3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); #endif/* VGM_USE_MPEG */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mta2_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mta2_decoder.c index 4f4ca57aa..2ecbb3279 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mta2_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mta2_decoder.c @@ -79,7 +79,7 @@ static void mta2_block_update(VGMSTREAMCHANNEL * stream) { } if (block_size <= 0 || block_tracks < 0) { /* nonsense block (maybe at EOF) */ - VGM_LOG("MTA2: bad block @ 0x%"PRIx64"\n", (off64_t)stream->offset); + VGM_LOG("MTA2: bad block @ 0x%x\n", (uint32_t)stream->offset); stream->offset += 0x10; repeat = 0; } @@ -113,20 +113,28 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, frame_size = read_16bitBE(stream->offset+0x06,stream->streamfile); /* not including this header */ /* 0x08(8): null */ - /* EOF: 0-fill buffer (or, as track_channels = 0 > divs by 0) */ - if (num_track < 0) { + + VGM_ASSERT(frame_size == 0, "MTA2: empty frame at %x\n", (uint32_t)stream->offset); + /* frame_size 0 means silent/empty frame (rarely found near EOF for one track but not others) + * negative track only happens for truncated files (EOF) */ + if (frame_size == 0 || num_track < 0) { for (i = 0; i < samples_to_do; i++) outbuf[i * channelspacing] = 0; + stream->offset += 0x10; return; } - track_channels = 0; for (i = 0; i < 8; i++) { if ((channel_layout >> i) & 0x01) track_channels++; } + if (track_channels == 0) { /* bad data, avoid div by 0 */ + VGM_LOG("track_channels 0 at %x\n", (uint32_t)stream->offset); + return; + } + /* assumes tracks channels are divided evenly in all tracks (ex. not 2ch + 1ch + 1ch) */ if (channel / track_channels == num_track) break; /* channel belongs to this track */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c index 7b9778eff..e2d0b1825 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c @@ -109,7 +109,7 @@ static void mtaf_block_update(VGMSTREAMCHANNEL * stream) { } if (block_size <= 0 || block_tracks < 0) { /* nonsense block (maybe at EOF) */ - VGM_LOG("MTAF: bad block @ %"PRIx64"\n", (off64_t)stream->offset); + VGM_LOG("MTAF: bad block @ %x\n", (uint32_t)stream->offset); stream->offset += 0x10; repeat = 0; } @@ -146,7 +146,7 @@ void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t init_idx = read_16bitLE(stream->offset+4+0+c*2, stream->streamfile); /* step-L/R */ int32_t init_hist = read_16bitLE(stream->offset+4+4+c*4, stream->streamfile); /* hist-L/R: hist 16bit + empty 16bit */ - VGM_ASSERT(init_idx < 0 || init_idx > 31, "MTAF: bad header idx @ 0x%"PRIx64"\n", (off64_t)stream->offset); + VGM_ASSERT(init_idx < 0 || init_idx > 31, "MTAF: bad header idx @ 0x%x\n", (uint32_t)stream->offset); /* avoid index out of range in corrupt files */ if (init_idx < 0) { init_idx = 0; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c index b9138c90d..4ea57cc07 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c @@ -23,7 +23,7 @@ void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci coef_index = ((uint8_t)read_8bit(frame_offset+channel,stream->streamfile) >> 4) & 0xf; shift_factor = ((uint8_t)read_8bit(frame_offset+channel,stream->streamfile) >> 0) & 0xf; /* rare but happens, also repeated headers don't match (ex. Ikaruga (GC) SONG02.adp) */ - VGM_ASSERT_ONCE(coef_index > 4 || shift_factor > 12, "DTK: incorrect coefs/shift at %"PRIx64"\n", (off64_t)frame_offset); + VGM_ASSERT_ONCE(coef_index > 4 || shift_factor > 12, "DTK: incorrect coefs/shift at %x\n", (uint32_t)frame_offset); /* decode nibbles */ for (i = first_sample; i < first_sample+samples_to_do; i++) { diff --git a/Frameworks/vgmstream/vgmstream/src/coding/pcfx_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/pcfx_decoder.c new file mode 100644 index 000000000..63cac8562 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/pcfx_decoder.c @@ -0,0 +1,92 @@ +#include "coding.h" + + +static const int step_sizes[49] = { /* OKI table */ + 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, + 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, + 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, + 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 +}; + +static const int stex_indexes[16] = { /* IMA table */ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + + +static void pcfx_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample, int mode) { + int code, step, delta; + + code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf; + step = step_sizes[*step_index]; + + delta = (code & 0x7); + if (mode & 1) { + if (step == 1552) /* bad last step_sizes value from OKI table */ + step = 1522; + delta = step * (delta + 1) * 2; + } + else { + delta = step * (delta + 1); + } + if (code & 0x8) + delta = -delta; + + *step_index += stex_indexes[code]; + if (*step_index < 0) *step_index = 0; + if (*step_index > 48) *step_index = 48; + + *hist1 += delta; + if (*hist1 > 16383) *hist1 = 16383; + if (*hist1 < -16384) *hist1 = -16384; + + if (mode & 1) { + *out_sample = *hist1; + } else { + *out_sample = *hist1 << 1; + } + + /* seems real HW does filtering here too */ + + /* double volume since it clips at half */ + if (mode & 2) { + *out_sample = *hist1 << 1; + } +} + + +/* PC-FX ADPCM decoding, variation of OKI/Dialogic/VOX ADPCM. Based on mednafen/pcfx-music-dump. + * Apparently most ADPCM was made with a buggy encoder, resulting in incorrect sound in real hardware + * and sound clipped at half. Decoding can be controlled with modes: + * - 0: hardware decoding (waveforms in many games will look wrong, ex. Der Langrisser track 032) + * - 1: 'buggy encoder' decoding (waveforms will look fine) + * - 2: hardware decoding with double volume (may clip?) + * - 3: 'buggy encoder' decoding with double volume + * + * PC-FX ISOs don't have a standard filesystem nor file formats (raw data must be custom-ripped), + * so it's needs GENH/TXTH. Sample rate can only be base_value divided by 1/2/3/4, where + * base_value is approximately ~31468.5 (follows hardware clocks), mono or stereo-interleaved. + */ +void decode_pcfx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode) { + int i, sample_count = 0; + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + int16_t out_sample; + + for (i = first_sample; i < first_sample + samples_to_do; i++) { + off_t byte_offset = stream->offset + i/2; + int nibble_shift = (i&1?4:0); /* low nibble first */ + + pcfx_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index, &out_sample, mode); + outbuf[sample_count] = out_sample; + sample_count += channelspacing; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + +size_t pcfx_bytes_to_samples(size_t bytes, int channels) { + /* 2 samples per byte (2 nibbles) in stereo or mono config */ + return bytes * 2 / channels; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c index 057ced733..45aa97936 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c @@ -63,7 +63,7 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, shift_factor = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 0) & 0xf; flag = (uint8_t)read_8bit(frame_offset+0x01,stream->streamfile); /* only lower nibble needed */ - VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %"PRIx64"\n", (off64_t)frame_offset); + VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset); if (coef_index > 5) /* needed by inFamous (PS3) (maybe it's supposed to use more filters?) */ coef_index = 0; /* upper filters aren't used in PS1/PS2, maybe in PSP/PS3? */ if (shift_factor > 12) @@ -71,7 +71,7 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, if (is_badflags) /* some games store garbage or extra internal logic in the flags, must be ignored */ flag = 0; - VGM_ASSERT_ONCE(flag > 7,"PS-ADPCM: unknown flag at %"PRIx64"\n", (off64_t)frame_offset); /* meta should use PSX-badflags */ + VGM_ASSERT_ONCE(flag > 7,"PS-ADPCM: unknown flag at %x\n", (uint32_t)frame_offset); /* meta should use PSX-badflags */ /* decode nibbles */ for (i = first_sample; i < first_sample + samples_to_do; i++) { @@ -123,7 +123,7 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample * outbuf, int cha coef_index = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 4) & 0xf; shift_factor = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 0) & 0xf; - VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %"PRIx64"\n", (off64_t)frame_offset); + VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset); if (coef_index > 5) /* needed by Afrika (PS3) (maybe it's supposed to use more filters?) */ coef_index = 0; /* upper filters aren't used in PS1/PS2, maybe in PSP/PS3? */ if (shift_factor > 12) @@ -180,7 +180,7 @@ static int ps_find_loop_offsets_internal(STREAMFILE *streamFile, off_t start_off uint8_t flag = (uint8_t)read_8bit(offset+0x01,streamFile) & 0x0F; /* lower nibble only (for HEVAG) */ /* theoretically possible and would use last 0x06 */ - VGM_ASSERT_ONCE(loop_start_found && flag == 0x06, "PS LOOPS: multiple loop start found at %"PRIx64"\n", (off64_t)offset); + VGM_ASSERT_ONCE(loop_start_found && flag == 0x06, "PS LOOPS: multiple loop start found at %x\n", (uint32_t)offset); if (flag == 0x06 && !loop_start_found) { loop_start = num_samples; /* loop start before this frame */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c index 2a0ba6c69..b5f3da953 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c @@ -69,7 +69,7 @@ vorbis_custom_codec_data * init_vorbis_custom(STREAMFILE *streamFile, off_t star return data; fail: - VGM_LOG("VORBIS: init fail at around 0x%"PRIx64"\n", (off64_t)start_offset); + VGM_LOG("VORBIS: init fail at around 0x%x\n", (uint32_t)start_offset); free_vorbis_custom(data); return NULL; } @@ -144,7 +144,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample /* parse the fake ogg packet into a logical vorbis block */ rc = vorbis_synthesis(&data->vb,&data->op); if (rc == OV_ENOTAUDIO) { - VGM_LOG("Vorbis: not an audio packet (size=0x%x) @ %"PRIx64"\n",(size_t)data->op.bytes,(off64_t)stream->offset); + VGM_LOG("Vorbis: not an audio packet (size=0x%x) @ %x\n",(size_t)data->op.bytes,(uint32_t)stream->offset); //VGM_LOGB(data->op.packet, (size_t)data->op.bytes,0); continue; /* rarely happens, seems ok? */ } else if (rc != 0) goto decode_fail; @@ -162,7 +162,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample decode_fail: /* on error just put some 0 samples */ - VGM_LOG("VORBIS: decode fail at %"PRIx64", missing %i samples\n", (off64_t)stream->offset, (samples_to_do - samples_done)); + VGM_LOG("VORBIS: decode fail at %x, missing %i samples\n", (uint32_t)stream->offset, (samples_to_do - samples_done)); memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * channels * sizeof(sample)); } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c index d0c694594..58c3c21a0 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c @@ -76,7 +76,7 @@ void decode_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, i if (read_32bitBE(frame_offset+0x00,stream->streamfile) != read_32bitBE(frame_offset+0x04,stream->streamfile) || read_32bitBE(frame_offset+0x08,stream->streamfile) != read_32bitBE(frame_offset+0x0c,stream->streamfile)) { - VGM_LOG("bad frames at %"PRIx64"\n", (off64_t)frame_offset); + VGM_LOG("bad frames at %x\n", (uint32_t)frame_offset); } @@ -90,7 +90,7 @@ void decode_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, i coef_index = ((uint8_t)read_8bit(sp_offset,stream->streamfile) >> 4) & 0xf; shift_factor = ((uint8_t)read_8bit(sp_offset,stream->streamfile) >> 0) & 0xf; - VGM_ASSERT(coef_index > 4 || shift_factor > 12, "XA: incorrect coefs/shift at %"PRIx64"\n", (off64_t)sp_offset); + VGM_ASSERT(coef_index > 4 || shift_factor > 12, "XA: incorrect coefs/shift at %x\n", (uint32_t)sp_offset); if (coef_index > 4) coef_index = 0; /* only 4 filters are used, rest is apparently 0 */ if (shift_factor > 12) diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index da48aff86..0f2e3cd50 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -1,11 +1,13 @@ #include "vgmstream.h" -/* defines the list of accepted extensions. vgmstream doesn't use it internally so it's here +/* Defines the list of accepted extensions. vgmstream doesn't use it internally so it's here * to inform plugins that need it. Common extensions are commented out to avoid stealing them. */ -/* some extensions require external libraries and could be #ifdef, not really needed */ -/* some formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension is not parsed */ +/* Some extensions require external libraries and could be #ifdef, not worth. */ + +/* Formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension isn't + * parsed by vgmstream and typically won't not be fully accurate. May have a .ext.pos pair for fun. */ static const char* extension_list[] = { @@ -16,19 +18,22 @@ static const char* extension_list[] = { "2pfs", "800", - //"aac", //common, also tri-Ace's - "aa3", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) + //"aac", //common + "aa3", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "aaap", "aax", "abk", - //"ac3", //FFmpeg, not parsed //common? - "ace", //fake, for tri-Ace's formats (to be removed) + //"ac3", //common, FFmpeg/not parsed (AC3) + "ace", //fake extension for tri-Ace's .aac (renamed, to be removed) "acm", "ad", //txth/reserved [Xenosaga Freaks (PS2)] + "adc", //txth/reserved [Tomb Raider The Last Revelation (DC), Tomb Raider Chronicles (DC)] "adm", "adp", "adpcm", + "adpcmx", "ads", + "adw", "adx", "afc", "agsc", @@ -37,13 +42,13 @@ static const char* extension_list[] = { "ai", //"aif", //common "aifc", //common? - "aifcl", //fake extension, for AIF??? + "aifcl", //fake extension for .aif??? //"aiff", //common - "aiffl", //fake extension, for AIF??? + "aiffl", //fake extension for .aif??? "aix", "akb", "al2", - "amts", //fake extension/header id for .stm (to be removed) + "amts", //fake extension/header id for .stm (renamed? to be removed?) "ao", "apc", "as4", @@ -72,7 +77,7 @@ static const char* extension_list[] = { "bdsp", "bfstm", "bfwav", - "bfwavnsmbu", + "bfwavnsmbu", //fake extension for New Super Smash Bros U (renamed to fix bug) "bg00", "bgm", "bgw", @@ -97,12 +102,13 @@ static const char* extension_list[] = { "cbd2", "ccc", "cd", - "cfn", //fake extension/header id for .caf (to be removed) + "cfn", //fake extension for CAF (renamed, to be removed?) "ckb", "ckd", "cks", "cnk", "cps", + "csa", //txth/reserved [LEGO Racers 2 (PS2)] "csmp", "cvs", "cxs", @@ -123,8 +129,12 @@ static const char* extension_list[] = { "e4x", "eam", - "emff", + "eas", + "eda", //txth/reserved [Project Eden (PS2)] + "emff", //fake extension for .mul (to be removed) + "enm", "eno", + "ens", "enth", "exa", "ezw", @@ -132,6 +142,7 @@ static const char* extension_list[] = { "fag", "ffw", "filp", + //"flac", //common "flx", "fsb", "fsv", @@ -146,10 +157,12 @@ static const char* extension_list[] = { "genh", "gms", "gsb", + //"gsf", //conflicts with GBA gsf plugins? "gtd", "gwm", "h4m", + "hab", "hca", "hdr", "hgc1", @@ -162,10 +175,11 @@ static const char* extension_list[] = { "iab", "iadp", "idsp", - "idvi", //fake extension for .pcm (to be removed) + "idvi", //fake extension/header id for .pcm (renamed, to be removed) "idx", "ikm", "ild", + "imc", "int", "isd", "isws", @@ -179,31 +193,46 @@ static const char* extension_list[] = { "jstm", "kces", - "kcey", //fake extension/header id (to be removed) + "kcey", //fake extension/header id for .pcm (renamed, to be removed) "khv", "km9", - "kovs", //.kvs header id + "kovs", //fake extension/header id for .kvs "kns", "kraw", - "ktss", //.kns header id + "ktss", //fake extension/header id for .kns "kvs", "l", - "laac", //fake extension, for AAC (tri-Ace/FFmpeg) - "lac3", //fake extension, for AC3 + "laac", //fake extension for .aac (tri-Ace) + "lac3", //fake extension for .ac3, FFmpeg/not parsed "leg", - "lflac", //fake extension, FFmpeg, not parsed, use with .pos pair for fun - "lmp4", //fake extension, for MP4s - "logg", //fake extension, for OGGs - "lopus", //fake extension, for OPUS + "lflac", //fake extension for .flac, FFmpeg/not parsed + "lin", + "lm0", + "lm1", + "lm2", + "lm3", + "lm4", + "lm5", + "lm6", + "lm7", + "lmp2", //fake extension for .mp2, FFmpeg/not parsed + "lmp3", //fake extension for .mp3, FFmpeg/not parsed + "lmp4", //fake extension for .mp4 + "lmpc", //fake extension for .mpc, FFmpeg/not parsed + "logg", //fake extension for .ogg + "lopus", //fake extension for .opus "lpcm", "lpk", "lps", + "lse", "lsf", - "lstm", //fake extension, for STMs - "lwav", //fake extension, for WAVs + "lstm", //fake extension for .stm + "lwav", //fake extension for .wav + "lwma", //fake extension for .wma, FFmpeg/not parsed "mab", + "map", "matx", "mc3", "mca", @@ -218,12 +247,14 @@ static const char* extension_list[] = { "mihb", "mnstr", "mogg", + //"mp2", //common //"mp3", //common //"mp4", //common - //"mpc", //FFmpeg, not parsed (musepack) //common + //"mpc", //common "mpdsp", "mpds", - "mps", //txh/reserved [Scandal (PS2)] + "mpf", + "mps", //txth/reserved [Scandal (PS2)] "ms", "msa", "msb", @@ -234,9 +265,11 @@ static const char* extension_list[] = { "msvp", "mta2", "mtaf", + "mul", "mus", "musc", "musx", + "mvb", //txth/reserved [Porsche Challenge (PS1)] "mwv", "mxst", "myspd", @@ -247,20 +280,24 @@ static const char* extension_list[] = { "nlsd", "nop", "nps", - "npsf", //fake extension/header id for .nps (to be removed) + "npsf", //fake extension/header id for .nps (in bigfiles) + "nus3audio", "nus3bank", "nwa", + "nwav", "nxa", //"ogg", //common "ogl", - "oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) + "oma", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "omu", //"opus", //common + "opusx", "otm", "ovb", "p1d", //txth/reserved [Farming Simulator 18 (3DS)] + "p2a", //txth/reserved [Thunderhawk Operation Phoenix (PS2)] "p2bt", "p3d", "past", @@ -270,10 +307,10 @@ static const char* extension_list[] = { "pnb", "pona", "pos", - "ps2stm", //fake extension for .stm (to be removed) + "ps2stm", //fake extension for .stm (renamed? to be removed?) "psh", // fake extension for VSV(?) Dawn of Mana needs to be checked again "psnd", - "psw", //fake extension for .wam + "psw", //fake extension for .wam (renamed, to be removed) "r", "rac", //txth/reserved [Manhunt (Xbox)] @@ -289,7 +326,7 @@ static const char* extension_list[] = { "rsd", "rsf", "rsm", - "rstm", //rsm header id + "rstm", //fake extension/header id for .rstm (in bigfiles) "rvws", "rwar", "rwav", @@ -311,6 +348,14 @@ static const char* extension_list[] = { "sb5", "sb6", "sb7", + "sm0", + "sm1", + "sm2", + "sm3", + "sm4", + "sm5", + "sm6", + "sm7", "sbin", "sc", "scd", @@ -331,7 +376,7 @@ static const char* extension_list[] = { "sli", "smc", "smp", - "smpl", //fake extension (to be removed) + "smpl", //fake extension/header id for .v0/v1 (renamed, to be removed) "smv", "snd", "snds", @@ -353,7 +398,7 @@ static const char* extension_list[] = { "ster", "sth", //"stm", //common - "stma", //fake extension (to be removed) + "stma", //fake extension/header id for .stm "str", "stream", "strm", @@ -375,9 +420,8 @@ static const char* extension_list[] = { "thp", "tk5", "tra", - "trj", - "trm", "tun", + "txth", "txtp", "tydsp", @@ -389,6 +433,7 @@ static const char* extension_list[] = { "v0", //"v1", //dual channel with v0 + "va3", "vag", "vai", "vas", @@ -422,9 +467,11 @@ static const char* extension_list[] = { "wavebatch", "wavm", "wb", + "wd", "wem", "wii", "wip", //txth/reserved [Colin McRae DiRT (PC)] + "wma", //common "wmus", "wp2", "wpd", @@ -451,12 +498,14 @@ static const char* extension_list[] = { "xss", "xvag", "xvas", - "xwav",//fake, to be removed + "xwav",//fake extension for .wav (renamed, to be removed) "xwb", "xmd", + "xopus", + "xps", "xwc", - "xwm", //FFmpeg, not parsed (XWMA) - "xwma", //FFmpeg, not parsed (XWMA) + "xwm", + "xwma", "xws", "xwv", @@ -464,6 +513,8 @@ static const char* extension_list[] = { "ymf", "zsd", + "zsm", + "zss", "zwdsp", "vgmstream" /* fake extension, catch-all for FFmpeg/txth/etc */ @@ -544,6 +595,7 @@ static const coding_info coding_info_list[] = { {coding_OTNS_IMA, "Omikron: The Nomad Soul 4-bit IMA ADPCM"}, {coding_WV6_IMA, "Gorilla Systems WV6 4-bit IMA ADPCM"}, {coding_ALP_IMA, "High Voltage ALP 4-bit IMA ADPCM"}, + {coding_FFTA2_IMA, "Final Fantasy Tactics A2 4-bit IMA ADPCM"}, {coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"}, {coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"}, @@ -578,6 +630,7 @@ static const coding_info coding_info_list[] = { {coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"}, {coding_ASF, "Argonaut ASF 4-bit ADPCM"}, {coding_XMD, "Konami XMD 4-bit ADPCM"}, + {coding_PCFX, "PC-FX 4-bit ADPCM"}, {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, {coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"}, @@ -587,6 +640,7 @@ static const coding_info coding_info_list[] = { {coding_DERF, "Xilam DERF 8-bit DPCM"}, {coding_ACM, "InterPlay ACM"}, {coding_NWA, "VisualArt's NWA DPCM"}, + {coding_CIRCUS_ADPCM, "Circus 8-bit ADPCM"}, {coding_EA_MT, "Electronic Arts MicroTalk"}, @@ -644,9 +698,8 @@ static const layout_info layout_info_list[] = { {layout_blocked_ws_aud, "blocked (Westwood Studios .aud)"}, {layout_blocked_matx, "blocked (Matrix .matx)"}, {layout_blocked_dec, "blocked (DEC)"}, - {layout_blocked_vs, "blocked (vs)"}, - {layout_blocked_emff_ps2, "blocked (EMFF PS2)"}, - {layout_blocked_emff_ngc, "blocked (EMFF NGC)"}, + {layout_blocked_vs, "blocked (Melbourne House VS)"}, + {layout_blocked_mul, "blocked (MUL)"}, {layout_blocked_gsb, "blocked (GSB)"}, {layout_blocked_thp, "blocked (THP Movie Audio)"}, {layout_blocked_filp, "blocked (FILP)"}, @@ -655,7 +708,7 @@ static const layout_info layout_info_list[] = { {layout_blocked_bdsp, "blocked (BDSP)"}, {layout_blocked_ivaud, "blocked (IVAUD)"}, {layout_blocked_ps2_iab, "blocked (IAB)"}, - {layout_blocked_ps2_strlr, "blocked (The Bouncer STR)"}, + {layout_blocked_vs_str, "blocked (STR VS)"}, {layout_blocked_rws, "blocked (RWS)"}, {layout_blocked_hwas, "blocked (HWAS)"}, {layout_blocked_tra, "blocked (TRA)"}, @@ -669,6 +722,7 @@ static const layout_info layout_info_list[] = { {layout_blocked_sthd, "blocked (STHD)"}, {layout_blocked_h4m, "blocked (H4M)"}, {layout_blocked_xa_aiff, "blocked (XA AIFF)"}, + {layout_blocked_vs_square, "blocked (Square VS)"}, }; static const meta_info meta_info_list[] = { @@ -699,7 +753,7 @@ static const meta_info meta_info_list[] = { {meta_RWAV, "Nintendo RWAV header"}, {meta_CWAV, "Nintendo CWAV header"}, {meta_FWAV, "Nintendo FWAV header"}, - {meta_PSX_XA, "RIFF/CDXA header"}, + {meta_XA, "Sony XA header"}, {meta_PS2_RXWS, "Sony RXWS header"}, {meta_PS2_RAW, ".int PCM raw header"}, {meta_PS2_OMU, "Alter Echo OMU Header"}, @@ -740,7 +794,7 @@ static const meta_info meta_info_list[] = { {meta_WS_AUD, "Westwood Studios .aud header"}, {meta_WS_AUD_old, "Westwood Studios .aud (old) header"}, {meta_PS2_IVB, "IVB/BVII header"}, - {meta_PS2_SVS, "Square SVS header"}, + {meta_SVS, "Square SVS header"}, {meta_RIFF_WAVE, "RIFF WAVE header"}, {meta_RIFF_WAVE_POS, "RIFF WAVE header and .pos for looping"}, {meta_NWA, "VisualArt's NWA header"}, @@ -750,7 +804,8 @@ static const meta_info meta_info_list[] = { {meta_HGC1, "Knights of the Temple 2 hgC1 Header"}, {meta_AUS, "Capcom AUS Header"}, {meta_RWS, "RenderWare RWS header"}, - {meta_EA_1SNH, "Electronic Arts 1SNh/EACS header"}, + {meta_EA_1SNH, "Electronic Arts 1SNh header"}, + {meta_EA_EACS, "Electronic Arts EACS header"}, {meta_SL3, "Atari Melbourne House SL3 header"}, {meta_FSB1, "FMOD Sample Bank (FSB1) Header"}, {meta_FSB2, "FMOD Sample Bank (FSB2) Header"}, @@ -790,11 +845,14 @@ static const meta_info meta_info_list[] = { {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"}, {meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"}, {meta_PS2_TEC, "assumed TECMO badflagged stream by .tec extension"}, + {meta_PS2_ENTH, ".enth Header"}, + {meta_SDT, "High Voltage .sdt header"}, + {meta_NGC_TYDSP, ".tydsp Header"}, {meta_XBOX_WVS, "Metal Arms WVS Header (XBOX)"}, {meta_NGC_WVS, "Metal Arms WVS Header (GameCube)"}, {meta_XBOX_MATX, "assumed Matrix file by .matx extension"}, {meta_DEC, "Falcom DEC RIFF header"}, - {meta_VS, "Men in Black VS Header"}, + {meta_VS, "Melbourne House .VS header"}, {meta_DC_STR, "Sega Stream Asset Builder header"}, {meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"}, {meta_XBOX_XMU, "XMU header"}, @@ -804,7 +862,7 @@ static const meta_info meta_info_list[] = { {meta_KRAW, "Geometry Wars: Galaxies KRAW header"}, {meta_NGC_YMF, "YMF DSP Header"}, {meta_PS2_CCC, "CCC Header"}, - {meta_PSX_FAG, "FAG Header"}, + {meta_FAG, "Radical .FAG Header"}, {meta_PS2_MIHB, "Sony MultiStream MIC header"}, {meta_DSP_WII_MUS, "mus header"}, {meta_WII_SNG, "SNG DSP Header"}, @@ -835,8 +893,7 @@ static const meta_info meta_info_list[] = { {meta_IDSP_NL, "Next Level IDSP header"}, {meta_IDSP_IE, "Inevitable Entertainment IDSP Header"}, {meta_UBI_JADE, "Ubisoft Jade RIFF header"}, - {meta_PS2_SEG, "SEG (PS2) Header"}, - {meta_XBOX_SEG, "SEG (XBOX) Header"}, + {meta_SEG, "Stormfront SEG header"}, {meta_NDS_STRM_FFTA2, "Final Fantasy Tactics A2 RIFF Header"}, {meta_STR_ASR, "Donkey Kong Jet Race KNON/WII Header"}, {meta_ZWDSP, "Zack and Wiki custom DSP Header"}, @@ -851,8 +908,7 @@ static const meta_info meta_info_list[] = { {meta_VGS, "Guitar Hero VGS Header"}, {meta_DC_DCSW_DCS, "Evil Twin DCS file with helper"}, {meta_WII_SMP, "SMP DSP Header"}, - {meta_EMFF_PS2, "Eidos Music File Format Header"}, - {meta_EMFF_NGC, "Eidos Music File Format Header"}, + {meta_MUL, "Crystal Dynamics .MUL header"}, {meta_THP, "THP Movie File Format Header"}, {meta_STS_WII, "Shikigami no Shiro (WII) Header"}, {meta_PS2_P2BT, "Pop'n'Music 7 Header"}, @@ -871,7 +927,7 @@ static const meta_info meta_info_list[] = { {meta_ADS, "dhSS Header"}, {meta_PS2_MCG, "Gunvari MCG Header"}, {meta_ZSD, "ZSD Header"}, - {meta_RedSpark, "RedSpark Header"}, + {meta_REDSPARK, "RedSpark Header"}, {meta_IVAUD, "Rockstar .ivaud header"}, {meta_DSP_WII_WSD, ".WSD header"}, {meta_WII_NDP, "Icon Games NDP header"}, @@ -949,7 +1005,7 @@ static const meta_info meta_info_list[] = { {meta_X360_TRA, "Terminal Reality .TRA raw header"}, {meta_PS2_VGS, "Princess Soft VGS header"}, {meta_PS2_IAB, "Runtime .IAB header"}, - {meta_PS2_STRLR, "The Bouncer STR header"}, + {meta_VS_STR, "Square .VS STR* header"}, {meta_LSF_N1NJ4N, ".lsf !n1nj4n header"}, {meta_VAWX, "feelplus VAWX header"}, {meta_PC_SNDS, "assumed Heavy Iron IMA by .snds extension"}, @@ -1025,20 +1081,16 @@ static const meta_info meta_info_list[] = { {meta_NGC_VID1, "Neversoft VID1 header"}, {meta_PC_FLX, "Ultima IX .FLX header"}, {meta_MOGG, "Harmonix Music Systems MOGG Vorbis"}, - {meta_OGG_VORBIS, "Ogg Vorbis"}, - {meta_OGG_SLI, "Ogg Vorbis with .sli (start,length) for looping"}, - {meta_OGG_SLI2, "Ogg Vorbis with .sli (from,to) for looping"}, - {meta_OGG_SFL, "Ogg Vorbis with SFPL for looping"}, - {meta_OGG_UM3, "Ogg Vorbis (Ultramarine3)"}, - {meta_OGG_KOVS, "Ogg Vorbis (KOVS header)"}, - {meta_OGG_PSYCHIC, "Ogg Vorbis (Psychic Software)"}, - {meta_OGG_SNGW, "Ogg Vorbis (Capcom)"}, - {meta_OGG_ISD, "Ogg Vorbis (ISD)"}, + {meta_OGG_VORBIS, "Ogg Vorbis header"}, + {meta_OGG_SLI, "Ogg Vorbis header (.sli looping)"}, + {meta_OPUS_SLI, "Ogg Opus header (.sli looping)"}, + {meta_OGG_SFL, "Ogg Vorbis header (SFPL looping)"}, + {meta_OGG_KOVS, "Ogg Vorbis header (KOVS)"}, + {meta_OGG_encrypted, "Ogg Vorbis header (encrypted)"}, {meta_KMA9, "Koei Tecmo KMA9 header"}, {meta_XWC, "Starbreeze XWC header"}, {meta_SQEX_SAB, "Square-Enix SAB header"}, {meta_SQEX_MAB, "Square-Enix MAB header"}, - {meta_OGG_L2SD, "Ogg Vorbis (L2SD)"}, {meta_WAF, "KID WAF header"}, {meta_WAVE, "EngineBlack .WAVE header"}, {meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"}, @@ -1052,20 +1104,15 @@ static const meta_info meta_info_list[] = { {meta_DSP_MCADPCM, "Bethesda .mcadpcm header"}, {meta_UBI_LYN, "Ubisoft LyN RIFF header"}, {meta_MSB_MSH, "Sony MultiStream MSH+MSB header"}, - {meta_OGG_RPGMV, "Ogg Vorbis (RPGMV header)"}, - {meta_OGG_ENO, "Ogg Vorbis (ENO header)"}, {meta_TXTP, "TXTP generic header"}, {meta_SMC_SMH, "Genki SMC+SMH header"}, - {meta_OGG_YS8, "Ogg Vorbis (Ys VIII header)"}, {meta_PPST, "Parappa PPST header"}, {meta_OPUS_PPP, "AT9 OPUS header"}, {meta_UBI_BAO, "Ubisoft BAO header"}, {meta_DSP_SWITCH_AUDIO, "UE4 Switch Audio header"}, {meta_TA_AAC_VITA, "tri-Ace AAC (Vita) header"}, - {meta_OGG_GWM, "Ogg Vorbis (GWM header)"}, {meta_DSP_SADF, "Procyon Studio SADF header"}, {meta_H4M, "Hudson HVQM4 header"}, - {meta_OGG_MUS, "Ogg Vorbis (MUS header)"}, {meta_ASF, "Argonaut ASF header"}, {meta_XMD, "Konami XMD header"}, {meta_CKS, "Cricket Audio CKS header"}, @@ -1095,6 +1142,18 @@ static const meta_info meta_info_list[] = { {meta_NXA, "Entergram NXA header"}, {meta_ADPCM_CAPCOM, "Capcom .ADPCM header"}, {meta_UE4OPUS, "Epic Games UE4OPUS header"}, + {meta_XWMA, "Microsoft XWMA RIFF header"}, + {meta_VA3, "Konami VA3 header" }, + {meta_XOPUS, "Exient XOPUS header"}, + {meta_VS_SQUARE, "Square VS header"}, + {meta_NWAV, "Chunsoft NWAV header"}, + {meta_XPCM, "Circus XPCM header"}, + {meta_MSF_TAMASOFT, "Tama-Soft MSF header"}, + {meta_XPS_DAT, "From Software .XPS+DAT header"}, + {meta_ZSND, "Vicarious Visions ZSND header"}, + {meta_DSP_ADPCMX, "AQUASTYLE ADPY header"}, + {meta_OGG_OPUS, "Ogg Opus header"}, + {meta_IMC, "iNiS .IMC header"}, }; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c index fe88a5cfb..c6eea228d 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c @@ -40,7 +40,7 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * if (samples_this_block < 0) { /* probably block bug or EOF, next calcs would give wrong values/segfaults/infinite loop */ - VGM_LOG("layout_blocked: wrong block samples at 0x%"PRIx64"\n", (off64_t)vgmstream->current_block_offset); + VGM_LOG("layout_blocked: wrong block samples at 0x%x\n", (uint32_t)vgmstream->current_block_offset); memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample)); break; } @@ -127,11 +127,8 @@ void block_update(off_t block_offset, VGMSTREAM * vgmstream) { case layout_blocked_dec: block_update_dec(block_offset,vgmstream); break; - case layout_blocked_emff_ps2: - block_update_emff_ps2(block_offset,vgmstream); - break; - case layout_blocked_emff_ngc: - block_update_emff_ngc(block_offset,vgmstream); + case layout_blocked_mul: + block_update_mul(block_offset,vgmstream); break; case layout_blocked_gsb: block_update_gsb(block_offset,vgmstream); @@ -166,8 +163,8 @@ void block_update(off_t block_offset, VGMSTREAM * vgmstream) { case layout_blocked_ps2_iab: block_update_ps2_iab(block_offset,vgmstream); break; - case layout_blocked_ps2_strlr: - block_update_ps2_strlr(block_offset,vgmstream); + case layout_blocked_vs_str: + block_update_vs_str(block_offset,vgmstream); break; case layout_blocked_rws: block_update_rws(block_offset,vgmstream); @@ -205,6 +202,9 @@ void block_update(off_t block_offset, VGMSTREAM * vgmstream) { case layout_blocked_xa_aiff: block_update_xa_aiff(block_offset,vgmstream); break; + case layout_blocked_vs_square: + block_update_vs_square(block_offset,vgmstream); + break; default: /* not a blocked layout */ break; } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c index bfa074124..7c99b6b2e 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c @@ -33,10 +33,15 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) { case 0x5344454E: /* "SDEN" */ case 0x53444652: /* "SDFR" */ case 0x53444745: /* "SDGE" */ + case 0x53444445: /* "SDDE" */ case 0x53444954: /* "SDIT" */ case 0x53445350: /* "SDSP" */ + case 0x53444553: /* "SDES" */ + case 0x53444D58: /* "SDMX" */ case 0x53445255: /* "SDRU" */ case 0x53444A41: /* "SDJA" */ + case 0x53444A50: /* "SDJP" */ + case 0x5344504C: /* "SDPL" */ /* audio chunk */ if (vgmstream->coding_type == coding_PSX) block_samples = ps_bytes_to_samples(block_size-0x10, vgmstream->channels); diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_emff.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_emff.c deleted file mode 100644 index 41ad197f0..000000000 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_emff.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* set up for the block at the given offset */ -void block_update_emff_ps2(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = read_32bitLE( - vgmstream->current_block_offset+0x10, - vgmstream->ch[0].streamfile); - vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x20; - vgmstream->current_block_size/=vgmstream->channels; - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i); - } -} - -void block_update_emff_ngc(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = read_32bitBE( - vgmstream->current_block_offset+0x20, - vgmstream->ch[0].streamfile); - vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x40; - vgmstream->current_block_size/=vgmstream->channels; - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset+0x40+(vgmstream->current_block_size*i); - } -} - diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c index 5c5c4082b..38a17adfd 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c @@ -48,7 +48,7 @@ void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream) { block_skip += (audio_bytes / vgmstream->num_streams) * (vgmstream->stream_index-1); } - VGM_ASSERT(frame_format == 1, "H4M: unknown frame_format %x at %"PRIx64"\n", frame_format, (off64_t)block_offset); + VGM_ASSERT(frame_format == 1, "H4M: unknown frame_format %x at %x\n", frame_format, (uint32_t)block_offset); /* pass current mode to the decoder */ vgmstream->codec_config = (frame_format << 8) | (vgmstream->codec_config & 0xFF); diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_mul.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_mul.c new file mode 100644 index 000000000..716e03c6d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_mul.c @@ -0,0 +1,50 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* process headered blocks with sub-headers */ +void block_update_mul(off_t block_offset, VGMSTREAM * vgmstream) { + STREAMFILE* streamFile = vgmstream->ch[0].streamfile; + int i, block_type; + size_t block_size, block_header, data_size, data_header; + int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; + + block_type = read_32bit(block_offset + 0x00,streamFile); + block_size = read_32bit(block_offset + 0x04,streamFile); /* not including main header */ + + switch(vgmstream->coding_type) { + case coding_NGC_DSP: + block_header = 0x20; + data_header = 0x20; + break; + default: + block_header = 0x10; + data_header = 0x10; + break; + } + + if (block_type == 0x00 && block_size == 0) { + /* oddity in some vid+audio files? bad extraction? */ + block_header = 0x10; + data_header = 0x00; + data_size = 0; + } + if (block_type == 0x00 && block_size != 0) { + /* read audio sub-header */ + data_size = read_32bit(block_offset + block_header + 0x00,streamFile); + } + else { + /* non-audio or empty audio block */ + data_header = 0x00; + data_size = 0; + } + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = data_size / vgmstream->channels; + vgmstream->next_block_offset = block_offset + block_header + block_size; + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + block_header + data_header + vgmstream->current_block_size*i; + //VGM_LOG("ch%i of=%lx\n", i, vgmstream->ch[i].offset); + } + //getchar(); +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs.c index 4284642d5..d53732d6b 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs.c @@ -1,17 +1,16 @@ #include "layout.h" #include "../vgmstream.h" -/* set up for the block at the given offset */ +/* mini-blocks of size + data */ void block_update_vs(off_t block_offset, VGMSTREAM * vgmstream) { + STREAMFILE* streamFile = vgmstream->ch[0].streamfile; int i; - for (i=0;ichannels;i++) { - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = read_32bitLE( - vgmstream->current_block_offset, - vgmstream->ch[0].streamfile); - vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 0x4; - vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x4; - if(i==0) block_offset=vgmstream->next_block_offset; + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset,streamFile); + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 0x04; + vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x04; + if (i == 0) block_offset=vgmstream->next_block_offset; } } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs_square.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs_square.c new file mode 100644 index 000000000..403d6140e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs_square.c @@ -0,0 +1,17 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* Square "VS" headered blocks */ +void block_update_vs_square(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + size_t block_size = 0x800; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = block_size - 0x20; + vgmstream->next_block_offset = block_offset + block_size*vgmstream->channels; + /* 0x08: number of remaning blocks, 0x0c: blocks left */ + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + 0x20 + 0x800*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ps2_strlr.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs_str.c similarity index 89% rename from Frameworks/vgmstream/vgmstream/src/layout/blocked_ps2_strlr.c rename to Frameworks/vgmstream/vgmstream/src/layout/blocked_vs_str.c index 17f982bb6..023f38bf1 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ps2_strlr.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vs_str.c @@ -2,7 +2,7 @@ #include "../vgmstream.h" /* The Bouncer STRx blocks, one block per channel when stereo */ -void block_update_ps2_strlr(off_t block_offset, VGMSTREAM * vgmstream) { +void block_update_vs_str(off_t block_offset, VGMSTREAM * vgmstream) { STREAMFILE* streamFile = vgmstream->ch[0].streamfile; int i; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa.c index 329e4475b..8ab45fdc1 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa.c @@ -26,7 +26,7 @@ void block_update_xa(off_t block_offset, VGMSTREAM * vgmstream) { VGM_ASSERT(block_offset + 0x930 < get_streamfile_size(streamFile) && (uint8_t)read_8bit(block_offset + 0x000 + 0x11,streamFile) != (uint8_t)read_8bit(block_offset + 0x930 + 0x11,streamFile), - "XA block: subchannel change at %"PRIx64"\n", (off64_t)block_offset); + "XA block: subchannel change at %x\n", (uint32_t)block_offset); /* submode flag bits (typical audio value = 0x64 01100100) * - 7 (0x80 10000000): end of file @@ -53,7 +53,7 @@ void block_update_xa(off_t block_offset, VGMSTREAM * vgmstream) { } else { ;VGM_ASSERT_ONCE(block_offset < get_streamfile_size(streamFile), - "XA block: non audio block found at %"PRIx64"\n", (off64_t)block_offset); + "XA block: non audio block found at %x\n", (uint32_t)block_offset); block_samples = 0; /* not an audio sector */ } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/layout.h b/Frameworks/vgmstream/vgmstream/src/layout/layout.h index f547d6771..6e3b65981 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/layout.h +++ b/Frameworks/vgmstream/vgmstream/src/layout/layout.h @@ -21,8 +21,7 @@ void block_update_ws_aud(off_t block_offset, VGMSTREAM * vgmstream); void block_update_matx(off_t block_offset, VGMSTREAM * vgmstream); void block_update_dec(off_t block_offset, VGMSTREAM * vgmstream); void block_update_vs(off_t block_offset, VGMSTREAM * vgmstream); -void block_update_emff_ps2(off_t block_offset, VGMSTREAM * vgmstream); -void block_update_emff_ngc(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_mul(off_t block_offset, VGMSTREAM * vgmstream); void block_update_gsb(off_t block_offset, VGMSTREAM * vgmstream); void block_update_xvas(off_t block_offset, VGMSTREAM * vgmstream); void block_update_thp(off_t block_offset, VGMSTREAM * vgmstream); @@ -33,7 +32,7 @@ void block_update_adm(off_t block_offset, VGMSTREAM * vgmstream); void block_update_bdsp(off_t block_offset, VGMSTREAM * vgmstream); void block_update_tra(off_t block_offset, VGMSTREAM * vgmstream); void block_update_ps2_iab(off_t block_offset, VGMSTREAM * vgmstream); -void block_update_ps2_strlr(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_vs_str(off_t block_offset, VGMSTREAM * vgmstream); void block_update_rws(off_t block_offset, VGMSTREAM * vgmstream); void block_update_hwas(off_t block_offset, VGMSTREAM * vgmstream); void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream); @@ -46,6 +45,7 @@ void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM * vgmstream); void block_update_sthd(off_t block_offset, VGMSTREAM * vgmstream); void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream); void block_update_xa_aiff(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_vs_square(off_t block_offset, VGMSTREAM * vgmstream); /* other layouts */ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aax.c b/Frameworks/vgmstream/vgmstream/src/meta/aax.c index 1ad4dbaa7..3418620e8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aax.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aax.c @@ -3,8 +3,6 @@ #include "../coding/coding.h" #include "aax_utf.h" -static STREAMFILE* setup_aax_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); - #define MAX_SEGMENTS 2 /* usually segment0=intro, segment1=loop/main */ @@ -77,7 +75,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { /* open each segment subfile */ for (i = 0; i < segment_count; i++) { - STREAMFILE* temp_streamFile = setup_aax_streamfile(streamFile, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx")); + STREAMFILE* temp_streamFile = setup_subfile_streamfile(streamFile, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx")); if (!temp_streamFile) goto fail; data->segments[i] = is_hca ? @@ -138,29 +136,6 @@ fail: return NULL; } -static STREAMFILE* setup_aax_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - /* CRI's UTF wrapper around DSP [Sonic Colors sfx (Wii), NiGHTS: Journey of Dreams sfx (Wii)] */ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h index ec37caaa8..f603c8582 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h @@ -185,6 +185,9 @@ static const adxkey_info adxkey8_list[] = { /* Tensei Hakkenshi - Fuumaroku (PS2) */ {0x5761,0x6283,0x4531, "HAKKEN",0}, + /* Lucky Star - Ryouou Gakuen Outousai (PS2) */ + {0x481D,0x44F9,0x4E35, "LSTARPS2",0}, + }; static const adxkey_info adxkey9_list[] = { @@ -192,10 +195,10 @@ static const adxkey_info adxkey9_list[] = { /* Phantasy Star Online 2 */ {0x07d2,0x1ec5,0x0c7f, NULL,0}, // guessed with degod - /* Dragon Ball Z: Dokkan Battle */ + /* Dragon Ball Z: Dokkan Battle (Android/iOS) */ {0x0003,0x0d19,0x043b, NULL,416383518}, // 0000000018D1821E - /* Kisou Ryouhei Gunhound EX (2013-01-31)(Dracue)[PSP] */ + /* Kisou Ryouhei Gunhound EX (PSP) */ {0x0005,0x0bcd,0x1add, NULL,683461999}, // 0000000028BCCD6F /* Raramagi (Android) */ @@ -210,12 +213,16 @@ static const adxkey_info adxkey9_list[] = { /* Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android) */ {0x3f10,0x3651,0x6d31, NULL,4867249871962584729}, // 438BF1F883653699 - // Super Robot Wars X-Omega (voices) [iOS/Android] + /* Super Robot Wars X-Omega (iOS/Android) voices */ {0x5152,0x7979,0x152b, NULL,165521992944278}, // 0000968A97978A96 - // AKA to BLUE (Android) + /* AKA to BLUE (Android) */ {0x03fc,0x0749,0x12EF, NULL,0}, // guessed with VGAudio (possible key: 1FE0748978 / 136909719928) //{0x0c03,0x0749,0x1459, NULL,0}, // 2nd guess (possible key: 6018748A2D / 412727151149) + + /* Mashiro Witch (Android) */ + {0x2669,0x1495,0x2407, NULL,0x55D11D3349495204}, // 55D11D3349495204 + }; static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/akb.c b/Frameworks/vgmstream/vgmstream/src/meta/akb.c index a42d091aa..91bedb819 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/akb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/akb.c @@ -51,7 +51,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile)) goto fail; - /* 0x04(2): version? (iPad/IPhone?) */ + /* 0x04(1): version */ header_size = read_16bitLE(0x06,streamFile); codec = read_8bit(0x0c,streamFile); @@ -62,10 +62,12 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { loop_end = read_32bitLE(0x18,streamFile); /* possibly more complex, see AKB2 */ - if (header_size >= 0x44) { /* v2 */ + if (header_size >= 0x44) { /* v2+ */ extradata_size = read_16bitLE(0x1c,streamFile); + /* 0x20+: config? (pan, volume) */ subheader_size = read_16bitLE(0x28,streamFile); - /* 0x20+: config? (pan, volume), 0x24: file_id? */ + /* 0x24: file_id? */ + /* 0x2b: encryption bitflag if version > 2? */ extradata_offset = header_size + subheader_size; start_offset = extradata_offset + extradata_size; } @@ -74,7 +76,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { } stream_size = get_streamfile_size(streamFile) - start_offset; - loop_flag = read_32bitLE(0x18,streamFile) > 0; /* loop end */ + loop_flag = (loop_end > loop_start); /* build the VGMSTREAM */ @@ -86,12 +88,12 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { switch (codec) { - case 0x02: { /* MSAPDCM [Dragon Quest II (iOS) sfx] */ + case 0x02: { /* MSADPCM [Dragon Quest II (iOS) sfx] */ vgmstream->coding_type = coding_MSADPCM; vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02,streamFile); - /* adjusted samples; bigger or smaller than base samples, but seems more accurate + /* adjusted samples; bigger or smaller than base samples, akb lib uses these fields instead * (base samples may have more than possible and read over file size otherwise, very strange) * loop_end seems to exist even with loop disabled */ vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile); @@ -107,6 +109,8 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { ovmi.meta_type = vgmstream->meta_type; ovmi.stream_size = stream_size; + /* extradata + 0x04: Ogg loop start offset */ + /* oggs have loop info in the comments */ ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); if (ogg_vgmstream) { @@ -143,7 +147,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { #endif #ifdef VGM_USE_FFMPEG - case 0x06: { /* aac [The World Ends with You (iPad)] */ + case 0x06: { /* M4A with AAC [The World Ends with You (iPad)] */ /* init_vgmstream_akb_mp4 above has priority, but this works fine too */ ffmpeg_codec_data *ffmpeg_data; @@ -157,16 +161,16 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { vgmstream->num_samples = num_samples; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; + /* bad total samples (some kind of duration? probably should be loop_end though) */ + if (loop_flag) + vgmstream->num_samples = loop_end+1; - /* remove encoder delay from the "global" sample values */ - vgmstream->num_samples -= ffmpeg_data->skipSamples; - vgmstream->loop_start_sample -= ffmpeg_data->skipSamples; - vgmstream->loop_end_sample -= ffmpeg_data->skipSamples; - + /* loops are pre-adjusted with 2112 encoder delay (ex. TWEWY B04's loop_start=45) */ break; } #endif + case 0x01: /* PCM16LE */ default: goto fail; } @@ -188,7 +192,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset, material_offset, extradata_offset; size_t material_size, extradata_size, stream_size; - int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, /*num_samples, loop_start,*/ loop_end; + int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, /*num_samples,*/ loop_start, loop_end; int total_subsongs, target_subsong = streamFile->stream_index; /* check extensions */ @@ -201,6 +205,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { goto fail; if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile)) goto fail; + /* 0x04: version */ /* parse tables */ { @@ -224,7 +229,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { material_offset = table_offset + read_32bitLE(table_offset + table_size + (target_subsong-1)*entry_size + 0x04, streamFile); } - /** stream header **/ + /** stream header (material) **/ /* 0x00: 0? */ codec = read_8bit(material_offset+0x01,streamFile); channel_count = read_8bit(material_offset+0x02,streamFile); @@ -234,15 +239,18 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { stream_size = read_32bitLE(material_offset+0x08,streamFile); //num_samples = read_32bitLE(material_offset+0x0c,streamFile); - //loop_start = read_32bitLE(material_offset+0x10,streamFile); + loop_start = read_32bitLE(material_offset+0x10,streamFile); loop_end = read_32bitLE(material_offset+0x14,streamFile); extradata_size = read_32bitLE(material_offset+0x18,streamFile); /* rest: ? (empty or 0x3f80) */ - loop_flag = (loop_end > 0); + loop_flag = (loop_end > loop_start); extradata_offset = material_offset + material_size; start_offset = material_offset + material_size + extradata_size; + if (encryption_flag & 0x08) + goto fail; + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); @@ -256,12 +264,11 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { switch (codec) { case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */ - if (encryption_flag & 0x08) goto fail; vgmstream->coding_type = coding_MSADPCM; vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02, streamFile); - /* adjusted samples; bigger or smaller than base samples, but seems more accurate + /* adjusted samples; bigger or smaller than base samples, akb lib uses these fields instead * (base samples may have more than possible and read over file size otherwise, very strange) * loop_end seems to exist even with loop disabled */ vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile); @@ -316,6 +323,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { } #endif + case 0x01: /* PCM16LE */ default: goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/atsl.c b/Frameworks/vgmstream/vgmstream/src/meta/atsl.c index 7ec190248..0b2f6c5b9 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/atsl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/atsl.c @@ -1,8 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_atsl_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); -typedef enum { ATRAC3, ATRAC9, KOVS, KTSS } atsl_codec; +typedef enum { ATRAC3, ATRAC9, KOVS, KTSS, KTAC } atsl_codec; /* .ATSL - Koei Tecmo audio container [One Piece Pirate Warriors (PS3), Warriors All-Stars (PC)] */ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { @@ -13,7 +12,7 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { atsl_codec codec; const char* fake_ext; off_t subfile_offset = 0; - size_t subfile_size = 0, header_size; + size_t subfile_size = 0, header_size, entry_size; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; @@ -40,24 +39,31 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { * - 00060301 00010301 atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS] * - 000A0301 00010501 atsl in G1L from Warriors All-Stars (PC)[KOVS] * - 000B0301 00080601 atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS] + * - 010C0301 01060601 .atsl from Dynasty Warriors 9 (PS4)[KTAC] */ - type = read_8bit(0x0d, streamFile); + entry_size = 0x28; + type = read_16bitLE(0x0c, streamFile); switch(type) { - case 0x01: + case 0x0100: codec = KOVS; fake_ext = "kvs"; break; - case 0x02: + case 0x0200: codec = ATRAC3; fake_ext = "at3"; big_endian = 1; break; - case 0x04: - case 0x06: + case 0x0400: + case 0x0600: codec = ATRAC9; fake_ext = "at9"; break; - case 0x08: + case 0x0601: + codec = KTAC; + fake_ext = "ktac"; + entry_size = 0x3c; + break; + case 0x0800: codec = KTSS; fake_ext = "ktss"; break; @@ -79,14 +85,15 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { for (i = 0; i < entries; i++) { int is_unique = 1; - off_t entry_offset = read_32bit(header_size + i*0x28 + 0x04,streamFile); - size_t entry_size = read_32bit(header_size + i*0x28 + 0x08,streamFile); - /* 0x00: id?, 0x08+: sample rate/num_samples/loop_start/etc, matching subfile header */ + /* 0x00: id */ + off_t entry_subfile_offset = read_32bit(header_size + i*entry_size + 0x04,streamFile); + size_t entry_subfile_size = read_32bit(header_size + i*entry_size + 0x08,streamFile); + /* 0x08+: channels/sample rate/num_samples/loop_start/etc (match subfile header) */ /* check if current entry was repeated in a prev entry */ for (j = 0; j < i; j++) { - off_t prev_offset = read_32bit(header_size + j*0x28 + 0x04,streamFile); - if (prev_offset == entry_offset) { + off_t prev_offset = read_32bit(header_size + j*entry_size + 0x04,streamFile); + if (prev_offset == entry_subfile_offset) { is_unique = 0; break; } @@ -98,8 +105,8 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { /* target GET, but keep going to count subsongs */ if (!subfile_offset && target_subsong == total_subsongs) { - subfile_offset = entry_offset; - subfile_size = entry_size; + subfile_offset = entry_subfile_offset; + subfile_size = entry_subfile_size; } } } @@ -110,7 +117,7 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { /* some kind of seek/switch table may follow (optional, found in .atsl3) */ - temp_streamFile = setup_atsl_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); if (!temp_streamFile) goto fail; /* init the VGMSTREAM */ @@ -130,6 +137,10 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { vgmstream = init_vgmstream_ktss(temp_streamFile); if (!vgmstream) goto fail; break; + case KTAC: + //vgmstream = init_vgmstream_ktac(temp_streamFile); //Koei Tecto VBR-like ATRAC9 + //if (!vgmstream) goto fail; + //break; default: goto fail; } @@ -144,27 +155,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - - -static STREAMFILE* setup_atsl_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awc.c b/Frameworks/vgmstream/vgmstream/src/meta/awc.c index 0b75c44c9..1ff2d1eb2 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/awc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/awc.c @@ -110,6 +110,8 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) { bytes = ffmpeg_make_riff_xma2(buf, 0x100, awc.num_samples, substream_size, layer_channels, awc.sample_rate, block_count, block_size); data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, substream_offset,substream_size); + xma_fix_raw_samples(data->layers[i], temp_streamFile, substream_offset,substream_size, 0, 0,0); /* samples are ok? */ + close_streamfile(temp_streamFile); if (!data->layers[i]->codec_data) goto fail; } @@ -128,6 +130,8 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) { if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, awc.stream_offset,awc.stream_size, 0, 0,0); /* samples are ok? */ } break; @@ -333,7 +337,7 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) { /* If music, data is divided into blocks of block_chunk size with padding. * Each block has a header/seek table and interleaved data for all channels */ if (awc->is_music && read_32bit(awc->stream_offset, streamFile) != 0) { - VGM_LOG("AWC: music found, but block doesn't start with seek table at %"PRIx64"\n", (off64_t)awc->stream_offset); + VGM_LOG("AWC: music found, but block doesn't start with seek table at %x\n", (uint32_t)awc->stream_offset); goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bik.c b/Frameworks/vgmstream/vgmstream/src/meta/bik.c index a80875fb1..8b0bf0def 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bik.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bik.c @@ -38,9 +38,9 @@ VGMSTREAM * init_vgmstream_bik(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG { - /* target_subsong should be passed with the streamFile */ + /* target_subsong should be passed manually */ - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, NULL,0, 0x0,get_streamfile_size(streamFile)); + vgmstream->codec_data = init_ffmpeg_header_offset_subsong(streamFile, NULL,0, 0x0,get_streamfile_size(streamFile), target_subsong); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c b/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c index 10e8f7a66..f7924cf06 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -typedef enum { PSX, PCM16, ATRAC9 } bnk_codec; +typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec; /* BNK - Sony's Scream Tool bank format [Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { @@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { size_t stream_size, interleave = 0; off_t sblk_offset, data_offset; size_t data_size; - int channel_count = 0, loop_flag, sample_rate, version; + int channel_count = 0, loop_flag, sample_rate, parts, version; int loop_start = 0, loop_end = 0; uint32_t atrac9_info = 0; @@ -25,11 +25,11 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { if (!check_extensions(streamFile, "bnk")) goto fail; - if (read_32bitBE(0x00,streamFile) == 0x00000003 && read_32bitBE(0x04,streamFile) == 0x00000002) { /* PS3 */ + if (read_32bitBE(0x00,streamFile) == 0x00000003) { /* PS3 */ read_32bit = read_32bitBE; read_16bit = read_16bitBE; } - else if (read_32bitBE(0x00,streamFile) == 0x03000000 && read_32bitBE(0x04,streamFile) == 0x02000000) { /* Vita/PS4 */ + else if (read_32bitBE(0x00,streamFile) == 0x03000000) { /* Vita/PS4 */ read_32bit = read_32bitLE; read_16bit = read_16bitLE; } @@ -37,17 +37,22 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { goto fail; } + parts = read_32bit(0x04,streamFile); + if (parts < 2 || parts > 3) goto fail; + sblk_offset = read_32bit(0x08,streamFile); /* 0x0c: sklb size */ data_offset = read_32bit(0x10,streamFile); data_size = read_32bit(0x14,streamFile); + /* 0x18: ZLSD small footer, rare [Yakuza 6's Puyo Puyo (PS4)] */ + /* 0x1c: ZLSD size */ /* SE banks, also used for music. Most table fields seems reserved/defaults and * don't change much between subsongs or files, so they aren't described in detail */ /* SBlk part: parse header */ - if (read_32bit(sblk_offset+0x00,streamFile) != 0x6B6C4253) /* "SBlk" (sample block?) */ + if (read_32bit(sblk_offset+0x00,streamFile) != 0x6B6C4253) /* "klBS" (SBlk = sample block?) */ goto fail; version = read_32bit(sblk_offset+0x04,streamFile); /* 0x08: possibly when version=0x0d, 0x03=Vita, 0x06=PS4 */ @@ -83,6 +88,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { break; case 0x0d: /* Polara (Vita), Crypt of the Necrodancer (Vita) */ + case 0x0e: /* Yakuza 6's Puyo Puyo (PS4) */ table1_offset = sblk_offset + read_32bit(sblk_offset+0x18,streamFile); table2_offset = sblk_offset + read_32bit(sblk_offset+0x1c,streamFile); table3_offset = sblk_offset + read_32bit(sblk_offset+0x2c,streamFile); @@ -159,6 +165,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { //case 0x04: /* different format? */ case 0x09: case 0x0d: + case 0x0e: /* find if this sound has an assigned name in table1 */ for (i = 0; i < section_entries; i++) { off_t entry_offset = (uint16_t)read_16bit(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,streamFile); @@ -255,6 +262,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { break; case 0x0d: + case 0x0e: type = read_16bit(start_offset+0x00,streamFile); if (read_32bit(start_offset+0x04,streamFile) != 0x01) /* type? */ goto fail; @@ -305,7 +313,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { loop_length = read_32bit(start_offset+0x1c,streamFile); loop_end = loop_start + loop_length; /* loop_start is -1 if not set */ - codec = PSX; + codec = HEVAG; break; default: @@ -377,6 +385,20 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; break; + + case HEVAG: + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_HEVAG; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + vgmstream->num_samples = ps_bytes_to_samples(stream_size,channel_count); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + break; + + default: + goto fail; } if (name_offset) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c index b7b4881de..3091383d5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c @@ -17,27 +17,33 @@ typedef struct { int32_t loop_start; int32_t loop_end; int32_t loop_start_offset; + int32_t data_offset; int big_endian; int loop_flag; int is_sead; int codec_config; + int is_bank; + int total_subsongs; } ea_header; static int parse_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset); +static VGMSTREAM * init_vgmstream_main(STREAMFILE *streamFile, ea_header* ea); + static void set_ea_1snh_num_samples(STREAMFILE* streamFile, off_t start_offset, ea_header* ea); static int get_ea_1snh_ima_version(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea); -/* EA 1SNh - from early EA games (~1996, ex. Need for Speed) */ +/* EA 1SNh - from early EA games, stream (~1996, ex. Need for Speed) */ VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; ea_header ea = {0}; + off_t eacs_offset; /* checks */ - /* .asf/as4: common, cnk: some PS games, .sng: fake for plugins (to mimic EA SCHl's common extension) */ - /* .uv, .tgq: some SAT games */ + /* .asf/as4: common + * .cnk: some PS games + * .sng: fake for plugins (to mimic EA SCHl's common extension) + * .uv/tgq: some SAT games (video only?) */ if (!check_extensions(streamFile,"asf,as4,cnk,sng,uv,tgq")) goto fail; @@ -47,45 +53,117 @@ VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE *streamFile) { /* stream is divided into blocks/chunks: 1SNh=audio header, 1SNd=data xN, 1SNl=loop end, 1SNe=end. * Video uses various blocks (kVGT/fVGT/etc) and sometimes alt audio blocks (SEAD/SNDC/SEND). */ - ea.is_sead = read_32bitBE(0x00,streamFile) == 0x53454144; /* use block size as endian marker (Saturn = BE) */ - ea.big_endian = !(read_32bitLE(0x04,streamFile) < 0x0000FFFF); + ea.big_endian = guess_endianness32bit(0x04,streamFile); - if (!parse_header(streamFile,&ea, 0x08)) + eacs_offset = 0x08; /* after 1SNh block id+size */ + + if (!parse_header(streamFile,&ea, eacs_offset)) + goto fail; + return init_vgmstream_main(streamFile, &ea); + +fail: + return NULL; +} + +/* EA EACS - from early EA games, bank (~1996, ex. Need for Speed) */ +VGMSTREAM * init_vgmstream_ea_eacs(STREAMFILE *streamFile) { + ea_header ea = {0}; + off_t eacs_offset; + + + /* checks */ + /* .eas: single bank [Need for Speed (PC)] + * .bnk: multi bank [Need for Speed (PC)] */ + if (!check_extensions(streamFile,"eas,bnk")) goto fail; - start_offset = 0x00; + /* plain data without blocks, can contain N*(EACS header) + N*(data), or N (EACS header + data) */ + ea.is_bank = 1; + + /* use ??? as endian marker (Saturn = BE) */ + //ea.big_endian = guess_endianness32bit(0x04,streamFile); + + if (read_32bitBE(0x00,streamFile) == 0x45414353) { /* "EACS" */ + /* single bank variant */ + eacs_offset = 0x00; + } + else if (read_32bitBE(0x00,streamFile) == 0x00) { + /* multi bank variant */ + int i; + int target_subsong = streamFile->stream_index; + + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0) goto fail; + + /* offsets to EACSs are scattered in the first 0x200 + * this looks dumb but seems like the only way */ + eacs_offset = 0; + for (i = 0x00; i < 0x200; i += 0x04) { + off_t bank_offset = read_32bitLE(i, streamFile); + if (bank_offset == 0) + continue; + + ea.total_subsongs++; + + /* parse mini bank header */ + if (ea.total_subsongs == target_subsong) { + /* 0x00: some id or flags? */ + eacs_offset = read_32bitLE(bank_offset + 0x04, streamFile); + /* rest: not sure if part of this header */ + } + } + + if (eacs_offset == 0) + goto fail; + } + else { + goto fail; + } + + if (!parse_header(streamFile,&ea, eacs_offset)) + goto fail; + return init_vgmstream_main(streamFile, &ea); + +fail: + return NULL; +} + + +static VGMSTREAM * init_vgmstream_main(STREAMFILE *streamFile, ea_header* ea) { + VGMSTREAM * vgmstream = NULL; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(ea.channels, ea.loop_flag); + vgmstream = allocate_vgmstream(ea->channels, ea->loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = ea.sample_rate; - vgmstream->num_samples = ea.num_samples; - vgmstream->loop_start_sample = ea.loop_start; - vgmstream->loop_end_sample = ea.loop_end; + vgmstream->sample_rate = ea->sample_rate; + vgmstream->num_samples = ea->num_samples; + vgmstream->loop_start_sample = ea->loop_start; + vgmstream->loop_end_sample = ea->loop_end; - vgmstream->codec_endian = ea.big_endian; - vgmstream->layout_type = layout_blocked_ea_1snh; - vgmstream->meta_type = meta_EA_1SNH; + vgmstream->codec_endian = ea->big_endian; + vgmstream->layout_type = ea->is_bank ? layout_none : layout_blocked_ea_1snh; + vgmstream->meta_type = ea->is_bank ? meta_EA_EACS : meta_EA_1SNH; + vgmstream->num_streams = ea->total_subsongs; - switch (ea.codec) { + switch (ea->codec) { case EA_CODEC_PCM: /* Need for Speed (PC) */ - vgmstream->coding_type = ea.bits==1 ? coding_PCM8_int : coding_PCM16_int; + vgmstream->coding_type = ea->bits==1 ? coding_PCM8_int : coding_PCM16_int; break; case EA_CODEC_ULAW: /* Crusader: No Remorse movies (SAT), FIFA 96 movies (SAT) */ - if (ea.bits && ea.bits!=2) goto fail; /* only set in EACS */ + if (ea->bits && ea->bits != 2) goto fail; /* only set in EACS */ vgmstream->coding_type = coding_ULAW_int; break; case EA_CODEC_IMA: /* Need for Speed II (PC) */ - if (ea.bits && ea.bits!=2) goto fail; /* only in EACS */ + if (ea->bits && ea->bits != 2) goto fail; /* only in EACS */ vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */ - vgmstream->codec_config = ea.codec_config; + vgmstream->codec_config = ea->codec_config; break; case EA_CODEC_PSX: /* Need for Speed (PS) */ @@ -93,12 +171,12 @@ VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE *streamFile) { break; default: - VGM_LOG("EA: unknown codec 0x%02x\n", ea.codec); + VGM_LOG("EA EACS: unknown codec 0x%02x\n", ea->codec); goto fail; } - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,streamFile,ea->data_offset)) goto fail; return vgmstream; @@ -116,15 +194,18 @@ static int parse_header(STREAMFILE* streamFile, ea_header* ea, off_t offset) { ea->bits = read_8bit(offset+0x08, streamFile); ea->channels = read_8bit(offset+0x09, streamFile); ea->codec = read_8bit(offset+0x0a, streamFile); - ea->type = read_8bit(offset+0x0b, streamFile); + ea->type = read_8bit(offset+0x0b, streamFile); /* block type? 0=1SNh, -1=bank */ ea->num_samples = read_32bit(offset+0x0c, streamFile); ea->loop_start = read_32bit(offset+0x10, streamFile); ea->loop_end = read_32bit(offset+0x14, streamFile) + ea->loop_start; /* loop length */ - /* 0x18: data start? (0x00), 0x1c: pan/volume/etc? (0x7F), rest can be padding/garbage */ - VGM_ASSERT(ea->type != 0, "EA EACS: unknown type\n"); /* block type? */ + ea->data_offset = read_32bit(offset+0x18, streamFile); /* 0 when blocked */ + /* 0x1c: pan/volume/etc? (0x7F) + * rest may be padding/garbage */ + //VGM_ASSERT(ea->type != 0, "EA EACS: unknown type %i\n", ea->type); if (ea->codec == EA_CODEC_IMA) ea->codec_config = get_ea_1snh_ima_version(streamFile, 0x00, ea); + /* EACS banks with empty values exist but will be rejected later */ } else if (ea->is_sead) { /* alt subheader (found in some PC videos) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index e56c55056..8c0d274da 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -19,6 +19,7 @@ #define EAAC_CODEC_DSP 0x08 #define EAAC_CODEC_EASPEEX 0x09 #define EAAC_CODEC_EATRAX 0x0a +#define EAAC_CODEC_EAMP3 0x0b #define EAAC_CODEC_EAOPUS 0x0c #define EAAC_FLAG_NONE 0x00 @@ -461,6 +462,85 @@ fail: return NULL; } +/* EA MPF/MUS combo - used in older 7th gen games for storing music */ +VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE *streamFile) { + uint32_t num_sounds; + uint8_t version, sub_version, block_id; + off_t table_offset, entry_offset, snr_offset, sns_offset; + size_t snr_size, sns_size; + int32_t(*read_32bit)(off_t, STREAMFILE*); + int16_t(*read_16bit)(off_t, STREAMFILE*); + STREAMFILE *musFile = NULL; + VGMSTREAM *vgmstream = NULL; + int target_stream = streamFile->stream_index; + + /* check extension */ + if (!check_extensions(streamFile, "mpf")) + goto fail; + + /* detect endianness */ + if (read_32bitBE(0x00, streamFile) == 0x50464478) { /* "PFDx" */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else if (read_32bitBE(0x00, streamFile) == 0x78444650) { /* "xDFP" */ + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } else { + goto fail; + } + + musFile = open_streamfile_by_ext(streamFile, "mus"); + if (!musFile) goto fail; + + /* MPF format is unchanged but we don't really care about its contents since + * MUS conveniently contains sound offset table */ + + version = read_8bit(0x04, streamFile); + sub_version = read_8bit(0x05, streamFile); + if (version != 0x05 || sub_version != 0x03) goto fail; + + /* number of files is always little endian */ + num_sounds = read_32bitLE(0x04, musFile); + table_offset = 0x28; + + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || num_sounds == 0 || target_stream > num_sounds) + goto fail; + + /* + * 0x00: hash? + * 0x04: index + * 0x06: zero + * 0x08: SNR offset + * 0x0c: SNS offset + * 0x10: SNR size + * 0x14: SNS size + * 0x18: zero + */ + entry_offset = table_offset + (target_stream - 1) * 0x1c; + snr_offset = read_32bit(entry_offset + 0x08, musFile) * 0x10; + sns_offset = read_32bit(entry_offset + 0x0c, musFile) * 0x80; + snr_size = read_32bit(entry_offset + 0x10, musFile); + sns_size = read_32bit(entry_offset + 0x14, musFile); + + block_id = read_8bit(sns_offset, musFile); + if (block_id != EAAC_BLOCKID0_DATA && block_id != EAAC_BLOCKID0_END) + goto fail; + + vgmstream = init_vgmstream_eaaudiocore_header(musFile, musFile, snr_offset, sns_offset, meta_EA_SNR_SNS); + if (!vgmstream) + goto fail; + + vgmstream->num_streams = num_sounds; + vgmstream->stream_size = sns_size; + close_streamfile(musFile); + return vgmstream; + +fail: + close_streamfile(musFile); + return NULL; +} + /* ************************************************************************* */ typedef struct { @@ -526,7 +606,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST /* get loops (fairly involved due to the multiple layouts and mutant streamfiles) * full loops aren't too uncommon [Dead Space (PC) stream sfx/ambiance, FIFA 98 (PS3) RAM sfx], - * while actual looping is very rare [Need for Speed: World (PC)] */ + * while actual looping is very rare [Need for Speed: World (PC)-EAL3, The Simpsons Game (X360)-EAXMA] */ if (eaac.flags & EAAC_FLAG_LOOPED) { eaac.loop_flag = 1; eaac.loop_start = read_32bitBE(header_offset+0x08, streamHead); @@ -545,9 +625,12 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST } //todo need more cases to test how layout/streamfiles react - if (eaac.loop_start > 0 && !(eaac.codec == EAAC_CODEC_EALAYER3_V1 || - eaac.codec == EAAC_CODEC_EALAYER3_V2_PCM || eaac.codec == EAAC_CODEC_EALAYER3_V2_SPIKE)) { - VGM_LOG("EA EAAC: unknown actual looping for non-EALayer3\n"); + if (eaac.loop_start > 0 && !( + eaac.codec == EAAC_CODEC_EALAYER3_V1 || + eaac.codec == EAAC_CODEC_EALAYER3_V2_PCM || + eaac.codec == EAAC_CODEC_EALAYER3_V2_SPIKE || + eaac.codec == EAAC_CODEC_EAXMA)) { + VGM_LOG("EA EAAC: unknown actual looping for codec %x\n", eaac.codec); goto fail; } } @@ -586,10 +669,22 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST #ifdef VGM_USE_FFMPEG case EAAC_CODEC_EAXMA: { /* "EXm0": EA-XMA [Dante's Inferno (X360)] */ - vgmstream->layout_data = build_layered_eaaudiocore_eaxma(streamData, &eaac); - if (!vgmstream->layout_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_layered; + + /* special (if hacky) loop handling, see comments */ + if (eaac.streamed && eaac.loop_start > 0) { + segmented_layout_data *data = build_segmented_eaaudiocore_looping(streamData, &eaac); + if (!data) goto fail; + vgmstream->layout_data = data; + vgmstream->coding_type = data->segments[0]->coding_type; + vgmstream->layout_type = layout_segmented; + } + else { + vgmstream->layout_data = build_layered_eaaudiocore_eaxma(streamData, &eaac); + if (!vgmstream->layout_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_layered; + } + break; } #endif @@ -612,7 +707,8 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST start_offset = 0x00; /* must point to the custom streamfile's beginning */ - if (eaac.streamed && eaac.loop_start > 0) { /* special (if hacky) loop handling, see comments */ + /* special (if hacky) loop handling, see comments */ + if (eaac.streamed && eaac.loop_start > 0) { segmented_layout_data *data = build_segmented_eaaudiocore_looping(streamData, &eaac); if (!data) goto fail; vgmstream->layout_data = data; @@ -664,10 +760,47 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST } #endif - case EAAC_CODEC_EASPEEX: /* EASpeex (libspeex variant, base versions vary: 1.0.5, 1.2beta3) */ - /* TODO */ - case EAAC_CODEC_EAOPUS: /* EAOpus (inside each SNS/SPS block is 16b frame size + standard? Opus packet) */ - /* TODO */ + +#ifdef VGM_USE_MPEG + case EAAC_CODEC_EAMP3: { /* "EM30"?: EAMP3 [Need for Speed 2015 (PS4)] */ + mpeg_custom_config cfg = {0}; + + start_offset = 0x00; /* must point to the custom streamfile's beginning */ + + temp_streamFile = setup_eaac_streamfile(streamData, eaac.version, eaac.codec, eaac.streamed,0,0, eaac.stream_offset); + if (!temp_streamFile) goto fail; + + vgmstream->codec_data = init_mpeg_custom(temp_streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_EAMP3, &cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->layout_type = layout_none; + + break; + } + +#endif + +#ifdef VGM_USE_FFMPEG + case EAAC_CODEC_EAOPUS: { /* EAOpus (unknown FourCC) [FIFA 17 (PC), FIFA 19 (Switch)]*/ + int skip = 0; + size_t data_size; + + /* We'll remove EA blocks and pass raw data to FFmpeg Opus decoder */ + + temp_streamFile = setup_eaac_streamfile(streamData, eaac.version, eaac.codec, eaac.streamed,0,0, eaac.stream_offset); + if (!temp_streamFile) goto fail; + + skip = ea_opus_get_encoder_delay(0x00, temp_streamFile); + data_size = get_streamfile_size(temp_streamFile); + + vgmstream->codec_data = init_ffmpeg_ea_opus(temp_streamFile, 0x00,data_size, vgmstream->channels, skip, vgmstream->sample_rate); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } +#endif + + case EAAC_CODEC_EASPEEX: /* "Esp0"?: EASpeex (libspeex variant, base versions vary: 1.0.5, 1.2beta3) */ //todo default: VGM_LOG("EA EAAC: unknown codec 0x%02x\n", eaac.codec); goto fail; @@ -696,17 +829,13 @@ static size_t get_snr_size(STREAMFILE *streamFile, off_t offset) { /* Actual looping uses 2 block sections, separated by a block end flag *and* padded. * - * We use the segmented layout, since the eaac_streamfile doesn't handle padding properly ATM - * (getting EALayer3 frame sizes + skip sizes can be fairly involved), plus seems likely - * that after a block end the decoder needs to be reset (not possible from a streamfile). - * - * Or could fix the blocked_layout+L32P bug, though that involves a lot of rewrites. - * So this is the simplest, surest way ATM (if very ugly). */ + * We use the segmented layout, since the eaac_streamfile doesn't handle padding, + * and the segments seem fully separate (so even skipping would probably decode wrong). */ // todo consider better ways to handle this once more looped files for other codecs are found static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *streamData, eaac_header *eaac) { segmented_layout_data *data = NULL; STREAMFILE* temp_streamFile[2] = {0}; - off_t offsets[2] = { eaac->stream_offset, eaac->loop_offset }; + off_t offsets[2] = { eaac->stream_offset, eaac->stream_offset + eaac->loop_offset }; int num_samples[2] = { eaac->loop_start, eaac->num_samples - eaac->loop_start}; int segment_count = 2; /* intro/loop */ int i; @@ -717,9 +846,6 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *st if (!data) goto fail; for (i = 0; i < segment_count; i++) { - temp_streamFile[i] = setup_eaac_streamfile(streamData, eaac->version,eaac->codec,eaac->streamed,0,0, offsets[i]); - if (!temp_streamFile[i]) goto fail; - data->segments[i] = allocate_vgmstream(eaac->channels, 0); if (!data->segments[i]) goto fail; data->segments[i]->sample_rate = eaac->sample_rate; @@ -727,6 +853,22 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *st //data->segments[i]->meta_type = eaac->meta_type; /* bleh */ switch(eaac->codec) { +#ifdef VGM_USE_FFMPEG + case EAAC_CODEC_EAXMA: { + eaac_header temp_eaac = *eaac; /* equivalent to memcpy... I think */ + temp_eaac.loop_flag = 0; + temp_eaac.num_samples = num_samples[i]; + temp_eaac.stream_offset = offsets[i]; + + /* layers inside segments, how trippy */ + data->segments[i]->layout_data = build_layered_eaaudiocore_eaxma(streamData, &temp_eaac); + if (!data->segments[i]->layout_data) goto fail; + data->segments[i]->coding_type = coding_FFmpeg; + data->segments[i]->layout_type = layout_layered; + break; + } +#endif + #ifdef VGM_USE_MPEG case EAAC_CODEC_EALAYER3_V1: case EAAC_CODEC_EALAYER3_V2_PCM: @@ -734,6 +876,9 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *st mpeg_custom_config cfg = {0}; mpeg_custom_t type = (eaac->codec == 0x05 ? MPEG_EAL31b : (eaac->codec == 0x06) ? MPEG_EAL32P : MPEG_EAL32S); + temp_streamFile[i] = setup_eaac_streamfile(streamData, eaac->version,eaac->codec,eaac->streamed,0,0, offsets[i]); + if (!temp_streamFile[i]) goto fail; + data->segments[i]->codec_data = init_mpeg_custom(temp_streamFile[i], 0x00, &data->segments[i]->coding_type, eaac->channels, type, &cfg); if (!data->segments[i]->codec_data) goto fail; data->segments[i]->layout_type = layout_none; @@ -748,7 +893,6 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *st goto fail; } - /* setup segmented VGMSTREAMs */ if (!setup_layout_segmented(data)) goto fail; return data; @@ -804,6 +948,8 @@ static layered_layout_data* build_layered_eaaudiocore_eaxma(STREAMFILE *streamDa data->layers[i]->coding_type = coding_FFmpeg; data->layers[i]->layout_type = layout_none; + + xma_fix_raw_samples(data->layers[i], temp_streamFile, 0x00,stream_size, 0, 0,0); /* samples are ok? */ } #else goto fail; @@ -814,7 +960,6 @@ static layered_layout_data* build_layered_eaaudiocore_eaxma(STREAMFILE *streamDa } } - /* setup layered VGMSTREAMs */ if (!setup_layout_layered(data)) goto fail; close_streamfile(temp_streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_streamfile.h index 4d08a0ef2..8ece6be25 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_streamfile.h @@ -85,6 +85,8 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, case 0x05: /* EALayer3 v1 */ case 0x06: /* EALayer3 v2 "PCM" */ case 0x07: /* EALayer3 v2 "Spike" */ + case 0x0b: /* EAMP3 */ + case 0x0c: /* EAOpus */ data->skip_size = 0x08; data->data_size = data->block_size - data->skip_size; break; @@ -93,12 +95,7 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, data->skip_size = 0x08; data->data_size = read_32bitBE(data->physical_offset+0x04,streamfile); /* also block_size - 0x08 */ break; -#if 0 - case 0x0c: /* EA Opus */ - data->skip_size = 0x08; - data->data_size = data->block_size - data->skip_size; - break; -#endif + default: return total_read; } @@ -178,6 +175,9 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) { block_flag = (uint8_t)read_8bit(physical_offset+0x00,streamfile); block_size = read_32bitBE(physical_offset+0x00,streamfile) & 0x00FFFFFF; + if (block_size == 0) + break; /* bad data */ + if (data->version == 0 && block_flag != 0x00 && block_flag != 0x80) break; /* unknown block */ @@ -206,24 +206,14 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) { case 0x05: /* EALayer3 v1 */ case 0x06: /* EALayer3 v2 "PCM" */ case 0x07: /* EALayer3 v2 "Spike" */ + case 0x0b: /* EAMP3 */ + case 0x0c: /* EAOpus */ data_size = block_size - 0x08; break; case 0x0a: /* EATrax */ data_size = read_32bitBE(physical_offset+0x04,streamfile); /* also block_size - 0x08 */ break; -#if 0 - case 0x0c: { /* EAOpus */ - size_t done; - data_size = 0; - while (done < block_size - 0x08) { - size_t packet_size = read_16bitBE(physical_offset+0x08+done,streamfile); - done += 0x02 + packet_size; - data_size = 0x1a + packet_size; /* OggS page per Opus packet */ - } - break; - } -#endif default: return 0; @@ -251,7 +241,7 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) { * - EA-XMA: deflated XMA in multistreams (separate 1/2ch packets) * - EALayer3: MPEG granule 1 can go in the next block (in V2"P" mainly, others could use layout blocked_sns) * - EATrax: ATRAC9 frames can be split between blooks - * - EAOpus: + * - EAOpus: multiple Opus packets of frame size + Opus data per block */ static STREAMFILE* setup_eaac_streamfile(STREAMFILE *streamFile, int version, int codec, int streamed, int stream_number, int stream_count, off_t stream_offset) { STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index d1611eeeb..b38c90503 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -5,24 +5,24 @@ /* header version */ #define EA_VERSION_NONE -1 -#define EA_VERSION_V0 0x00 // ~early PC (when codec1 was used) -#define EA_VERSION_V1 0x01 // ~PC -#define EA_VERSION_V2 0x02 // ~PS era -#define EA_VERSION_V3 0x03 // ~PS2 era +#define EA_VERSION_V0 0x00 /* ~early PC (when codec1 was used) */ +#define EA_VERSION_V1 0x01 /* ~PC */ +#define EA_VERSION_V2 0x02 /* ~PS1 */ +#define EA_VERSION_V3 0x03 /* ~PS2 */ -/* platform constants (unasigned values seem internal only) */ -#define EA_PLATFORM_GENERIC -1 // typically Wii/X360/PS3/videos +/* platform constants (unassigned values seem internal only) */ +#define EA_PLATFORM_GENERIC -1 /* typically Wii/X360/PS3/videos */ #define EA_PLATFORM_PC 0x00 #define EA_PLATFORM_PSX 0x01 #define EA_PLATFORM_N64 0x02 #define EA_PLATFORM_MAC 0x03 #define EA_PLATFORM_SAT 0x04 #define EA_PLATFORM_PS2 0x05 -#define EA_PLATFORM_GC_WII 0x06 // reused later for Wii +#define EA_PLATFORM_GC_WII 0x06 #define EA_PLATFORM_XBOX 0x07 -#define EA_PLATFORM_X360 0x09 // also "Xenon" +#define EA_PLATFORM_X360 0x09 #define EA_PLATFORM_PSP 0x0A -#define EA_PLATFORM_PS3 0x0E // very rare [Need for Speed: Carbon (PS3)] +#define EA_PLATFORM_PS3 0x0E /* very rare [Need for Speed: Carbon (PS3)] */ #define EA_PLATFORM_3DS 0x14 /* codec constants (undefined are probably reserved, ie.- sx.exe encodes PCM24/DVI but no platform decodes them) */ @@ -62,13 +62,18 @@ #define EA_BLOCKID_LOC_DATA 0x53440000 /* "SD" */ #define EA_BLOCKID_LOC_END 0x53450000 /* "SE" */ -#define EA_BLOCKID_LOC_EN 0x0000454E -#define EA_BLOCKID_LOC_FR 0x00004652 -#define EA_BLOCKID_LOC_GE 0x00004745 -#define EA_BLOCKID_LOC_IT 0x00004954 -#define EA_BLOCKID_LOC_SP 0x00005350 -#define EA_BLOCKID_LOC_RU 0x00005255 -#define EA_BLOCKID_LOC_JA 0x00004A41 +#define EA_BLOCKID_LOC_EN 0x0000454E /* English */ +#define EA_BLOCKID_LOC_FR 0x00004652 /* French */ +#define EA_BLOCKID_LOC_GE 0x00004745 /* German, older */ +#define EA_BLOCKID_LOC_DE 0x00004445 /* German, newer */ +#define EA_BLOCKID_LOC_IT 0x00004954 /* Italian */ +#define EA_BLOCKID_LOC_SP 0x00005350 /* Castilian Spanish, older */ +#define EA_BLOCKID_LOC_ES 0x00004553 /* Castilian Spanish, newer */ +#define EA_BLOCKID_LOC_MX 0x00004D58 /* Mexican Spanish */ +#define EA_BLOCKID_LOC_RU 0x00005255 /* Russian */ +#define EA_BLOCKID_LOC_JA 0x00004A41 /* Japanese, older */ +#define EA_BLOCKID_LOC_JP 0x00004A50 /* Japanese, newer */ +#define EA_BLOCKID_LOC_PL 0x0000504C /* Polish */ #define EA_BNK_HEADER_LE 0x424E4B6C /* "BNKl" */ #define EA_BNK_HEADER_BE 0x424E4B62 /* "BNKb" */ @@ -97,19 +102,34 @@ typedef struct { int codec_config; } ea_header; -static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams); -static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams); +static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int standalone); +static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded); static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length, int bnk_version); static uint32_t read_patch(STREAMFILE* streamFile, off_t* offset); -static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream); static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea); -static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header *ea, off_t start_offset, int is_bnk, int total_streams); +static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header *ea, off_t start_offset, int is_bnk, int standalone); +static void update_ea_stream_size_and_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream, int standalone); /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) { - /* check extension; exts don't seem enforced by EA's tools, but usually: - * STR/ASF/MUS ~early, EAM ~mid, SNG/AUD ~late, rest uncommon/one game (ex. STRM: MySims Kingdom Wii) */ - if (!check_extensions(streamFile,"str,asf,mus,eam,sng,aud,sx,strm,xa,xsf,exa,stm,trj,trm")) + + /* check extension */ + /* they don't seem enforced by EA's tools but usually: + * .asf: ~early [ex. Need for Speed (PC)] + * .str: ~early [ex. FIFA 2002 (PS1)] + * .eam: ~mid (fake?) + * .exa: ~mid [ex. 007 - From Russia with Love] + * .sng: ~late (fake?) + * .aud: ~late [ex. FIFA 14 (3DS)] + * .strm: MySims Kingdom (Wii) + * .stm: FIFA 12 (3DS) + * .sx/xa: fake? + * .hab: GoldenEye - Rogue Agent (inside .big) + * .xsf: 007 - Agent Under Fire (Xbox) + * .gsf: 007 - Everything or Nothing (GC) + * .mus: map/mpf+mus only? + * (extensionless): SSX (PS2) (inside .big) */ + if (!check_extensions(streamFile,"asf,str,eam,exa,sng,aud,sx,xa,strm,stm,hab,xsf,gsf,mus,")) goto fail; /* check header */ @@ -117,16 +137,21 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) { read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_EN) && /* "SHEN" */ read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_FR) && /* "SHFR" */ read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_GE) && /* "SHGE" */ + read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_DE) && /* "SHDE" */ read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_IT) && /* "SHIT" */ read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_SP) && /* "SHSP" */ + read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_ES) && /* "SHES" */ + read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_MX) && /* "SHMX" */ read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_RU) && /* "SHRU" */ - read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JA)) /* "SHJA" */ + read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JA) && /* "SHJA" */ + read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JP) && /* "SHJP" */ + read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_PL)) /* "SHPL" */ goto fail; /* Stream is divided into blocks/chunks: SCHl=audio header, SCCl=count of SCDl, SCDl=data xN, SCLl=loop end, SCEl=end. - * Video uses picture blocks (MVhd/MV0K/etc) and sometimes multiaudio blocks (SHxx/SCxx/SDxx/SExx where xx=language=EN/FR/GE/IT/SP/RU/JA). + * Video uses picture blocks (MVhd/MV0K/etc) and sometimes multiaudio blocks (SHxx/SCxx/SDxx/SExx where xx=language). * The number/size is affected by: block rate setting, sample rate, channels, CPU location (SPU/main/DSP/others), etc */ - return parse_schl_block(streamFile, 0x00, 0); + return parse_schl_block(streamFile, 0x00, 1); fail: return NULL; @@ -137,8 +162,12 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) { off_t offset; /* check extension */ - /* .bnk: sfx, .sdt: speech, .mus: streams/jingles (rare) */ - if (!check_extensions(streamFile,"bnk,sdt,mus")) + /* .bnk: common + * .sdt: Harry Potter games + * .mus: streams/jingles (rare) + * .abk: GoldenEye - Rogue Agent + * .ast: FIFA 2004 (inside .big) */ + if (!check_extensions(streamFile,"bnk,sdt,mus,abk,ast")) goto fail; /* check header (doesn't use EA blocks, otherwise very similar to SCHl) */ @@ -261,7 +290,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { goto fail; bnk_target_stream = read_32bit(target_entry_offset + 0x04, streamFile) + 1; - vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, total_sounds); + vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, 1); if (!vgmstream) goto fail; break; @@ -280,7 +309,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, astData) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(astData, schl_offset, total_sounds); + vgmstream = parse_schl_block(astData, schl_offset, 0); if (!vgmstream) goto fail; break; @@ -290,6 +319,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { break; } + vgmstream->num_streams = total_sounds; close_streamfile(astData); return vgmstream; @@ -339,10 +369,11 @@ VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, datFile) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(datFile, schl_offset, total_sounds); + vgmstream = parse_schl_block(datFile, schl_offset, 0); if (!vgmstream) goto fail; + vgmstream->num_streams = total_sounds; close_streamfile(datFile); return vgmstream; @@ -351,97 +382,279 @@ fail: return NULL; } -/* EA IDX/BIG combo - basically a set of HDR/DAT compiled into one file */ -VGMSTREAM * init_vgmstream_ea_idx_big(STREAMFILE *streamFile) { - int target_stream = streamFile->stream_index, total_sounds, subsound_index; - uint32_t i, num_hdr; - uint16_t hdr_id, hdr_subid; - uint8_t userdata_size, hdr_sounds; - off_t entry_offset, hdr_offset, base_offset, schl_offset, offset_mult; - //size_t hdr_size; - char stream_name[STREAM_NAME_SIZE]; - STREAMFILE *bigFile = NULL; - VGMSTREAM *vgmstream = NULL; - int32_t (*read_32bit)(off_t,STREAMFILE*); - int16_t (*read_16bit)(off_t,STREAMFILE*); - /* seems to always start with 0x00000001 */ - if (read_32bitLE(0x00, streamFile) != 0x00000001 && - read_32bitBE(0x00, streamFile) != 0x00000001) - goto fail; +/* open map/mpf+mus pairs that aren't exact pairs, since EA's games can load any combo */ +static STREAMFILE * open_mapfile_pair(STREAMFILE *streamFile) { + static const char *const mapfile_pairs[][2] = { + /* standard cases, replace map part with mus part (from the end to preserve prefixes) */ + {"MUS_CTRL.MPF","MUS_STR.MUS"}, /* GoldenEye - Rogue Agent (PS2) */ + {"mus_ctrl.mpf","mus_str.mus"}, /* GoldenEye - Rogue Agent (others) */ + {".mpf","_main.mus"}, /* 007 - Everything or Nothing (GC) */ + /* hack when when multiple maps point to the same mus, uses name before "+" + * ex. ZZZTR00A.TRJ+ZTR00PGR.MAP or ZZZTR00A.TRJ+ZTR00R0A.MAP both point to ZZZTR00A.TRJ */ + {"+",""}, /* Need for Speed III (PS1) */ + }; + STREAMFILE *musFile = NULL; + char file_name[PATH_LIMIT]; + int pair_count = (sizeof(mapfile_pairs)/sizeof(mapfile_pairs[0])); + int i; + size_t file_len, map_len; - bigFile = open_streamfile_by_ext(streamFile, "big"); - if (!bigFile) - goto fail; + get_streamfile_filename(streamFile, file_name, PATH_LIMIT); + file_len = strlen(file_name); - if (read_32bitBE(0x00, bigFile) != EA_BLOCKID_HEADER) - goto fail; + for (i = 0; i < pair_count; i++) { + const char *map_name = mapfile_pairs[i][0]; + const char *mus_name = mapfile_pairs[i][1]; + map_len = strlen(map_name); - /* use number of files for endianness check */ - if (guess_endianness32bit(0x04,streamFile)) { - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } - - num_hdr = read_32bit(0x04, streamFile); - if (read_32bit(0x54,streamFile) != num_hdr) - goto fail; - - if (target_stream == 0) target_stream = 1; - schl_offset = 0; - total_sounds = 0; - schl_offset = 0xFFFFFFFF; - - for (i = 0; i < num_hdr; i++) { - entry_offset = 0x58 + 0x10 * i; - //hdr_size = read_32bit(entry_offset + 0x04, streamFile); - hdr_offset = read_32bit(entry_offset + 0x08, streamFile); - base_offset = read_32bit(entry_offset + 0x0C, streamFile); - - hdr_id = read_16bit(hdr_offset + 0x00, streamFile); - hdr_subid = read_16bit(hdr_offset + 0x02, streamFile); - userdata_size = read_8bit(hdr_offset + 0x04, streamFile) & 0x0F; - hdr_sounds = read_8bit(hdr_offset + 0x05, streamFile); - offset_mult = (off_t)read_8bit(hdr_offset + 0x07, streamFile) * 0x0100 + 0x0100; - - if (target_stream > total_sounds && target_stream <= total_sounds + hdr_sounds) { - schl_offset = base_offset + (off_t)read_16bitBE(hdr_offset + 0x0C + (0x02+userdata_size) * (target_stream-total_sounds-1), streamFile) * offset_mult; - subsound_index = target_stream - total_sounds; - - /* There are no filenames but we can add IDs to stream name for better organization */ - if (hdr_subid != 0xFFFF) - snprintf(stream_name, STREAM_NAME_SIZE, "%03d_%02d_%d", hdr_id, hdr_subid, subsound_index); - else - snprintf(stream_name, STREAM_NAME_SIZE, "%03d_%d", hdr_id, subsound_index); + if (map_name[0] == '+') { + /* use name before "+" */ + char *mod_name = strchr(file_name, '+'); + if (mod_name == NULL) + continue; + mod_name[0] = '\0'; + } + else { + /* replace map_name with expected mus_name */ + if (file_len < map_len) + continue; + if (strncmp(file_name+(file_len - map_len), map_name, map_len) != 0) + continue; + file_name[file_len - map_len] = '\0'; + strcat(file_name, mus_name); } - total_sounds += hdr_sounds; + musFile = open_streamfile_by_filename(streamFile, file_name); + if (musFile) return musFile; + + get_streamfile_filename(streamFile, file_name, PATH_LIMIT); /* reset for next loop */ } - if (schl_offset == 0xFFFFFFFF) + return NULL; +} + +/* EA MAP/MUS combo - used in older games for interactive music (for EA's PathFinder tool) */ +VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE *streamFile) { + uint8_t version, num_sounds, num_userdata, userdata_size; + off_t section_offset, schl_offset; + STREAMFILE *musFile = NULL; + VGMSTREAM *vgmstream = NULL; + int target_stream = streamFile->stream_index; + + /* check extension */ + if (!check_extensions(streamFile, "map,lin,mpf")) goto fail; - if (read_32bitBE(schl_offset, bigFile) != EA_BLOCKID_HEADER) + /* always big endian */ + if (read_32bitBE(0x00, streamFile) != 0x50464478) /* "PFDx" */ goto fail; - vgmstream = parse_schl_block(bigFile, schl_offset, total_sounds); + version = read_8bit(0x04, streamFile); + if (version > 1) goto fail; + + musFile = open_streamfile_by_ext(streamFile, "mus"); + if (!musFile) { + musFile = open_mapfile_pair(streamFile); + if (!musFile) goto fail; + } + + /* + * 0x04: ??? + * 0x05: intro segment + * 0x06: number of segments + * 0x07: userdata entry size (incorrect?) + * 0x08: three zeroes + * 0x0b: number of userdata entries + * 0x0c: section 1 start + */ + num_sounds = read_8bit(0x06, streamFile); + userdata_size = read_8bit(0x07, streamFile); + num_userdata = read_8bit(0x0b, streamFile); + section_offset = 0x0c; + + /* section 1: contains information about segment playback order */ + section_offset += num_sounds * 0x1c; + + /* section 2: userdata, specific to game and track */ + section_offset += num_userdata * userdata_size; + + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || num_sounds == 0 || target_stream > num_sounds) + goto fail; + + /* section 3: sound offset table */ + schl_offset = read_32bitBE(section_offset + (target_stream - 1) * 0x04, streamFile); + if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER) + goto fail; + + vgmstream = parse_schl_block(musFile, schl_offset, 0); if (!vgmstream) goto fail; - strncpy(vgmstream->stream_name, stream_name, STREAM_NAME_SIZE); - close_streamfile(bigFile); + vgmstream->num_streams = num_sounds; + close_streamfile(musFile); return vgmstream; fail: - close_streamfile(bigFile); + close_streamfile(musFile); + return NULL; +} + +/* EA MPF/MUS combo - used in newer 6th gen games for interactive music (for EA's PathFinder tool) */ +VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) { + off_t section_offset, entry_offset, subentry_num, eof_offset, off_mult, schl_offset; + size_t sec2_size; + uint16_t sec1_num; + uint8_t version, sub_version, sec2_num, sec3_num, sec4_num; + int32_t(*read_32bit)(off_t, STREAMFILE*); + int16_t(*read_16bit)(off_t, STREAMFILE*); + STREAMFILE *musFile = NULL; + VGMSTREAM *vgmstream = NULL; + int target_stream = streamFile->stream_index, total_streams, big_endian; + + /* check extension */ + if (!check_extensions(streamFile, "mpf")) + goto fail; + + /* detect endianness */ + if (read_32bitBE(0x00, streamFile) == 0x50464478) { /* "PFDx" */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + big_endian = 1; + } else if (read_32bitBE(0x00, streamFile) == 0x78444650) { /* "xDFP" */ + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + big_endian = 0; + } else { + goto fail; + } + + version = read_8bit(0x04, streamFile); + sub_version = read_8bit(0x05, streamFile); + + if (version < 3 || version > 5) goto fail; + if (version == 5 && sub_version > 2) goto fail; /* newer version using SNR/SNS */ + + musFile = open_streamfile_by_ext(streamFile, "mus"); + if (!musFile) { + musFile = open_mapfile_pair(streamFile); + if (!musFile) goto fail; + } + + /* HACK: number of sub-entries is stored in bitstreams that are different in LE and BE */ + /* I can't figure it out, so let's just use a workaround for now */ + + if (version == 3 && sub_version == 1) { /* SSX Tricky */ + /* we need to go through the first two sections to find sound table */ + sec1_num = read_16bit(0x12, streamFile); + sec2_size = read_8bit(0x0e, streamFile); + sec2_num = read_8bit(0x0f, streamFile); + sec3_num = read_8bit(0x10, streamFile); + sec4_num = read_8bit(0x11, streamFile); + + /* get the last entry offset */ + section_offset = 0x24; + entry_offset = read_16bit(section_offset + (sec1_num - 1) * 0x02, streamFile) * 0x04; + subentry_num = read_8bit(entry_offset + 0x0b, streamFile); + + section_offset = entry_offset + 0x0c + subentry_num * 0x04; + section_offset += align_size_to_block(sec2_num * sec2_size, 0x04); + section_offset += sec3_num * 0x04; + section_offset += sec4_num * 0x04; + + entry_offset = read_32bit(section_offset, streamFile) * 0x04; + section_offset = read_32bit(entry_offset + 0x00, streamFile) * 0x04; + eof_offset = get_streamfile_size(streamFile); + total_streams = (eof_offset - section_offset) / 0x08; + off_mult = 0x04; + } else if (version == 3 && sub_version == 4) { /* Harry Potter and the Chamber of Secrets */ + sec1_num = read_16bit(0x12, streamFile); + sec2_size = read_8bit(0x0e, streamFile); + sec2_num = read_8bit(0x0f, streamFile); + sec3_num = read_8bit(0x10, streamFile); + sec4_num = read_8bit(0x11, streamFile); + + /* get the last entry offset */ + section_offset = 0x24; + entry_offset = read_16bit(section_offset + (sec1_num - 1) * 0x02, streamFile) * 0x04; + if (big_endian) { + subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 19) & 0xFF; + } else { + subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 16) & 0xFF; + } + + section_offset = entry_offset + 0x0c + subentry_num * 0x04; + section_offset += align_size_to_block(sec2_num * sec2_size, 0x04); + section_offset += sec3_num * 0x04; + section_offset += sec4_num * 0x04; + + entry_offset = read_32bit(section_offset, streamFile) * 0x04; + section_offset = read_32bit(entry_offset + 0x00, streamFile) * 0x04; + eof_offset = read_32bit(entry_offset + 0x04, streamFile) * 0x04; + total_streams = (eof_offset - section_offset) / 0x08; + off_mult = 0x04; + } else if (version == 4) { /* SSX 3, Need for Speed: Underground 2 */ + /* we need to go through the first two sections to find sound table */ + sec1_num = read_16bit(0x12, streamFile); + sec2_num = read_8bit(0x0f, streamFile); + + /* get the last entry offset */ + section_offset = 0x20; + entry_offset = read_16bit(section_offset + (sec1_num - 1) * 0x02, streamFile) * 0x04; + if (big_endian) { + subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 15) & 0xFF; + } else { + subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 20) & 0xFF; + } + + section_offset = entry_offset + 0x10 + subentry_num * 0x04; + entry_offset = read_16bit(section_offset + (sec2_num - 1) * 0x02, streamFile) * 0x04; + if (big_endian) { + subentry_num = (read_32bitBE(entry_offset + 0x0c, streamFile) >> 10) & 0xFF; + } else { + subentry_num = (read_32bitBE(entry_offset + 0x0c, streamFile) >> 8) & 0xFF; + } + + section_offset = entry_offset + 0x10 + subentry_num * 0x10; + + entry_offset = read_32bit(section_offset, streamFile) * 0x04; + section_offset = read_32bit(entry_offset + 0x00, streamFile) * 0x04; + eof_offset = read_32bit(entry_offset + 0x04, streamFile) * 0x04; + total_streams = (eof_offset - section_offset) / 0x08; + off_mult = 0x80; + } else if (version == 5) { /* Need for Speed: Most Wanted, Need for Speed: Carbon */ + section_offset = read_32bit(0x34, streamFile); + eof_offset = read_32bit(0x38, streamFile); + total_streams = (eof_offset - section_offset) / 0x08; + off_mult = 0x80; + } else { + goto fail; + } + + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || total_streams == 0 || target_stream > total_streams) + goto fail; + + schl_offset = read_32bit(section_offset + (target_stream - 1) * 0x08 + 0x00, streamFile) * off_mult; + if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER) + goto fail; + + vgmstream = parse_schl_block(musFile, schl_offset, 0); + if (!vgmstream) + goto fail; + + vgmstream->num_streams = total_streams; + close_streamfile(musFile); + return vgmstream; + +fail: + close_streamfile(musFile); return NULL; } /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ -static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams) { +static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int standalone) { off_t start_offset, header_offset; size_t header_size; ea_header ea = { 0 }; @@ -462,19 +675,20 @@ static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int to start_offset = offset + header_size; /* starts in "SCCl" (skipped in block layout) or very rarely "SCDl" and maybe movie blocks */ /* rest is common */ - return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, 0, total_streams); + return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, 0, standalone); fail: return NULL; } /* EA BNK with variable header - from EA games SFXs; also created by sx.exe */ -static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams) { +static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded) { off_t header_offset, start_offset, test_offset, table_offset; size_t header_size; ea_header ea = {0}; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + VGMSTREAM *vgmstream = NULL; int i, bnk_version; int total_bnk_sounds, real_bnk_sounds = 0; @@ -525,7 +739,7 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta real_bnk_sounds++; /* ABK points at absolute indexes, i.e. with dummies included */ - if (total_streams != 0) { + if (is_embedded != 0) { if (target_stream - 1 == i) header_offset = offset + table_offset + 0x04 * i + test_offset; } @@ -552,14 +766,20 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta start_offset = ea.offsets[0]; /* first channel, presumably needed for MPEG */ /* rest is common */ - return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version, total_streams ? total_streams : real_bnk_sounds); + vgmstream = init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version, 0); + if (!vgmstream) goto fail; + if (!is_embedded) { + vgmstream->num_streams = real_bnk_sounds; + } + + return vgmstream; fail: return NULL; } /* inits VGMSTREAM from a EA header */ -static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header * ea, off_t start_offset, int bnk_version, int total_streams) { +static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header * ea, off_t start_offset, int bnk_version, int standalone) { VGMSTREAM * vgmstream = NULL; int i, ch; int is_bnk = bnk_version; @@ -606,9 +826,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ vgmstream->layout_type = layout_blocked_ea_schl; } - vgmstream->num_streams = total_streams; - //vgmstream->stream_size = ; //todo needed for kbps info - /* EA usually implements their codecs in all platforms (PS2/WII do EAXA/MT/EALAYER3) and * favors them over platform's natives (ex. EAXA vs VAG/DSP). * Unneeded codecs are removed over time (ex. LAYER3 when EALAYER3 was introduced). */ @@ -790,15 +1007,11 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ vgmstream->ch[i].offset = ea->offsets[i]; } } + + /* TODO: Figure out how to get stream size for BNK sounds */ } - else if (vgmstream->layout_type == layout_blocked_ea_schl) { - /* regular SCHls, except ATRAC3plus */ - if (total_streams == 0) { - /* HACK: fix num_samples for streams with multiple SCHl. Need to eventually get rid of this */ - int total_samples = get_ea_stream_total_samples(streamFile, start_offset, vgmstream); - if (total_samples > vgmstream->num_samples) - vgmstream->num_samples = total_samples; - } + else { + update_ea_stream_size_and_samples(streamFile, start_offset, vgmstream, standalone); } return vgmstream; @@ -1188,38 +1401,52 @@ fail: return 0; } -/* Get total samples by parsing block headers, needed when multiple files are stitched together. - * Some EA files (.mus/eam/sng/etc) concat many small subfiles, used for interactive/mapped - * music (.map/lin). Subfiles always share header, except num_samples. */ -static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream) { - int num_samples = 0; - int multiple_schl = 0; +static void update_ea_stream_size_and_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM *vgmstream, int standalone) { + uint32_t block_id; + int32_t num_samples; + size_t stream_size, file_size; + int multiple_schl; - /* calc num_samples as playable data size varies between files/blocks */ - { - vgmstream->next_block_offset = start_offset; - do { - uint32_t block_id = read_32bitBE(vgmstream->next_block_offset+0x00,streamFile); - if (block_id == EA_BLOCKID_HEADER) /* "SCHl" start block (movie "SHxx" shouldn't use multi files) */ - multiple_schl = 1; + stream_size = 0, num_samples = 0, multiple_schl = 0; + file_size = get_streamfile_size(streamFile); + vgmstream->next_block_offset = start_offset; - block_update_ea_schl(vgmstream->next_block_offset,vgmstream); - num_samples += vgmstream->current_block_samples; + while (vgmstream->next_block_offset < file_size) { + block_update_ea_schl(vgmstream->next_block_offset, vgmstream); + + block_id = read_32bitBE(vgmstream->current_block_offset + 0x00, streamFile); + if (block_id == EA_BLOCKID_END) { /* banks should never contain movie "SHxx" */ + if (!standalone) + break; + } + else if (block_id == EA_BLOCKID_HEADER) { /* "SCHl" start block (movie "SHxx" shouldn't use multi files) */ + multiple_schl = 1; } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - /* reset after getting samples */ - block_update(start_offset,vgmstream); + /* HACK: fix num_samples for streams with multiple SCHl. Need to eventually get rid of this. + * Get total samples by parsing block headers, needed when multiple files are stitched together. + * Some EA files (.mus/eam/sng/etc) concat many small subfiles, used for interactive/mapped + * music (.map/lin). Subfiles always share header, except num_samples. */ + num_samples += vgmstream->current_block_samples; + + /* Stream size is almost never provided in bank files so we have to calc it manually */ + if (vgmstream->current_block_samples != 0) { + stream_size += vgmstream->next_block_offset - vgmstream->current_block_offset - 0x0c; + } } + /* reset once we're done */ + block_update(start_offset, vgmstream); + /* only use calculated samples with multiple subfiles (rarely header samples may be less due to padding) */ - if (multiple_schl) { - ;VGM_LOG("EA SCHl: multiple SCHl found\n"); - return num_samples; - } - else { - return 0; + if (standalone && multiple_schl) { + VGM_LOG("EA SCHl: multiple SCHl found\n"); + if (num_samples > vgmstream->num_samples) { + vgmstream->num_samples = num_samples; + } } + + vgmstream->stream_size = stream_size; } /* find data start offset inside the first SCDl; not very elegant but oh well */ @@ -1243,10 +1470,15 @@ static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_EN: /* "SDEN" */ case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_FR: /* "SDFR" */ case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_GE: /* "SDGE" */ + case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_DE: /* "SDDE" */ case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_IT: /* "SDIT" */ case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_SP: /* "SDSP" */ + case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_ES: /* "SDES" */ + case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_MX: /* "SDMX" */ case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_RU: /* "SDRU" */ case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_JA: /* "SDJA" */ + case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_JP: /* "SDJP" */ + case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_PL: /* "SDPL" */ offset = read_32bit(block_offset+0x0c,streamFile); /* first value seems ok, second is something else in EALayer3 */ return block_offset + 0x0c + ea->channels*0x04 + offset; case 0x00000000: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/emff.c b/Frameworks/vgmstream/vgmstream/src/meta/emff.c deleted file mode 100644 index 79928e66b..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/emff.c +++ /dev/null @@ -1,179 +0,0 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../util.h" - -/* EMFF - Eidos Music File Format (PS2), -Legacy of Kain - Defiance, possibly more... */ -VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - int frequency; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("emff",filename_extension(filename))) goto fail; - - /* do some checks on the file, cause we have no magic words to check the header... - it seems if 0x800 and 0x804 = 0 then the file has only audio, if 0x800 = 1 - it has a text section, if both are 1 it's video with a text section included... */ - if (read_32bitBE(0x800,streamFile) == 0x01000000 || /* "0x01000000" */ - read_32bitBE(0x804,streamFile) == 0x01000000) /* "0x01000000" */ - goto fail; - - frequency = read_32bitLE(0x0,streamFile); - channel_count = read_32bitLE(0xC,streamFile); - - if (frequency > 48000 || - channel_count > 8) { - goto fail; - } - - loop_flag = (read_32bitLE(0x4,streamFile) != 0xFFFFFFFF); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->sample_rate = frequency; - vgmstream->channels = channel_count; - vgmstream->coding_type = coding_PSX; - - vgmstream->layout_type = layout_blocked_emff_ps2; - vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_EMFF_PS2; - - /* open the file for reading */ - { - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - } - } - - /* Calc num_samples */ - block_update_emff_ps2(start_offset,vgmstream); - vgmstream->num_samples = read_32bitLE(0x8,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitLE(0x28,streamFile)-start_offset)*28/16/channel_count; - vgmstream->loop_end_sample = read_32bitLE(0x8,streamFile); - } - - return vgmstream; - -/* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - - -/* EMFF - Eidos Music File Format (NGC/WII), -found in Tomb Raider Legend/Anniversary/Underworld, possibly more... */ -VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - int frequency; - int i; - int j; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("emff",filename_extension(filename))) goto fail; - - /* do some checks on the file, cause we have no magic words to check the header... - it seems if 0x800 and 0x804 = 0 then the file has only audio, if 0x800 = 1 - it has a text section, if both are 1 it's video with a text section included... */ - if (read_32bitBE(0x800,streamFile) == 0x00000001 || /* "0x00000001" */ - read_32bitBE(0x804,streamFile) == 0x00000001) /* "0x00000001" */ - goto fail; - - frequency = read_32bitBE(0x0,streamFile); - channel_count = read_32bitBE(0xC,streamFile); - - if (frequency > 48000 || - channel_count > 8) { - goto fail; - } - - loop_flag = (read_32bitBE(0x4,streamFile) != 0xFFFFFFFF); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->sample_rate = frequency; - vgmstream->channels = channel_count; - vgmstream->coding_type = coding_NGC_DSP; - - /* Retrieving coefs and loops, depending on the file layout... */ - /* Found in Tomb Raider - Legend for GameCube */ - if (read_32bitBE(0xC8,streamFile) > 0x0) { - off_t coef_table[8] = {0xC8,0xF6,0x124,0x152,0x180,0x1AE,0x1DC,0x20A}; - for (j=0;jchannels;j++) { - for (i=0;i<16;i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); - } - } - /* Found in Tomb Raider - Anniversary for WII */ - } else if (read_32bitBE(0xCC,streamFile) > 0x0) { - off_t coef_table[8] = {0xCC,0xFA,0x128,0x156,0x184,0x1B2,0x1E0,0x20E}; - for (j=0;jchannels;j++) { - for (i=0;i<16;i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); - } -} - /* Found in Tomb Raider - Underworld for WII */ - } else if (read_32bitBE(0x2D0,streamFile) > 0x0) { - off_t coef_table[8] = {0x2D0,0x2FE,0x32C,0x35A,0x388,0x3B6,0x3E4,0x412}; - for (j=0;jchannels;j++) { - for (i=0;i<16;i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); - } -} - - } else { - goto fail; - } - - vgmstream->layout_type = layout_blocked_emff_ngc; - vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_EMFF_NGC; - - /* open the file for reading */ - { - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - } - } - - /* Calc num_samples */ - block_update_emff_ngc(start_offset,vgmstream); - vgmstream->num_samples = read_32bitBE(0x8,streamFile);; - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitBE(0x28,streamFile))*14/8/channel_count; - vgmstream->loop_end_sample = read_32bitBE(0x8,streamFile); - } - - return vgmstream; - -/* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fag.c b/Frameworks/vgmstream/vgmstream/src/meta/fag.c new file mode 100644 index 000000000..473e77c66 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/fag.c @@ -0,0 +1,52 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* .FAG - from Jackie Chan: Stuntmaster (PS1) */ +VGMSTREAM * init_vgmstream_fag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + size_t stream_size; + int loop_flag, channel_count; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* checks */ + if (!check_extensions(streamFile,"fag")) + goto fail; + + total_subsongs = read_32bitLE(0x00,streamFile); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + if (total_subsongs > 2) + goto fail; + loop_flag = 0; + channel_count = 2; + + start_offset = read_32bitLE(0x04 + 0x04*(target_subsong-1),streamFile); + stream_size = read_32bitLE(0x04 + 0x04*total_subsongs + 0x04*(target_subsong-1),streamFile) - start_offset; /* end offset */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_FAG; + vgmstream->sample_rate = 24000; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); + + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c index a78c9af01..80156dfd1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c @@ -363,6 +363,8 @@ VGMSTREAM * init_vgmstream_fsb(STREAMFILE *streamFile) { if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, fsb.stream_offset,fsb.stream_size, 0, 0,0); /* samples look ok */ break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c index d06717ec6..a9445b5d7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c @@ -150,6 +150,12 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { /* when start is 0 seems the song repeats with no real looping (ex. Sonic Boom Fire & Ice jingles) */ fsb5.loop_flag = (fsb5.loop_start != 0x00); + + /* ignore wrong loops in some files [Pac-Man CE2 Plus (Switch) pce2p_bgm_ajurika_*.fsb] */ + if (fsb5.loop_start == 0x3c && fsb5.loop_end == 0x007F007F && + fsb5.num_samples > fsb5.loop_end + 100000) { /* arbitrary limit */ + fsb5.loop_flag = 0; + } break; case 0x04: /* free comment, or maybe SFX info */ break; @@ -182,7 +188,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { // /* found in some XMA2/Vorbis/FADPCM */ // break; default: - VGM_LOG("FSB5: unknown extraflag 0x%x at %"PRIx64" + 0x04 (size 0x%x)\n", extraflag_type, (off64_t)extraflag_offset, extraflag_size); + VGM_LOG("FSB5: unknown extraflag 0x%x at %x + 0x04 (size 0x%x)\n", extraflag_type, (uint32_t)extraflag_offset, extraflag_size); break; } @@ -308,7 +314,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { break; #ifdef VGM_USE_FFMPEG - case 0x0A: {/* FMOD_SOUND_FORMAT_XMA [Dark Souls 2 (X360)] */ + case 0x0A: {/* FMOD_SOUND_FORMAT_XMA [Minecraft Story Mode (X360)] */ uint8_t buf[0x100]; int bytes, block_size, block_count; @@ -317,9 +323,11 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, fsb5.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, fsb5.stream_offset,fsb5.stream_size); - if ( !vgmstream->codec_data ) goto fail; + if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, fsb5.stream_offset,fsb5.stream_size, 0, 0,0); /* samples look ok */ break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c index bdadd6c8b..acdf9d01d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/genh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/genh.c @@ -4,7 +4,6 @@ #include "../util.h" - /* known GENH types */ typedef enum { PSX = 0, /* PSX ADPCM */ @@ -31,6 +30,7 @@ typedef enum { XMA2 = 21, /* raw XMA2 */ FFMPEG = 22, /* any headered FFmpeg format */ AC3 = 23, /* AC3/SPDIF */ + PCFX = 24, /* PC-FX ADPCM */ } genh_type; typedef struct { @@ -52,8 +52,10 @@ typedef struct { int loop_flag; - int32_t coef[2]; - int32_t coef_splitted[2]; + int32_t coef_offset; + int32_t coef_spacing; + int32_t coef_split_offset; + int32_t coef_split_spacing; int32_t coef_type; int32_t coef_interleave_type; int coef_big_endian; @@ -111,6 +113,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case AC3: case FFMPEG: coding = coding_FFmpeg; break; #endif + case PCFX: coding = coding_PCFX; break; default: goto fail; } @@ -183,6 +186,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { } break; + + case coding_PCFX: + vgmstream->interleave_block_size = genh.interleave; + vgmstream->layout_type = layout_interleave; + if (genh.codec_mode >= 0 && genh.codec_mode <= 3) + vgmstream->codec_config = genh.codec_mode; + break; + case coding_MS_IMA: if (!genh.interleave) goto fail; /* creates garbage */ @@ -233,16 +244,16 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { for (i=0;ichannels;i++) { int16_t (*read_16bit)(off_t , STREAMFILE*) = genh.coef_big_endian ? read_16bitBE : read_16bitLE; - /* normal/split coefs bit flag */ - if ((genh.coef_type & 1) == 0) { /* not set: normal coefs, all 16 interleaved into one array */ - for (j=0;j<16;j++) { - vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef[i]+j*2,streamFile); + /* normal/split coefs */ + if ((genh.coef_type & 1) == 0) { /* normal mode */ + for (j = 0; j < 16; j++) { + vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, streamFile); } } - else { /* set: split coefs, 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right */ - for (j=0;j<8;j++) { - vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(genh.coef[i]+j*2,streamFile); - vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(genh.coef_splitted[i]+j*2,streamFile); + else { /* split coefs, 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right */ + for (j = 0; j < 8; j++) { + vgmstream->ch[i].adpcm_coef[j*2] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, streamFile); + vgmstream->ch[i].adpcm_coef[j*2+1] = read_16bit(genh.coef_split_offset + i*genh.coef_split_spacing + j*2, streamFile); } } } @@ -304,7 +315,6 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { else { goto fail; } - if (bytes <= 0) goto fail; ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size); if ( !ffmpeg_data ) goto fail; @@ -313,8 +323,9 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { vgmstream->codec_data = ffmpeg_data; vgmstream->layout_type = layout_none; - /* force encoder delay */ - if (genh.skip_samples_mode && genh.skip_samples >= 0) { + if (genh.codec == XMA1 || genh.codec == XMA2) { + xma_fix_raw_samples(vgmstream, streamFile, genh.start_offset,genh.data_size, 0, 0,0); + } else if (genh.skip_samples_mode && genh.skip_samples >= 0) { /* force encoder delay */ ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples); } @@ -344,10 +355,10 @@ fail: static int parse_genh(STREAMFILE * streamFile, genh_header * genh) { size_t header_size; - genh->channels = read_32bitLE(0x4,streamFile); + genh->channels = read_32bitLE(0x04,streamFile); - genh->interleave = read_32bitLE(0x8,streamFile); - genh->sample_rate = read_32bitLE(0xc,streamFile); + genh->interleave = read_32bitLE(0x08,streamFile); + genh->sample_rate = read_32bitLE(0x0c,streamFile); genh->loop_start_sample = read_32bitLE(0x10,streamFile); genh->loop_end_sample = read_32bitLE(0x14,streamFile); @@ -359,37 +370,54 @@ static int parse_genh(STREAMFILE * streamFile, genh_header * genh) { genh->start_offset = 0x800; header_size = 0x800; } - /* check for audio data start past header end */ - if (header_size > genh->start_offset) goto fail; - genh->coef[0] = read_32bitLE(0x24,streamFile); - genh->coef[1] = read_32bitLE(0x28,streamFile); - genh->coef_interleave_type = read_32bitLE(0x2C,streamFile); + if (header_size > genh->start_offset) /* audio data start past header end */ + goto fail; + if (header_size < 0x24) /* absolute minimum for GENH */ + goto fail; + + /* DSP coefficients */ + if (header_size >= 0x30) { + genh->coef_offset = read_32bitLE(0x24,streamFile); + if (genh->channels == 2) /* old meaning, "coef right offset" */ + genh->coef_spacing = read_32bitLE(0x28,streamFile) - genh->coef_offset; + else if (genh->channels > 2) /* new meaning, "coef spacing" */ + genh->coef_spacing = read_32bitLE(0x28,streamFile); + genh->coef_interleave_type = read_32bitLE(0x2C,streamFile); + } /* DSP coefficient variants */ - /* bit 0 flag - split coefs (2 arrays) */ - /* bit 1 flag - little endian coefs (for some 3DS) */ - genh->coef_type = read_32bitLE(0x30,streamFile); - genh->coef_big_endian = ((genh->coef_type & 2) == 0); + if (header_size >= 0x34) { + /* bit 0 flag - split coefs (2 arrays) */ + /* bit 1 flag - little endian coefs (for some 3DS) */ + genh->coef_type = read_32bitLE(0x30,streamFile); + genh->coef_big_endian = ((genh->coef_type & 2) == 0); + } - /* when using split coefficients, 2nd array is at: */ - genh->coef_splitted[0] = read_32bitLE(0x34,streamFile); - genh->coef_splitted[1] = read_32bitLE(0x38,streamFile); + /* DSP split coefficients' 2nd array */ + if (header_size >= 0x3c) { + genh->coef_split_offset = read_32bitLE(0x34,streamFile); + if (genh->channels == 2) /* old meaning, "coef right offset" */ + genh->coef_split_spacing = read_32bitLE(0x38,streamFile) - genh->coef_split_offset; + else if (genh->channels > 2) /* new meaning, "coef spacing" */ + genh->coef_split_spacing = read_32bitLE(0x38,streamFile); + } + + /* extended fields */ + if (header_size >= 0x54) { + genh->num_samples = read_32bitLE(0x40,streamFile); + genh->skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */ + genh->skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */ + genh->codec_mode = read_8bit(0x4b,streamFile); + if ((genh->codec == ATRAC3 || genh->codec == ATRAC3PLUS) && genh->codec_mode==0) + genh->codec_mode = read_8bit(0x49,streamFile); + if ((genh->codec == XMA1 || genh->codec == XMA2) && genh->codec_mode==0) + genh->codec_mode = read_8bit(0x4a,streamFile); + genh->data_size = read_32bitLE(0x50,streamFile); + } - /* other fields */ - genh->num_samples = read_32bitLE(0x40,streamFile); - genh->skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */ - genh->skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */ - genh->codec_mode = read_8bit(0x4b,streamFile); - if ((genh->codec == ATRAC3 || genh->codec == ATRAC3PLUS) && genh->codec_mode==0) - genh->codec_mode = read_8bit(0x49,streamFile); - if ((genh->codec == XMA1 || genh->codec == XMA2) && genh->codec_mode==0) - genh->codec_mode = read_8bit(0x4a,streamFile); - genh->data_size = read_32bitLE(0x50,streamFile); if (genh->data_size == 0) genh->data_size = get_streamfile_size(streamFile) - genh->start_offset; - - genh->num_samples = genh->num_samples > 0 ? genh->num_samples : genh->loop_end_sample; genh->loop_flag = genh->loop_start_sample != -1; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c b/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c index 4163db820..8a5236aae 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c @@ -12,7 +12,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) { int codec_id; - /* check extensions */ + /* checks */ if (!check_extensions(streamFile,"gsb")) goto fail; @@ -116,14 +116,13 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) { /* 0x00: fmt0x166 header (BE), 0x34: seek table */ bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, datasize, streamHeader, 1); - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); if ( !ffmpeg_data ) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0); /* samples are ok */ break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gtd.c b/Frameworks/vgmstream/vgmstream/src/meta/gtd.c index 9002fdd20..8d77ca5e0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/gtd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/gtd.c @@ -94,6 +94,8 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; vgmstream->num_samples = num_samples; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca.c b/Frameworks/vgmstream/vgmstream/src/meta/hca.c index 90efd4f9b..7fe5f68c9 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca.c @@ -21,10 +21,19 @@ VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile) { /* find decryption key in external file or preloaded list */ if (hca_data->info.encryptionEnabled) { - uint8_t keybuf[8]; - if (read_key_file(keybuf, 8, streamFile) == 8) { + uint8_t keybuf[0x08+0x02]; + size_t keysize; + + keysize = read_key_file(keybuf, 0x08+0x04, streamFile); + if (keysize == 0x08) { /* standard */ keycode = (uint64_t)get_64bitBE(keybuf+0x00); - } else { + } + else if (keysize == 0x08+0x02) { /* seed key + AWB subkey */ + uint64_t key = (uint64_t)get_64bitBE(keybuf+0x00); + uint16_t sub = (uint16_t)get_16bitBE(keybuf+0x08); + keycode = key * ( ((uint64_t)sub << 16u) | ((uint16_t)~sub + 2u) ); + } + else { find_hca_key(hca_data, &keycode); } @@ -63,46 +72,61 @@ fail: } +static inline void test_key(hca_codec_data * hca_data, uint64_t key, uint16_t subkey, int *best_score, uint64_t *best_keycode) { + int score; + + if (subkey) { + key = key * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) ); + } + + score = test_hca_key(hca_data, (unsigned long long)key); + + //;VGM_LOG("HCA: test key=%08x%08x, subkey=%04x, score=%i\n", + // (uint32_t)((key >> 32) & 0xFFFFFFFF), (uint32_t)(key & 0xFFFFFFFF), subkey, score); + + /* wrong key */ + if (score < 0) + return; + + /* update if something better is found */ + if (*best_score <= 0 || (score < *best_score && score > 0)) { + *best_score = score; + *best_keycode = key; + } +} + /* Try to find the decryption key from a list. */ static void find_hca_key(hca_codec_data * hca_data, unsigned long long * out_keycode) { const size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info); - unsigned long long best_keycode; int best_score = -1; - int i; - - best_keycode = 0xCC55463930DBE1AB; /* defaults to PSO2 key, most common */ + int i,j; + *out_keycode = 0xCC55463930DBE1AB; /* defaults to PSO2 key, most common */ /* find a candidate key */ for (i = 0; i < keys_length; i++) { - int score; - unsigned long long keycode = (unsigned long long)hcakey_list[i].key; + uint64_t key = hcakey_list[i].key; + size_t subkeys_size = hcakey_list[i].subkeys_size; + const uint16_t *subkeys = hcakey_list[i].subkeys; - score = test_hca_key(hca_data, keycode); - - //;VGM_LOG("HCA: test key=%08x%08x, score=%i\n", - // (uint32_t)((keycode >> 32) & 0xFFFFFFFF), (uint32_t)(keycode & 0xFFFFFFFF), score); - - /* wrong key */ - if (score < 0) - continue; - - /* score 0 is not trustable, update too if something better is found */ - if (best_score < 0 || score < best_score || (best_score == 0 && score == 1)) { - best_score = score; - best_keycode = keycode; + if (subkeys_size > 0) { + for (j = 0; j < subkeys_size; j++) { + test_key(hca_data, key, subkeys[j], &best_score, out_keycode); + if (best_score == 1) /* best possible score */ + goto done; + } } - - /* best possible score */ - if (score == 1) { - break; + else { + test_key(hca_data, key, 0, &best_score, out_keycode); + if (best_score == 1) /* best possible score */ + goto done; } } +done: //;VGM_LOG("HCA: best key=%08x%08x (score=%i)\n", - // (uint32_t)((best_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(best_keycode & 0xFFFFFFFF), best_score); + // (uint32_t)((*out_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(*out_keycode & 0xFFFFFFFF), best_score); VGM_ASSERT(best_score > 1, "HCA: best key=%08x%08x (score=%i)\n", - (uint32_t)((best_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(best_keycode & 0xFFFFFFFF), best_score); - *out_keycode = best_keycode; + (uint32_t)((*out_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(*out_keycode & 0xFFFFFFFF), best_score); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index 811302c67..4acbbefb6 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -1,14 +1,23 @@ #ifndef _HCA_KEYS_H_ #define _HCA_KEYS_H_ +#include "hca_keys_awb.h" + typedef struct { - uint64_t key; + uint64_t key; /* hca key or seed ('user') key */ + const uint16_t *subkeys; /* scramble subkey table for seed key */ + size_t subkeys_size; /* size of the derivation subkey table */ } hcakey_info; + /** * List of known keys, extracted from the game files (mostly found in 2ch.net). * CRI's tools expect an unsigned 64 bit number string, but keys are commonly found online in hex form. * Keys only use 56 bits though, so the upper 8 bits can be ignored. + * + * ACB+AWB after mid 2018 use a user seed key + a scramble subkey in the AWB (normally 16b LE at 0x0e) + * to create the final HCA key, which means there is one key per AWB (so most HCA have a unique key). + * vgmstream derives the key if subkey table is provided. */ static const hcakey_info hcakey_list[] = { @@ -219,7 +228,7 @@ static const hcakey_info hcakey_list[] = { // Taga Tame no Alchemist (iOS/Android) {5047159794308}, // 00000497222AAA84 - // Shin Tennis no Ouji-sama: Rising Beat (iOS/Android) + // Shin Tennis no Ouji-sama: Rising Beat (iOS/Android) voices? {4902201417679}, // 0000047561F95FCF // Kai-ri-Sei Million Arthur (Vita) @@ -249,6 +258,15 @@ static const hcakey_info hcakey_list[] = { // Onsen Musume: Yunohana Kore Kushon (Android) voices {6667}, // 0000000000001A0B + /* Dragalia Lost (Cygames) [iOS/Android] */ + {2967411924141, subkeys_dgl, sizeof(subkeys_dgl) / sizeof(subkeys_dgl[0]) }, // 000002B2E7889CAD + + /* Libra of Precatus (Android) */ + {0x6D8EFB700870FCD4}, // 6D8EFB700870FCD4 + + /* Mashiro Witch (Android) */ + {0x55D11D3349495204}, // 55D11D3349495204 + }; #endif/*_HCA_KEYS_H_*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys_awb.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys_awb.h new file mode 100644 index 000000000..85ed09f94 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys_awb.h @@ -0,0 +1,4150 @@ +#ifndef _HCA_KEYS_AWB_H_ +#define _HCA_KEYS_AWB_H_ + +/* AWB subkey tables */ + +static const uint16_t subkeys_dgl[] = { /* Dragalia Lost (Cygames) [iOS/Android] */ + 0x0152,0x0165,0x0192,0x01E8,0x0240,0x026B,0x02B8,0x0348,0x055E,0x0595,0x05DC,0x0606,0x0636,0x0690,0x06A1,0x06A4, + 0x06B3,0x0760,0x0767,0x076E,0x076F,0x07A6,0x07AA,0x07B4,0x07CC,0x080D,0x082B,0x084C,0x0859,0x085B,0x0861,0x0864, + 0x0865,0x0873,0x088A,0x089B,0x08A5,0x08A7,0x08C3,0x08C6,0x08D5,0x08D8,0x08E0,0x08E8,0x08EF,0x08F0,0x0908,0x090B, + 0x0916,0x0919,0x0923,0x0926,0x0929,0x092C,0x092D,0x092F,0x0942,0x0944,0x094C,0x094E,0x0957,0x095F,0x0963,0x0964, + 0x096C,0x097B,0x097D,0x0988,0x099E,0x09AE,0x09C1,0x09C2,0x09C5,0x09C8,0x09D7,0x09FF,0x0A00,0x0A02,0x0A12,0x0A16, + 0x0A19,0x0A25,0x0A2A,0x0A2F,0x0A30,0x0A31,0x0A3F,0x0A41,0x0A53,0x0A63,0x0A65,0x0A6D,0x0A73,0x0A77,0x0A99,0x0A9A, + 0x0AA5,0x0AA8,0x0AB8,0x0AC2,0x0AC5,0x0ACC,0x0AE0,0x0AE3,0x0AEC,0x0B09,0x0B0C,0x0B35,0x0B5B,0x0B6F,0x0B7C,0x0B8D, + 0x0BA1,0x0BB0,0x0BBE,0x0BC9,0x0BDE,0x0BEF,0x0C04,0x0C0F,0x0C30,0x0C8B,0x0C9A,0x0C9F,0x0CA9,0x0CB9,0x0D71,0x0DB0, + 0x0DCF,0x0DD4,0x0DE6,0x0E1C,0x0E66,0x0E9D,0x0EAF,0x0EBB,0x0FDA,0x102F,0x103A,0x1074,0x10BF,0x10C7,0x1107,0x113A, + 0x116F,0x11A6,0x11FB,0x1220,0x130E,0x1335,0x135B,0x13C0,0x1474,0x1538,0x1585,0x15AD,0x15E1,0x1748,0x1892,0x18A4, + 0x1944,0x197A,0x19F3,0x1A47,0x1A5B,0x1A89,0x1AAC,0x1C31,0x1C3B,0x1C7C,0x1C7E,0x1D01,0x1D0C,0x1D5A,0x1E1E,0x1E88, + 0x1F0A,0x1FC2,0x2000,0x2007,0x208C,0x20E9,0x20EE,0x2160,0x216E,0x21CA,0x221E,0x2265,0x2275,0x2277,0x22C4,0x22FA, + 0x2330,0x2379,0x23C9,0x23D8,0x2415,0x243C,0x245A,0x24AD,0x24CD,0x2540,0x2632,0x264C,0x269B,0x26B5,0x26C5,0x26FC, + 0x2701,0x274D,0x274E,0x2777,0x27EE,0x284B,0x288C,0x28A9,0x28B6,0x292B,0x2930,0x29B0,0x29B2,0x29D9,0x2A0A,0x2A47, + 0x2A55,0x2A5D,0x2ADB,0x2AE7,0x2D08,0x2DB0,0x2DB7,0x2DC3,0x2E6E,0x2E75,0x2E9E,0x2EB6,0x2ED8,0x2F64,0x2F66,0x2F72, + 0x30BB,0x30CA,0x30E6,0x3160,0x3218,0x32E8,0x333F,0x338B,0x33BE,0x355A,0x357D,0x35DD,0x3619,0x36AA,0x3738,0x3752, + 0x37DE,0x3804,0x380C,0x3920,0x39DB,0x3C7B,0x3CA3,0x3D50,0x3EB2,0x3EF2,0x3F42,0x3F79,0x4000,0x403D,0x40BF,0x40DE, + 0x413E,0x414F,0x41A3,0x42EA,0x434A,0x43D3,0x43E9,0x4411,0x4541,0x4751,0x4793,0x47DF,0x4840,0x487A,0x48D7,0x49B4, + 0x49E3,0x4B0E,0x4B21,0x4B8D,0x4C49,0x4C72,0x4D44,0x4D86,0x4DEA,0x4DF5,0x4E40,0x4F60,0x4F92,0x4FF2,0x5220,0x5493, + 0x54CE,0x552C,0x559B,0x5639,0x567C,0x56A1,0x56EE,0x5794,0x582E,0x5846,0x586A,0x58B1,0x58C3,0x59A5,0x59EF,0x5A86, + 0x5B19,0x5B49,0x5B5C,0x5B90,0x5BCF,0x5C38,0x5C75,0x5C83,0x5D61,0x5DE0,0x5E47,0x5E57,0x5ED5,0x6000,0x601F,0x6071, + 0x6104,0x6188,0x6191,0x61B2,0x61EB,0x6226,0x627D,0x62F9,0x63DE,0x645F,0x64D3,0x659D,0x65D3,0x65D4,0x65F2,0x6631, + 0x6914,0x6990,0x6993,0x6A52,0x6A85,0x6B16,0x6BF6,0x6CD6,0x6CE3,0x6CF9,0x6CFA,0x6D0E,0x6D16,0x6D3E,0x6D80,0x6DCF, + 0x6E73,0x6EC5,0x6F14,0x6FD0,0x7033,0x704C,0x7098,0x7242,0x7278,0x7319,0x7427,0x7432,0x747F,0x7484,0x749D,0x74D7, + 0x74D8,0x756A,0x7576,0x7588,0x75A9,0x764D,0x773C,0x7766,0x7895,0x78B0,0x78F3,0x7976,0x798F,0x79E7,0x79F9,0x7A1D, + 0x7A24,0x7A47,0x7B64,0x7BBC,0x7C2E,0x7CBA,0x7D0D,0x7D12,0x7E66,0x7EB5,0x7EBA,0x7EC5,0x7F1B,0x7F26,0x7F5F,0x7FC1, + 0x7FCE,0x7FFC,0x8000,0x8075,0x80B2,0x80FF,0x81C8,0x826C,0x8274,0x82B5,0x8412,0x8458,0x8467,0x8533,0x8577,0x85FF, + 0x8658,0x86E3,0x86E6,0x878E,0x885E,0x8A7E,0x8B1F,0x8B25,0x8B33,0x8B4D,0x8B80,0x8BFF,0x8C38,0x8D46,0x8D8B,0x8E10, + 0x8E79,0x8F01,0x8FF1,0x9000,0x9029,0x9082,0x924A,0x92F8,0x9342,0x940C,0x94B9,0x9580,0x95ED,0x9630,0x97D1,0x97FC, + 0x9810,0x9825,0x9861,0x98FB,0x990E,0x9970,0x9A37,0x9B36,0x9B67,0x9FA3,0x9FF2,0xA000,0xA0A3,0xA1C6,0xA27A,0xA2FB, + 0xA3AB,0xA3C2,0xA4E1,0xA548,0xA553,0xA585,0xA6A7,0xA71C,0xA723,0xA77E,0xA7D6,0xA894,0xA8BF,0xA8E0,0xA90A,0xAA3A, + 0xAA57,0xAADF,0xAAF4,0xAB0B,0xABF3,0xAC0C,0xAC23,0xAC55,0xAD00,0xADC4,0xADF1,0xAE02,0xAE16,0xAE6A,0xAEA7,0xAEB6, + 0xB040,0xB073,0xB122,0xB14B,0xB175,0xB177,0xB25D,0xB262,0xB332,0xB378,0xB400,0xB52E,0xB54B,0xB592,0xB59C,0xB5AD, + 0xB5CE,0xB5D3,0xB5D5,0xB613,0xB65D,0xB79F,0xB89D,0xB907,0xBC78,0xBCCC,0xBDBF,0xBE21,0xBF21,0xBF64,0xC13F,0xC2EA, + 0xC303,0xC385,0xC3C9,0xC3D8,0xC452,0xC5CB,0xC5EB,0xC655,0xC67B,0xC6D9,0xC728,0xC8A8,0xCAF6,0xCDAC,0xCDF7,0xD075, + 0xD163,0xD203,0xD410,0xD49E,0xD718,0xD876,0xD99C,0xDA29,0xDAA7,0xDBA0,0xDC8F,0xDCFA,0xDD3D,0xDD55,0xDE02,0xDE30, + 0xE000,0xE02E,0xE073,0xE1C5,0xE1CD,0xE288,0xE3AE,0xE597,0xE5E3,0xE652,0xE775,0xE930,0xE947,0xEC15,0xEC1B,0xED0A, + 0xED93,0xED95,0xEDC2,0xEF7F,0xEFA6,0xEFB6,0xF049,0xF0C7,0xF107,0xF41F,0xF558,0xF5C8,0xF7DC,0xF7ED,0xF89E,0xF8B2, + 0xF9C9,0xFAAA,0xFB77,0xFCAF,0xFCCA,0xFD01,0xFD13,0xFD57,0xFD68,0xFDDB,0xFE07,0xFF43,0xFF65,0xFF85,0xFF8B,0xFF9A, + 0xFFD0, +}; + +#if 0 +static const uint16_t subkeys_all[] = { /* all values for testing purposes (slow) */ + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, + 0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF, + 0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF, + 0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, + 0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF, + 0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, + 0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF, + 0x0100,0x0101,0x0102,0x0103,0x0104,0x0105,0x0106,0x0107,0x0108,0x0109,0x010A,0x010B,0x010C,0x010D,0x010E,0x010F, + 0x0110,0x0111,0x0112,0x0113,0x0114,0x0115,0x0116,0x0117,0x0118,0x0119,0x011A,0x011B,0x011C,0x011D,0x011E,0x011F, + 0x0120,0x0121,0x0122,0x0123,0x0124,0x0125,0x0126,0x0127,0x0128,0x0129,0x012A,0x012B,0x012C,0x012D,0x012E,0x012F, + 0x0130,0x0131,0x0132,0x0133,0x0134,0x0135,0x0136,0x0137,0x0138,0x0139,0x013A,0x013B,0x013C,0x013D,0x013E,0x013F, + 0x0140,0x0141,0x0142,0x0143,0x0144,0x0145,0x0146,0x0147,0x0148,0x0149,0x014A,0x014B,0x014C,0x014D,0x014E,0x014F, + 0x0150,0x0151,0x0152,0x0153,0x0154,0x0155,0x0156,0x0157,0x0158,0x0159,0x015A,0x015B,0x015C,0x015D,0x015E,0x015F, + 0x0160,0x0161,0x0162,0x0163,0x0164,0x0165,0x0166,0x0167,0x0168,0x0169,0x016A,0x016B,0x016C,0x016D,0x016E,0x016F, + 0x0170,0x0171,0x0172,0x0173,0x0174,0x0175,0x0176,0x0177,0x0178,0x0179,0x017A,0x017B,0x017C,0x017D,0x017E,0x017F, + 0x0180,0x0181,0x0182,0x0183,0x0184,0x0185,0x0186,0x0187,0x0188,0x0189,0x018A,0x018B,0x018C,0x018D,0x018E,0x018F, + 0x0190,0x0191,0x0192,0x0193,0x0194,0x0195,0x0196,0x0197,0x0198,0x0199,0x019A,0x019B,0x019C,0x019D,0x019E,0x019F, + 0x01A0,0x01A1,0x01A2,0x01A3,0x01A4,0x01A5,0x01A6,0x01A7,0x01A8,0x01A9,0x01AA,0x01AB,0x01AC,0x01AD,0x01AE,0x01AF, + 0x01B0,0x01B1,0x01B2,0x01B3,0x01B4,0x01B5,0x01B6,0x01B7,0x01B8,0x01B9,0x01BA,0x01BB,0x01BC,0x01BD,0x01BE,0x01BF, + 0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C6,0x01C7,0x01C8,0x01C9,0x01CA,0x01CB,0x01CC,0x01CD,0x01CE,0x01CF, + 0x01D0,0x01D1,0x01D2,0x01D3,0x01D4,0x01D5,0x01D6,0x01D7,0x01D8,0x01D9,0x01DA,0x01DB,0x01DC,0x01DD,0x01DE,0x01DF, + 0x01E0,0x01E1,0x01E2,0x01E3,0x01E4,0x01E5,0x01E6,0x01E7,0x01E8,0x01E9,0x01EA,0x01EB,0x01EC,0x01ED,0x01EE,0x01EF, + 0x01F0,0x01F1,0x01F2,0x01F3,0x01F4,0x01F5,0x01F6,0x01F7,0x01F8,0x01F9,0x01FA,0x01FB,0x01FC,0x01FD,0x01FE,0x01FF, + 0x0200,0x0201,0x0202,0x0203,0x0204,0x0205,0x0206,0x0207,0x0208,0x0209,0x020A,0x020B,0x020C,0x020D,0x020E,0x020F, + 0x0210,0x0211,0x0212,0x0213,0x0214,0x0215,0x0216,0x0217,0x0218,0x0219,0x021A,0x021B,0x021C,0x021D,0x021E,0x021F, + 0x0220,0x0221,0x0222,0x0223,0x0224,0x0225,0x0226,0x0227,0x0228,0x0229,0x022A,0x022B,0x022C,0x022D,0x022E,0x022F, + 0x0230,0x0231,0x0232,0x0233,0x0234,0x0235,0x0236,0x0237,0x0238,0x0239,0x023A,0x023B,0x023C,0x023D,0x023E,0x023F, + 0x0240,0x0241,0x0242,0x0243,0x0244,0x0245,0x0246,0x0247,0x0248,0x0249,0x024A,0x024B,0x024C,0x024D,0x024E,0x024F, + 0x0250,0x0251,0x0252,0x0253,0x0254,0x0255,0x0256,0x0257,0x0258,0x0259,0x025A,0x025B,0x025C,0x025D,0x025E,0x025F, + 0x0260,0x0261,0x0262,0x0263,0x0264,0x0265,0x0266,0x0267,0x0268,0x0269,0x026A,0x026B,0x026C,0x026D,0x026E,0x026F, + 0x0270,0x0271,0x0272,0x0273,0x0274,0x0275,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x027D,0x027E,0x027F, + 0x0280,0x0281,0x0282,0x0283,0x0284,0x0285,0x0286,0x0287,0x0288,0x0289,0x028A,0x028B,0x028C,0x028D,0x028E,0x028F, + 0x0290,0x0291,0x0292,0x0293,0x0294,0x0295,0x0296,0x0297,0x0298,0x0299,0x029A,0x029B,0x029C,0x029D,0x029E,0x029F, + 0x02A0,0x02A1,0x02A2,0x02A3,0x02A4,0x02A5,0x02A6,0x02A7,0x02A8,0x02A9,0x02AA,0x02AB,0x02AC,0x02AD,0x02AE,0x02AF, + 0x02B0,0x02B1,0x02B2,0x02B3,0x02B4,0x02B5,0x02B6,0x02B7,0x02B8,0x02B9,0x02BA,0x02BB,0x02BC,0x02BD,0x02BE,0x02BF, + 0x02C0,0x02C1,0x02C2,0x02C3,0x02C4,0x02C5,0x02C6,0x02C7,0x02C8,0x02C9,0x02CA,0x02CB,0x02CC,0x02CD,0x02CE,0x02CF, + 0x02D0,0x02D1,0x02D2,0x02D3,0x02D4,0x02D5,0x02D6,0x02D7,0x02D8,0x02D9,0x02DA,0x02DB,0x02DC,0x02DD,0x02DE,0x02DF, + 0x02E0,0x02E1,0x02E2,0x02E3,0x02E4,0x02E5,0x02E6,0x02E7,0x02E8,0x02E9,0x02EA,0x02EB,0x02EC,0x02ED,0x02EE,0x02EF, + 0x02F0,0x02F1,0x02F2,0x02F3,0x02F4,0x02F5,0x02F6,0x02F7,0x02F8,0x02F9,0x02FA,0x02FB,0x02FC,0x02FD,0x02FE,0x02FF, + 0x0300,0x0301,0x0302,0x0303,0x0304,0x0305,0x0306,0x0307,0x0308,0x0309,0x030A,0x030B,0x030C,0x030D,0x030E,0x030F, + 0x0310,0x0311,0x0312,0x0313,0x0314,0x0315,0x0316,0x0317,0x0318,0x0319,0x031A,0x031B,0x031C,0x031D,0x031E,0x031F, + 0x0320,0x0321,0x0322,0x0323,0x0324,0x0325,0x0326,0x0327,0x0328,0x0329,0x032A,0x032B,0x032C,0x032D,0x032E,0x032F, + 0x0330,0x0331,0x0332,0x0333,0x0334,0x0335,0x0336,0x0337,0x0338,0x0339,0x033A,0x033B,0x033C,0x033D,0x033E,0x033F, + 0x0340,0x0341,0x0342,0x0343,0x0344,0x0345,0x0346,0x0347,0x0348,0x0349,0x034A,0x034B,0x034C,0x034D,0x034E,0x034F, + 0x0350,0x0351,0x0352,0x0353,0x0354,0x0355,0x0356,0x0357,0x0358,0x0359,0x035A,0x035B,0x035C,0x035D,0x035E,0x035F, + 0x0360,0x0361,0x0362,0x0363,0x0364,0x0365,0x0366,0x0367,0x0368,0x0369,0x036A,0x036B,0x036C,0x036D,0x036E,0x036F, + 0x0370,0x0371,0x0372,0x0373,0x0374,0x0375,0x0376,0x0377,0x0378,0x0379,0x037A,0x037B,0x037C,0x037D,0x037E,0x037F, + 0x0380,0x0381,0x0382,0x0383,0x0384,0x0385,0x0386,0x0387,0x0388,0x0389,0x038A,0x038B,0x038C,0x038D,0x038E,0x038F, + 0x0390,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F, + 0x03A0,0x03A1,0x03A2,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,0x03AA,0x03AB,0x03AC,0x03AD,0x03AE,0x03AF, + 0x03B0,0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF, + 0x03C0,0x03C1,0x03C2,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9,0x03CA,0x03CB,0x03CC,0x03CD,0x03CE,0x03CF, + 0x03D0,0x03D1,0x03D2,0x03D3,0x03D4,0x03D5,0x03D6,0x03D7,0x03D8,0x03D9,0x03DA,0x03DB,0x03DC,0x03DD,0x03DE,0x03DF, + 0x03E0,0x03E1,0x03E2,0x03E3,0x03E4,0x03E5,0x03E6,0x03E7,0x03E8,0x03E9,0x03EA,0x03EB,0x03EC,0x03ED,0x03EE,0x03EF, + 0x03F0,0x03F1,0x03F2,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F8,0x03F9,0x03FA,0x03FB,0x03FC,0x03FD,0x03FE,0x03FF, + 0x0400,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,0x0409,0x040A,0x040B,0x040C,0x040D,0x040E,0x040F, + 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,0x041F, + 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F, + 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,0x043F, + 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,0x044F, + 0x0450,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,0x045A,0x045B,0x045C,0x045D,0x045E,0x045F, + 0x0460,0x0461,0x0462,0x0463,0x0464,0x0465,0x0466,0x0467,0x0468,0x0469,0x046A,0x046B,0x046C,0x046D,0x046E,0x046F, + 0x0470,0x0471,0x0472,0x0473,0x0474,0x0475,0x0476,0x0477,0x0478,0x0479,0x047A,0x047B,0x047C,0x047D,0x047E,0x047F, + 0x0480,0x0481,0x0482,0x0483,0x0484,0x0485,0x0486,0x0487,0x0488,0x0489,0x048A,0x048B,0x048C,0x048D,0x048E,0x048F, + 0x0490,0x0491,0x0492,0x0493,0x0494,0x0495,0x0496,0x0497,0x0498,0x0499,0x049A,0x049B,0x049C,0x049D,0x049E,0x049F, + 0x04A0,0x04A1,0x04A2,0x04A3,0x04A4,0x04A5,0x04A6,0x04A7,0x04A8,0x04A9,0x04AA,0x04AB,0x04AC,0x04AD,0x04AE,0x04AF, + 0x04B0,0x04B1,0x04B2,0x04B3,0x04B4,0x04B5,0x04B6,0x04B7,0x04B8,0x04B9,0x04BA,0x04BB,0x04BC,0x04BD,0x04BE,0x04BF, + 0x04C0,0x04C1,0x04C2,0x04C3,0x04C4,0x04C5,0x04C6,0x04C7,0x04C8,0x04C9,0x04CA,0x04CB,0x04CC,0x04CD,0x04CE,0x04CF, + 0x04D0,0x04D1,0x04D2,0x04D3,0x04D4,0x04D5,0x04D6,0x04D7,0x04D8,0x04D9,0x04DA,0x04DB,0x04DC,0x04DD,0x04DE,0x04DF, + 0x04E0,0x04E1,0x04E2,0x04E3,0x04E4,0x04E5,0x04E6,0x04E7,0x04E8,0x04E9,0x04EA,0x04EB,0x04EC,0x04ED,0x04EE,0x04EF, + 0x04F0,0x04F1,0x04F2,0x04F3,0x04F4,0x04F5,0x04F6,0x04F7,0x04F8,0x04F9,0x04FA,0x04FB,0x04FC,0x04FD,0x04FE,0x04FF, + 0x0500,0x0501,0x0502,0x0503,0x0504,0x0505,0x0506,0x0507,0x0508,0x0509,0x050A,0x050B,0x050C,0x050D,0x050E,0x050F, + 0x0510,0x0511,0x0512,0x0513,0x0514,0x0515,0x0516,0x0517,0x0518,0x0519,0x051A,0x051B,0x051C,0x051D,0x051E,0x051F, + 0x0520,0x0521,0x0522,0x0523,0x0524,0x0525,0x0526,0x0527,0x0528,0x0529,0x052A,0x052B,0x052C,0x052D,0x052E,0x052F, + 0x0530,0x0531,0x0532,0x0533,0x0534,0x0535,0x0536,0x0537,0x0538,0x0539,0x053A,0x053B,0x053C,0x053D,0x053E,0x053F, + 0x0540,0x0541,0x0542,0x0543,0x0544,0x0545,0x0546,0x0547,0x0548,0x0549,0x054A,0x054B,0x054C,0x054D,0x054E,0x054F, + 0x0550,0x0551,0x0552,0x0553,0x0554,0x0555,0x0556,0x0557,0x0558,0x0559,0x055A,0x055B,0x055C,0x055D,0x055E,0x055F, + 0x0560,0x0561,0x0562,0x0563,0x0564,0x0565,0x0566,0x0567,0x0568,0x0569,0x056A,0x056B,0x056C,0x056D,0x056E,0x056F, + 0x0570,0x0571,0x0572,0x0573,0x0574,0x0575,0x0576,0x0577,0x0578,0x0579,0x057A,0x057B,0x057C,0x057D,0x057E,0x057F, + 0x0580,0x0581,0x0582,0x0583,0x0584,0x0585,0x0586,0x0587,0x0588,0x0589,0x058A,0x058B,0x058C,0x058D,0x058E,0x058F, + 0x0590,0x0591,0x0592,0x0593,0x0594,0x0595,0x0596,0x0597,0x0598,0x0599,0x059A,0x059B,0x059C,0x059D,0x059E,0x059F, + 0x05A0,0x05A1,0x05A2,0x05A3,0x05A4,0x05A5,0x05A6,0x05A7,0x05A8,0x05A9,0x05AA,0x05AB,0x05AC,0x05AD,0x05AE,0x05AF, + 0x05B0,0x05B1,0x05B2,0x05B3,0x05B4,0x05B5,0x05B6,0x05B7,0x05B8,0x05B9,0x05BA,0x05BB,0x05BC,0x05BD,0x05BE,0x05BF, + 0x05C0,0x05C1,0x05C2,0x05C3,0x05C4,0x05C5,0x05C6,0x05C7,0x05C8,0x05C9,0x05CA,0x05CB,0x05CC,0x05CD,0x05CE,0x05CF, + 0x05D0,0x05D1,0x05D2,0x05D3,0x05D4,0x05D5,0x05D6,0x05D7,0x05D8,0x05D9,0x05DA,0x05DB,0x05DC,0x05DD,0x05DE,0x05DF, + 0x05E0,0x05E1,0x05E2,0x05E3,0x05E4,0x05E5,0x05E6,0x05E7,0x05E8,0x05E9,0x05EA,0x05EB,0x05EC,0x05ED,0x05EE,0x05EF, + 0x05F0,0x05F1,0x05F2,0x05F3,0x05F4,0x05F5,0x05F6,0x05F7,0x05F8,0x05F9,0x05FA,0x05FB,0x05FC,0x05FD,0x05FE,0x05FF, + 0x0600,0x0601,0x0602,0x0603,0x0604,0x0605,0x0606,0x0607,0x0608,0x0609,0x060A,0x060B,0x060C,0x060D,0x060E,0x060F, + 0x0610,0x0611,0x0612,0x0613,0x0614,0x0615,0x0616,0x0617,0x0618,0x0619,0x061A,0x061B,0x061C,0x061D,0x061E,0x061F, + 0x0620,0x0621,0x0622,0x0623,0x0624,0x0625,0x0626,0x0627,0x0628,0x0629,0x062A,0x062B,0x062C,0x062D,0x062E,0x062F, + 0x0630,0x0631,0x0632,0x0633,0x0634,0x0635,0x0636,0x0637,0x0638,0x0639,0x063A,0x063B,0x063C,0x063D,0x063E,0x063F, + 0x0640,0x0641,0x0642,0x0643,0x0644,0x0645,0x0646,0x0647,0x0648,0x0649,0x064A,0x064B,0x064C,0x064D,0x064E,0x064F, + 0x0650,0x0651,0x0652,0x0653,0x0654,0x0655,0x0656,0x0657,0x0658,0x0659,0x065A,0x065B,0x065C,0x065D,0x065E,0x065F, + 0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667,0x0668,0x0669,0x066A,0x066B,0x066C,0x066D,0x066E,0x066F, + 0x0670,0x0671,0x0672,0x0673,0x0674,0x0675,0x0676,0x0677,0x0678,0x0679,0x067A,0x067B,0x067C,0x067D,0x067E,0x067F, + 0x0680,0x0681,0x0682,0x0683,0x0684,0x0685,0x0686,0x0687,0x0688,0x0689,0x068A,0x068B,0x068C,0x068D,0x068E,0x068F, + 0x0690,0x0691,0x0692,0x0693,0x0694,0x0695,0x0696,0x0697,0x0698,0x0699,0x069A,0x069B,0x069C,0x069D,0x069E,0x069F, + 0x06A0,0x06A1,0x06A2,0x06A3,0x06A4,0x06A5,0x06A6,0x06A7,0x06A8,0x06A9,0x06AA,0x06AB,0x06AC,0x06AD,0x06AE,0x06AF, + 0x06B0,0x06B1,0x06B2,0x06B3,0x06B4,0x06B5,0x06B6,0x06B7,0x06B8,0x06B9,0x06BA,0x06BB,0x06BC,0x06BD,0x06BE,0x06BF, + 0x06C0,0x06C1,0x06C2,0x06C3,0x06C4,0x06C5,0x06C6,0x06C7,0x06C8,0x06C9,0x06CA,0x06CB,0x06CC,0x06CD,0x06CE,0x06CF, + 0x06D0,0x06D1,0x06D2,0x06D3,0x06D4,0x06D5,0x06D6,0x06D7,0x06D8,0x06D9,0x06DA,0x06DB,0x06DC,0x06DD,0x06DE,0x06DF, + 0x06E0,0x06E1,0x06E2,0x06E3,0x06E4,0x06E5,0x06E6,0x06E7,0x06E8,0x06E9,0x06EA,0x06EB,0x06EC,0x06ED,0x06EE,0x06EF, + 0x06F0,0x06F1,0x06F2,0x06F3,0x06F4,0x06F5,0x06F6,0x06F7,0x06F8,0x06F9,0x06FA,0x06FB,0x06FC,0x06FD,0x06FE,0x06FF, + 0x0700,0x0701,0x0702,0x0703,0x0704,0x0705,0x0706,0x0707,0x0708,0x0709,0x070A,0x070B,0x070C,0x070D,0x070E,0x070F, + 0x0710,0x0711,0x0712,0x0713,0x0714,0x0715,0x0716,0x0717,0x0718,0x0719,0x071A,0x071B,0x071C,0x071D,0x071E,0x071F, + 0x0720,0x0721,0x0722,0x0723,0x0724,0x0725,0x0726,0x0727,0x0728,0x0729,0x072A,0x072B,0x072C,0x072D,0x072E,0x072F, + 0x0730,0x0731,0x0732,0x0733,0x0734,0x0735,0x0736,0x0737,0x0738,0x0739,0x073A,0x073B,0x073C,0x073D,0x073E,0x073F, + 0x0740,0x0741,0x0742,0x0743,0x0744,0x0745,0x0746,0x0747,0x0748,0x0749,0x074A,0x074B,0x074C,0x074D,0x074E,0x074F, + 0x0750,0x0751,0x0752,0x0753,0x0754,0x0755,0x0756,0x0757,0x0758,0x0759,0x075A,0x075B,0x075C,0x075D,0x075E,0x075F, + 0x0760,0x0761,0x0762,0x0763,0x0764,0x0765,0x0766,0x0767,0x0768,0x0769,0x076A,0x076B,0x076C,0x076D,0x076E,0x076F, + 0x0770,0x0771,0x0772,0x0773,0x0774,0x0775,0x0776,0x0777,0x0778,0x0779,0x077A,0x077B,0x077C,0x077D,0x077E,0x077F, + 0x0780,0x0781,0x0782,0x0783,0x0784,0x0785,0x0786,0x0787,0x0788,0x0789,0x078A,0x078B,0x078C,0x078D,0x078E,0x078F, + 0x0790,0x0791,0x0792,0x0793,0x0794,0x0795,0x0796,0x0797,0x0798,0x0799,0x079A,0x079B,0x079C,0x079D,0x079E,0x079F, + 0x07A0,0x07A1,0x07A2,0x07A3,0x07A4,0x07A5,0x07A6,0x07A7,0x07A8,0x07A9,0x07AA,0x07AB,0x07AC,0x07AD,0x07AE,0x07AF, + 0x07B0,0x07B1,0x07B2,0x07B3,0x07B4,0x07B5,0x07B6,0x07B7,0x07B8,0x07B9,0x07BA,0x07BB,0x07BC,0x07BD,0x07BE,0x07BF, + 0x07C0,0x07C1,0x07C2,0x07C3,0x07C4,0x07C5,0x07C6,0x07C7,0x07C8,0x07C9,0x07CA,0x07CB,0x07CC,0x07CD,0x07CE,0x07CF, + 0x07D0,0x07D1,0x07D2,0x07D3,0x07D4,0x07D5,0x07D6,0x07D7,0x07D8,0x07D9,0x07DA,0x07DB,0x07DC,0x07DD,0x07DE,0x07DF, + 0x07E0,0x07E1,0x07E2,0x07E3,0x07E4,0x07E5,0x07E6,0x07E7,0x07E8,0x07E9,0x07EA,0x07EB,0x07EC,0x07ED,0x07EE,0x07EF, + 0x07F0,0x07F1,0x07F2,0x07F3,0x07F4,0x07F5,0x07F6,0x07F7,0x07F8,0x07F9,0x07FA,0x07FB,0x07FC,0x07FD,0x07FE,0x07FF, + 0x0800,0x0801,0x0802,0x0803,0x0804,0x0805,0x0806,0x0807,0x0808,0x0809,0x080A,0x080B,0x080C,0x080D,0x080E,0x080F, + 0x0810,0x0811,0x0812,0x0813,0x0814,0x0815,0x0816,0x0817,0x0818,0x0819,0x081A,0x081B,0x081C,0x081D,0x081E,0x081F, + 0x0820,0x0821,0x0822,0x0823,0x0824,0x0825,0x0826,0x0827,0x0828,0x0829,0x082A,0x082B,0x082C,0x082D,0x082E,0x082F, + 0x0830,0x0831,0x0832,0x0833,0x0834,0x0835,0x0836,0x0837,0x0838,0x0839,0x083A,0x083B,0x083C,0x083D,0x083E,0x083F, + 0x0840,0x0841,0x0842,0x0843,0x0844,0x0845,0x0846,0x0847,0x0848,0x0849,0x084A,0x084B,0x084C,0x084D,0x084E,0x084F, + 0x0850,0x0851,0x0852,0x0853,0x0854,0x0855,0x0856,0x0857,0x0858,0x0859,0x085A,0x085B,0x085C,0x085D,0x085E,0x085F, + 0x0860,0x0861,0x0862,0x0863,0x0864,0x0865,0x0866,0x0867,0x0868,0x0869,0x086A,0x086B,0x086C,0x086D,0x086E,0x086F, + 0x0870,0x0871,0x0872,0x0873,0x0874,0x0875,0x0876,0x0877,0x0878,0x0879,0x087A,0x087B,0x087C,0x087D,0x087E,0x087F, + 0x0880,0x0881,0x0882,0x0883,0x0884,0x0885,0x0886,0x0887,0x0888,0x0889,0x088A,0x088B,0x088C,0x088D,0x088E,0x088F, + 0x0890,0x0891,0x0892,0x0893,0x0894,0x0895,0x0896,0x0897,0x0898,0x0899,0x089A,0x089B,0x089C,0x089D,0x089E,0x089F, + 0x08A0,0x08A1,0x08A2,0x08A3,0x08A4,0x08A5,0x08A6,0x08A7,0x08A8,0x08A9,0x08AA,0x08AB,0x08AC,0x08AD,0x08AE,0x08AF, + 0x08B0,0x08B1,0x08B2,0x08B3,0x08B4,0x08B5,0x08B6,0x08B7,0x08B8,0x08B9,0x08BA,0x08BB,0x08BC,0x08BD,0x08BE,0x08BF, + 0x08C0,0x08C1,0x08C2,0x08C3,0x08C4,0x08C5,0x08C6,0x08C7,0x08C8,0x08C9,0x08CA,0x08CB,0x08CC,0x08CD,0x08CE,0x08CF, + 0x08D0,0x08D1,0x08D2,0x08D3,0x08D4,0x08D5,0x08D6,0x08D7,0x08D8,0x08D9,0x08DA,0x08DB,0x08DC,0x08DD,0x08DE,0x08DF, + 0x08E0,0x08E1,0x08E2,0x08E3,0x08E4,0x08E5,0x08E6,0x08E7,0x08E8,0x08E9,0x08EA,0x08EB,0x08EC,0x08ED,0x08EE,0x08EF, + 0x08F0,0x08F1,0x08F2,0x08F3,0x08F4,0x08F5,0x08F6,0x08F7,0x08F8,0x08F9,0x08FA,0x08FB,0x08FC,0x08FD,0x08FE,0x08FF, + 0x0900,0x0901,0x0902,0x0903,0x0904,0x0905,0x0906,0x0907,0x0908,0x0909,0x090A,0x090B,0x090C,0x090D,0x090E,0x090F, + 0x0910,0x0911,0x0912,0x0913,0x0914,0x0915,0x0916,0x0917,0x0918,0x0919,0x091A,0x091B,0x091C,0x091D,0x091E,0x091F, + 0x0920,0x0921,0x0922,0x0923,0x0924,0x0925,0x0926,0x0927,0x0928,0x0929,0x092A,0x092B,0x092C,0x092D,0x092E,0x092F, + 0x0930,0x0931,0x0932,0x0933,0x0934,0x0935,0x0936,0x0937,0x0938,0x0939,0x093A,0x093B,0x093C,0x093D,0x093E,0x093F, + 0x0940,0x0941,0x0942,0x0943,0x0944,0x0945,0x0946,0x0947,0x0948,0x0949,0x094A,0x094B,0x094C,0x094D,0x094E,0x094F, + 0x0950,0x0951,0x0952,0x0953,0x0954,0x0955,0x0956,0x0957,0x0958,0x0959,0x095A,0x095B,0x095C,0x095D,0x095E,0x095F, + 0x0960,0x0961,0x0962,0x0963,0x0964,0x0965,0x0966,0x0967,0x0968,0x0969,0x096A,0x096B,0x096C,0x096D,0x096E,0x096F, + 0x0970,0x0971,0x0972,0x0973,0x0974,0x0975,0x0976,0x0977,0x0978,0x0979,0x097A,0x097B,0x097C,0x097D,0x097E,0x097F, + 0x0980,0x0981,0x0982,0x0983,0x0984,0x0985,0x0986,0x0987,0x0988,0x0989,0x098A,0x098B,0x098C,0x098D,0x098E,0x098F, + 0x0990,0x0991,0x0992,0x0993,0x0994,0x0995,0x0996,0x0997,0x0998,0x0999,0x099A,0x099B,0x099C,0x099D,0x099E,0x099F, + 0x09A0,0x09A1,0x09A2,0x09A3,0x09A4,0x09A5,0x09A6,0x09A7,0x09A8,0x09A9,0x09AA,0x09AB,0x09AC,0x09AD,0x09AE,0x09AF, + 0x09B0,0x09B1,0x09B2,0x09B3,0x09B4,0x09B5,0x09B6,0x09B7,0x09B8,0x09B9,0x09BA,0x09BB,0x09BC,0x09BD,0x09BE,0x09BF, + 0x09C0,0x09C1,0x09C2,0x09C3,0x09C4,0x09C5,0x09C6,0x09C7,0x09C8,0x09C9,0x09CA,0x09CB,0x09CC,0x09CD,0x09CE,0x09CF, + 0x09D0,0x09D1,0x09D2,0x09D3,0x09D4,0x09D5,0x09D6,0x09D7,0x09D8,0x09D9,0x09DA,0x09DB,0x09DC,0x09DD,0x09DE,0x09DF, + 0x09E0,0x09E1,0x09E2,0x09E3,0x09E4,0x09E5,0x09E6,0x09E7,0x09E8,0x09E9,0x09EA,0x09EB,0x09EC,0x09ED,0x09EE,0x09EF, + 0x09F0,0x09F1,0x09F2,0x09F3,0x09F4,0x09F5,0x09F6,0x09F7,0x09F8,0x09F9,0x09FA,0x09FB,0x09FC,0x09FD,0x09FE,0x09FF, + 0x0A00,0x0A01,0x0A02,0x0A03,0x0A04,0x0A05,0x0A06,0x0A07,0x0A08,0x0A09,0x0A0A,0x0A0B,0x0A0C,0x0A0D,0x0A0E,0x0A0F, + 0x0A10,0x0A11,0x0A12,0x0A13,0x0A14,0x0A15,0x0A16,0x0A17,0x0A18,0x0A19,0x0A1A,0x0A1B,0x0A1C,0x0A1D,0x0A1E,0x0A1F, + 0x0A20,0x0A21,0x0A22,0x0A23,0x0A24,0x0A25,0x0A26,0x0A27,0x0A28,0x0A29,0x0A2A,0x0A2B,0x0A2C,0x0A2D,0x0A2E,0x0A2F, + 0x0A30,0x0A31,0x0A32,0x0A33,0x0A34,0x0A35,0x0A36,0x0A37,0x0A38,0x0A39,0x0A3A,0x0A3B,0x0A3C,0x0A3D,0x0A3E,0x0A3F, + 0x0A40,0x0A41,0x0A42,0x0A43,0x0A44,0x0A45,0x0A46,0x0A47,0x0A48,0x0A49,0x0A4A,0x0A4B,0x0A4C,0x0A4D,0x0A4E,0x0A4F, + 0x0A50,0x0A51,0x0A52,0x0A53,0x0A54,0x0A55,0x0A56,0x0A57,0x0A58,0x0A59,0x0A5A,0x0A5B,0x0A5C,0x0A5D,0x0A5E,0x0A5F, + 0x0A60,0x0A61,0x0A62,0x0A63,0x0A64,0x0A65,0x0A66,0x0A67,0x0A68,0x0A69,0x0A6A,0x0A6B,0x0A6C,0x0A6D,0x0A6E,0x0A6F, + 0x0A70,0x0A71,0x0A72,0x0A73,0x0A74,0x0A75,0x0A76,0x0A77,0x0A78,0x0A79,0x0A7A,0x0A7B,0x0A7C,0x0A7D,0x0A7E,0x0A7F, + 0x0A80,0x0A81,0x0A82,0x0A83,0x0A84,0x0A85,0x0A86,0x0A87,0x0A88,0x0A89,0x0A8A,0x0A8B,0x0A8C,0x0A8D,0x0A8E,0x0A8F, + 0x0A90,0x0A91,0x0A92,0x0A93,0x0A94,0x0A95,0x0A96,0x0A97,0x0A98,0x0A99,0x0A9A,0x0A9B,0x0A9C,0x0A9D,0x0A9E,0x0A9F, + 0x0AA0,0x0AA1,0x0AA2,0x0AA3,0x0AA4,0x0AA5,0x0AA6,0x0AA7,0x0AA8,0x0AA9,0x0AAA,0x0AAB,0x0AAC,0x0AAD,0x0AAE,0x0AAF, + 0x0AB0,0x0AB1,0x0AB2,0x0AB3,0x0AB4,0x0AB5,0x0AB6,0x0AB7,0x0AB8,0x0AB9,0x0ABA,0x0ABB,0x0ABC,0x0ABD,0x0ABE,0x0ABF, + 0x0AC0,0x0AC1,0x0AC2,0x0AC3,0x0AC4,0x0AC5,0x0AC6,0x0AC7,0x0AC8,0x0AC9,0x0ACA,0x0ACB,0x0ACC,0x0ACD,0x0ACE,0x0ACF, + 0x0AD0,0x0AD1,0x0AD2,0x0AD3,0x0AD4,0x0AD5,0x0AD6,0x0AD7,0x0AD8,0x0AD9,0x0ADA,0x0ADB,0x0ADC,0x0ADD,0x0ADE,0x0ADF, + 0x0AE0,0x0AE1,0x0AE2,0x0AE3,0x0AE4,0x0AE5,0x0AE6,0x0AE7,0x0AE8,0x0AE9,0x0AEA,0x0AEB,0x0AEC,0x0AED,0x0AEE,0x0AEF, + 0x0AF0,0x0AF1,0x0AF2,0x0AF3,0x0AF4,0x0AF5,0x0AF6,0x0AF7,0x0AF8,0x0AF9,0x0AFA,0x0AFB,0x0AFC,0x0AFD,0x0AFE,0x0AFF, + 0x0B00,0x0B01,0x0B02,0x0B03,0x0B04,0x0B05,0x0B06,0x0B07,0x0B08,0x0B09,0x0B0A,0x0B0B,0x0B0C,0x0B0D,0x0B0E,0x0B0F, + 0x0B10,0x0B11,0x0B12,0x0B13,0x0B14,0x0B15,0x0B16,0x0B17,0x0B18,0x0B19,0x0B1A,0x0B1B,0x0B1C,0x0B1D,0x0B1E,0x0B1F, + 0x0B20,0x0B21,0x0B22,0x0B23,0x0B24,0x0B25,0x0B26,0x0B27,0x0B28,0x0B29,0x0B2A,0x0B2B,0x0B2C,0x0B2D,0x0B2E,0x0B2F, + 0x0B30,0x0B31,0x0B32,0x0B33,0x0B34,0x0B35,0x0B36,0x0B37,0x0B38,0x0B39,0x0B3A,0x0B3B,0x0B3C,0x0B3D,0x0B3E,0x0B3F, + 0x0B40,0x0B41,0x0B42,0x0B43,0x0B44,0x0B45,0x0B46,0x0B47,0x0B48,0x0B49,0x0B4A,0x0B4B,0x0B4C,0x0B4D,0x0B4E,0x0B4F, + 0x0B50,0x0B51,0x0B52,0x0B53,0x0B54,0x0B55,0x0B56,0x0B57,0x0B58,0x0B59,0x0B5A,0x0B5B,0x0B5C,0x0B5D,0x0B5E,0x0B5F, + 0x0B60,0x0B61,0x0B62,0x0B63,0x0B64,0x0B65,0x0B66,0x0B67,0x0B68,0x0B69,0x0B6A,0x0B6B,0x0B6C,0x0B6D,0x0B6E,0x0B6F, + 0x0B70,0x0B71,0x0B72,0x0B73,0x0B74,0x0B75,0x0B76,0x0B77,0x0B78,0x0B79,0x0B7A,0x0B7B,0x0B7C,0x0B7D,0x0B7E,0x0B7F, + 0x0B80,0x0B81,0x0B82,0x0B83,0x0B84,0x0B85,0x0B86,0x0B87,0x0B88,0x0B89,0x0B8A,0x0B8B,0x0B8C,0x0B8D,0x0B8E,0x0B8F, + 0x0B90,0x0B91,0x0B92,0x0B93,0x0B94,0x0B95,0x0B96,0x0B97,0x0B98,0x0B99,0x0B9A,0x0B9B,0x0B9C,0x0B9D,0x0B9E,0x0B9F, + 0x0BA0,0x0BA1,0x0BA2,0x0BA3,0x0BA4,0x0BA5,0x0BA6,0x0BA7,0x0BA8,0x0BA9,0x0BAA,0x0BAB,0x0BAC,0x0BAD,0x0BAE,0x0BAF, + 0x0BB0,0x0BB1,0x0BB2,0x0BB3,0x0BB4,0x0BB5,0x0BB6,0x0BB7,0x0BB8,0x0BB9,0x0BBA,0x0BBB,0x0BBC,0x0BBD,0x0BBE,0x0BBF, + 0x0BC0,0x0BC1,0x0BC2,0x0BC3,0x0BC4,0x0BC5,0x0BC6,0x0BC7,0x0BC8,0x0BC9,0x0BCA,0x0BCB,0x0BCC,0x0BCD,0x0BCE,0x0BCF, + 0x0BD0,0x0BD1,0x0BD2,0x0BD3,0x0BD4,0x0BD5,0x0BD6,0x0BD7,0x0BD8,0x0BD9,0x0BDA,0x0BDB,0x0BDC,0x0BDD,0x0BDE,0x0BDF, + 0x0BE0,0x0BE1,0x0BE2,0x0BE3,0x0BE4,0x0BE5,0x0BE6,0x0BE7,0x0BE8,0x0BE9,0x0BEA,0x0BEB,0x0BEC,0x0BED,0x0BEE,0x0BEF, + 0x0BF0,0x0BF1,0x0BF2,0x0BF3,0x0BF4,0x0BF5,0x0BF6,0x0BF7,0x0BF8,0x0BF9,0x0BFA,0x0BFB,0x0BFC,0x0BFD,0x0BFE,0x0BFF, + 0x0C00,0x0C01,0x0C02,0x0C03,0x0C04,0x0C05,0x0C06,0x0C07,0x0C08,0x0C09,0x0C0A,0x0C0B,0x0C0C,0x0C0D,0x0C0E,0x0C0F, + 0x0C10,0x0C11,0x0C12,0x0C13,0x0C14,0x0C15,0x0C16,0x0C17,0x0C18,0x0C19,0x0C1A,0x0C1B,0x0C1C,0x0C1D,0x0C1E,0x0C1F, + 0x0C20,0x0C21,0x0C22,0x0C23,0x0C24,0x0C25,0x0C26,0x0C27,0x0C28,0x0C29,0x0C2A,0x0C2B,0x0C2C,0x0C2D,0x0C2E,0x0C2F, + 0x0C30,0x0C31,0x0C32,0x0C33,0x0C34,0x0C35,0x0C36,0x0C37,0x0C38,0x0C39,0x0C3A,0x0C3B,0x0C3C,0x0C3D,0x0C3E,0x0C3F, + 0x0C40,0x0C41,0x0C42,0x0C43,0x0C44,0x0C45,0x0C46,0x0C47,0x0C48,0x0C49,0x0C4A,0x0C4B,0x0C4C,0x0C4D,0x0C4E,0x0C4F, + 0x0C50,0x0C51,0x0C52,0x0C53,0x0C54,0x0C55,0x0C56,0x0C57,0x0C58,0x0C59,0x0C5A,0x0C5B,0x0C5C,0x0C5D,0x0C5E,0x0C5F, + 0x0C60,0x0C61,0x0C62,0x0C63,0x0C64,0x0C65,0x0C66,0x0C67,0x0C68,0x0C69,0x0C6A,0x0C6B,0x0C6C,0x0C6D,0x0C6E,0x0C6F, + 0x0C70,0x0C71,0x0C72,0x0C73,0x0C74,0x0C75,0x0C76,0x0C77,0x0C78,0x0C79,0x0C7A,0x0C7B,0x0C7C,0x0C7D,0x0C7E,0x0C7F, + 0x0C80,0x0C81,0x0C82,0x0C83,0x0C84,0x0C85,0x0C86,0x0C87,0x0C88,0x0C89,0x0C8A,0x0C8B,0x0C8C,0x0C8D,0x0C8E,0x0C8F, + 0x0C90,0x0C91,0x0C92,0x0C93,0x0C94,0x0C95,0x0C96,0x0C97,0x0C98,0x0C99,0x0C9A,0x0C9B,0x0C9C,0x0C9D,0x0C9E,0x0C9F, + 0x0CA0,0x0CA1,0x0CA2,0x0CA3,0x0CA4,0x0CA5,0x0CA6,0x0CA7,0x0CA8,0x0CA9,0x0CAA,0x0CAB,0x0CAC,0x0CAD,0x0CAE,0x0CAF, + 0x0CB0,0x0CB1,0x0CB2,0x0CB3,0x0CB4,0x0CB5,0x0CB6,0x0CB7,0x0CB8,0x0CB9,0x0CBA,0x0CBB,0x0CBC,0x0CBD,0x0CBE,0x0CBF, + 0x0CC0,0x0CC1,0x0CC2,0x0CC3,0x0CC4,0x0CC5,0x0CC6,0x0CC7,0x0CC8,0x0CC9,0x0CCA,0x0CCB,0x0CCC,0x0CCD,0x0CCE,0x0CCF, + 0x0CD0,0x0CD1,0x0CD2,0x0CD3,0x0CD4,0x0CD5,0x0CD6,0x0CD7,0x0CD8,0x0CD9,0x0CDA,0x0CDB,0x0CDC,0x0CDD,0x0CDE,0x0CDF, + 0x0CE0,0x0CE1,0x0CE2,0x0CE3,0x0CE4,0x0CE5,0x0CE6,0x0CE7,0x0CE8,0x0CE9,0x0CEA,0x0CEB,0x0CEC,0x0CED,0x0CEE,0x0CEF, + 0x0CF0,0x0CF1,0x0CF2,0x0CF3,0x0CF4,0x0CF5,0x0CF6,0x0CF7,0x0CF8,0x0CF9,0x0CFA,0x0CFB,0x0CFC,0x0CFD,0x0CFE,0x0CFF, + 0x0D00,0x0D01,0x0D02,0x0D03,0x0D04,0x0D05,0x0D06,0x0D07,0x0D08,0x0D09,0x0D0A,0x0D0B,0x0D0C,0x0D0D,0x0D0E,0x0D0F, + 0x0D10,0x0D11,0x0D12,0x0D13,0x0D14,0x0D15,0x0D16,0x0D17,0x0D18,0x0D19,0x0D1A,0x0D1B,0x0D1C,0x0D1D,0x0D1E,0x0D1F, + 0x0D20,0x0D21,0x0D22,0x0D23,0x0D24,0x0D25,0x0D26,0x0D27,0x0D28,0x0D29,0x0D2A,0x0D2B,0x0D2C,0x0D2D,0x0D2E,0x0D2F, + 0x0D30,0x0D31,0x0D32,0x0D33,0x0D34,0x0D35,0x0D36,0x0D37,0x0D38,0x0D39,0x0D3A,0x0D3B,0x0D3C,0x0D3D,0x0D3E,0x0D3F, + 0x0D40,0x0D41,0x0D42,0x0D43,0x0D44,0x0D45,0x0D46,0x0D47,0x0D48,0x0D49,0x0D4A,0x0D4B,0x0D4C,0x0D4D,0x0D4E,0x0D4F, + 0x0D50,0x0D51,0x0D52,0x0D53,0x0D54,0x0D55,0x0D56,0x0D57,0x0D58,0x0D59,0x0D5A,0x0D5B,0x0D5C,0x0D5D,0x0D5E,0x0D5F, + 0x0D60,0x0D61,0x0D62,0x0D63,0x0D64,0x0D65,0x0D66,0x0D67,0x0D68,0x0D69,0x0D6A,0x0D6B,0x0D6C,0x0D6D,0x0D6E,0x0D6F, + 0x0D70,0x0D71,0x0D72,0x0D73,0x0D74,0x0D75,0x0D76,0x0D77,0x0D78,0x0D79,0x0D7A,0x0D7B,0x0D7C,0x0D7D,0x0D7E,0x0D7F, + 0x0D80,0x0D81,0x0D82,0x0D83,0x0D84,0x0D85,0x0D86,0x0D87,0x0D88,0x0D89,0x0D8A,0x0D8B,0x0D8C,0x0D8D,0x0D8E,0x0D8F, + 0x0D90,0x0D91,0x0D92,0x0D93,0x0D94,0x0D95,0x0D96,0x0D97,0x0D98,0x0D99,0x0D9A,0x0D9B,0x0D9C,0x0D9D,0x0D9E,0x0D9F, + 0x0DA0,0x0DA1,0x0DA2,0x0DA3,0x0DA4,0x0DA5,0x0DA6,0x0DA7,0x0DA8,0x0DA9,0x0DAA,0x0DAB,0x0DAC,0x0DAD,0x0DAE,0x0DAF, + 0x0DB0,0x0DB1,0x0DB2,0x0DB3,0x0DB4,0x0DB5,0x0DB6,0x0DB7,0x0DB8,0x0DB9,0x0DBA,0x0DBB,0x0DBC,0x0DBD,0x0DBE,0x0DBF, + 0x0DC0,0x0DC1,0x0DC2,0x0DC3,0x0DC4,0x0DC5,0x0DC6,0x0DC7,0x0DC8,0x0DC9,0x0DCA,0x0DCB,0x0DCC,0x0DCD,0x0DCE,0x0DCF, + 0x0DD0,0x0DD1,0x0DD2,0x0DD3,0x0DD4,0x0DD5,0x0DD6,0x0DD7,0x0DD8,0x0DD9,0x0DDA,0x0DDB,0x0DDC,0x0DDD,0x0DDE,0x0DDF, + 0x0DE0,0x0DE1,0x0DE2,0x0DE3,0x0DE4,0x0DE5,0x0DE6,0x0DE7,0x0DE8,0x0DE9,0x0DEA,0x0DEB,0x0DEC,0x0DED,0x0DEE,0x0DEF, + 0x0DF0,0x0DF1,0x0DF2,0x0DF3,0x0DF4,0x0DF5,0x0DF6,0x0DF7,0x0DF8,0x0DF9,0x0DFA,0x0DFB,0x0DFC,0x0DFD,0x0DFE,0x0DFF, + 0x0E00,0x0E01,0x0E02,0x0E03,0x0E04,0x0E05,0x0E06,0x0E07,0x0E08,0x0E09,0x0E0A,0x0E0B,0x0E0C,0x0E0D,0x0E0E,0x0E0F, + 0x0E10,0x0E11,0x0E12,0x0E13,0x0E14,0x0E15,0x0E16,0x0E17,0x0E18,0x0E19,0x0E1A,0x0E1B,0x0E1C,0x0E1D,0x0E1E,0x0E1F, + 0x0E20,0x0E21,0x0E22,0x0E23,0x0E24,0x0E25,0x0E26,0x0E27,0x0E28,0x0E29,0x0E2A,0x0E2B,0x0E2C,0x0E2D,0x0E2E,0x0E2F, + 0x0E30,0x0E31,0x0E32,0x0E33,0x0E34,0x0E35,0x0E36,0x0E37,0x0E38,0x0E39,0x0E3A,0x0E3B,0x0E3C,0x0E3D,0x0E3E,0x0E3F, + 0x0E40,0x0E41,0x0E42,0x0E43,0x0E44,0x0E45,0x0E46,0x0E47,0x0E48,0x0E49,0x0E4A,0x0E4B,0x0E4C,0x0E4D,0x0E4E,0x0E4F, + 0x0E50,0x0E51,0x0E52,0x0E53,0x0E54,0x0E55,0x0E56,0x0E57,0x0E58,0x0E59,0x0E5A,0x0E5B,0x0E5C,0x0E5D,0x0E5E,0x0E5F, + 0x0E60,0x0E61,0x0E62,0x0E63,0x0E64,0x0E65,0x0E66,0x0E67,0x0E68,0x0E69,0x0E6A,0x0E6B,0x0E6C,0x0E6D,0x0E6E,0x0E6F, + 0x0E70,0x0E71,0x0E72,0x0E73,0x0E74,0x0E75,0x0E76,0x0E77,0x0E78,0x0E79,0x0E7A,0x0E7B,0x0E7C,0x0E7D,0x0E7E,0x0E7F, + 0x0E80,0x0E81,0x0E82,0x0E83,0x0E84,0x0E85,0x0E86,0x0E87,0x0E88,0x0E89,0x0E8A,0x0E8B,0x0E8C,0x0E8D,0x0E8E,0x0E8F, + 0x0E90,0x0E91,0x0E92,0x0E93,0x0E94,0x0E95,0x0E96,0x0E97,0x0E98,0x0E99,0x0E9A,0x0E9B,0x0E9C,0x0E9D,0x0E9E,0x0E9F, + 0x0EA0,0x0EA1,0x0EA2,0x0EA3,0x0EA4,0x0EA5,0x0EA6,0x0EA7,0x0EA8,0x0EA9,0x0EAA,0x0EAB,0x0EAC,0x0EAD,0x0EAE,0x0EAF, + 0x0EB0,0x0EB1,0x0EB2,0x0EB3,0x0EB4,0x0EB5,0x0EB6,0x0EB7,0x0EB8,0x0EB9,0x0EBA,0x0EBB,0x0EBC,0x0EBD,0x0EBE,0x0EBF, + 0x0EC0,0x0EC1,0x0EC2,0x0EC3,0x0EC4,0x0EC5,0x0EC6,0x0EC7,0x0EC8,0x0EC9,0x0ECA,0x0ECB,0x0ECC,0x0ECD,0x0ECE,0x0ECF, + 0x0ED0,0x0ED1,0x0ED2,0x0ED3,0x0ED4,0x0ED5,0x0ED6,0x0ED7,0x0ED8,0x0ED9,0x0EDA,0x0EDB,0x0EDC,0x0EDD,0x0EDE,0x0EDF, + 0x0EE0,0x0EE1,0x0EE2,0x0EE3,0x0EE4,0x0EE5,0x0EE6,0x0EE7,0x0EE8,0x0EE9,0x0EEA,0x0EEB,0x0EEC,0x0EED,0x0EEE,0x0EEF, + 0x0EF0,0x0EF1,0x0EF2,0x0EF3,0x0EF4,0x0EF5,0x0EF6,0x0EF7,0x0EF8,0x0EF9,0x0EFA,0x0EFB,0x0EFC,0x0EFD,0x0EFE,0x0EFF, + 0x0F00,0x0F01,0x0F02,0x0F03,0x0F04,0x0F05,0x0F06,0x0F07,0x0F08,0x0F09,0x0F0A,0x0F0B,0x0F0C,0x0F0D,0x0F0E,0x0F0F, + 0x0F10,0x0F11,0x0F12,0x0F13,0x0F14,0x0F15,0x0F16,0x0F17,0x0F18,0x0F19,0x0F1A,0x0F1B,0x0F1C,0x0F1D,0x0F1E,0x0F1F, + 0x0F20,0x0F21,0x0F22,0x0F23,0x0F24,0x0F25,0x0F26,0x0F27,0x0F28,0x0F29,0x0F2A,0x0F2B,0x0F2C,0x0F2D,0x0F2E,0x0F2F, + 0x0F30,0x0F31,0x0F32,0x0F33,0x0F34,0x0F35,0x0F36,0x0F37,0x0F38,0x0F39,0x0F3A,0x0F3B,0x0F3C,0x0F3D,0x0F3E,0x0F3F, + 0x0F40,0x0F41,0x0F42,0x0F43,0x0F44,0x0F45,0x0F46,0x0F47,0x0F48,0x0F49,0x0F4A,0x0F4B,0x0F4C,0x0F4D,0x0F4E,0x0F4F, + 0x0F50,0x0F51,0x0F52,0x0F53,0x0F54,0x0F55,0x0F56,0x0F57,0x0F58,0x0F59,0x0F5A,0x0F5B,0x0F5C,0x0F5D,0x0F5E,0x0F5F, + 0x0F60,0x0F61,0x0F62,0x0F63,0x0F64,0x0F65,0x0F66,0x0F67,0x0F68,0x0F69,0x0F6A,0x0F6B,0x0F6C,0x0F6D,0x0F6E,0x0F6F, + 0x0F70,0x0F71,0x0F72,0x0F73,0x0F74,0x0F75,0x0F76,0x0F77,0x0F78,0x0F79,0x0F7A,0x0F7B,0x0F7C,0x0F7D,0x0F7E,0x0F7F, + 0x0F80,0x0F81,0x0F82,0x0F83,0x0F84,0x0F85,0x0F86,0x0F87,0x0F88,0x0F89,0x0F8A,0x0F8B,0x0F8C,0x0F8D,0x0F8E,0x0F8F, + 0x0F90,0x0F91,0x0F92,0x0F93,0x0F94,0x0F95,0x0F96,0x0F97,0x0F98,0x0F99,0x0F9A,0x0F9B,0x0F9C,0x0F9D,0x0F9E,0x0F9F, + 0x0FA0,0x0FA1,0x0FA2,0x0FA3,0x0FA4,0x0FA5,0x0FA6,0x0FA7,0x0FA8,0x0FA9,0x0FAA,0x0FAB,0x0FAC,0x0FAD,0x0FAE,0x0FAF, + 0x0FB0,0x0FB1,0x0FB2,0x0FB3,0x0FB4,0x0FB5,0x0FB6,0x0FB7,0x0FB8,0x0FB9,0x0FBA,0x0FBB,0x0FBC,0x0FBD,0x0FBE,0x0FBF, + 0x0FC0,0x0FC1,0x0FC2,0x0FC3,0x0FC4,0x0FC5,0x0FC6,0x0FC7,0x0FC8,0x0FC9,0x0FCA,0x0FCB,0x0FCC,0x0FCD,0x0FCE,0x0FCF, + 0x0FD0,0x0FD1,0x0FD2,0x0FD3,0x0FD4,0x0FD5,0x0FD6,0x0FD7,0x0FD8,0x0FD9,0x0FDA,0x0FDB,0x0FDC,0x0FDD,0x0FDE,0x0FDF, + 0x0FE0,0x0FE1,0x0FE2,0x0FE3,0x0FE4,0x0FE5,0x0FE6,0x0FE7,0x0FE8,0x0FE9,0x0FEA,0x0FEB,0x0FEC,0x0FED,0x0FEE,0x0FEF, + 0x0FF0,0x0FF1,0x0FF2,0x0FF3,0x0FF4,0x0FF5,0x0FF6,0x0FF7,0x0FF8,0x0FF9,0x0FFA,0x0FFB,0x0FFC,0x0FFD,0x0FFE,0x0FFF, + 0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007,0x1008,0x1009,0x100A,0x100B,0x100C,0x100D,0x100E,0x100F, + 0x1010,0x1011,0x1012,0x1013,0x1014,0x1015,0x1016,0x1017,0x1018,0x1019,0x101A,0x101B,0x101C,0x101D,0x101E,0x101F, + 0x1020,0x1021,0x1022,0x1023,0x1024,0x1025,0x1026,0x1027,0x1028,0x1029,0x102A,0x102B,0x102C,0x102D,0x102E,0x102F, + 0x1030,0x1031,0x1032,0x1033,0x1034,0x1035,0x1036,0x1037,0x1038,0x1039,0x103A,0x103B,0x103C,0x103D,0x103E,0x103F, + 0x1040,0x1041,0x1042,0x1043,0x1044,0x1045,0x1046,0x1047,0x1048,0x1049,0x104A,0x104B,0x104C,0x104D,0x104E,0x104F, + 0x1050,0x1051,0x1052,0x1053,0x1054,0x1055,0x1056,0x1057,0x1058,0x1059,0x105A,0x105B,0x105C,0x105D,0x105E,0x105F, + 0x1060,0x1061,0x1062,0x1063,0x1064,0x1065,0x1066,0x1067,0x1068,0x1069,0x106A,0x106B,0x106C,0x106D,0x106E,0x106F, + 0x1070,0x1071,0x1072,0x1073,0x1074,0x1075,0x1076,0x1077,0x1078,0x1079,0x107A,0x107B,0x107C,0x107D,0x107E,0x107F, + 0x1080,0x1081,0x1082,0x1083,0x1084,0x1085,0x1086,0x1087,0x1088,0x1089,0x108A,0x108B,0x108C,0x108D,0x108E,0x108F, + 0x1090,0x1091,0x1092,0x1093,0x1094,0x1095,0x1096,0x1097,0x1098,0x1099,0x109A,0x109B,0x109C,0x109D,0x109E,0x109F, + 0x10A0,0x10A1,0x10A2,0x10A3,0x10A4,0x10A5,0x10A6,0x10A7,0x10A8,0x10A9,0x10AA,0x10AB,0x10AC,0x10AD,0x10AE,0x10AF, + 0x10B0,0x10B1,0x10B2,0x10B3,0x10B4,0x10B5,0x10B6,0x10B7,0x10B8,0x10B9,0x10BA,0x10BB,0x10BC,0x10BD,0x10BE,0x10BF, + 0x10C0,0x10C1,0x10C2,0x10C3,0x10C4,0x10C5,0x10C6,0x10C7,0x10C8,0x10C9,0x10CA,0x10CB,0x10CC,0x10CD,0x10CE,0x10CF, + 0x10D0,0x10D1,0x10D2,0x10D3,0x10D4,0x10D5,0x10D6,0x10D7,0x10D8,0x10D9,0x10DA,0x10DB,0x10DC,0x10DD,0x10DE,0x10DF, + 0x10E0,0x10E1,0x10E2,0x10E3,0x10E4,0x10E5,0x10E6,0x10E7,0x10E8,0x10E9,0x10EA,0x10EB,0x10EC,0x10ED,0x10EE,0x10EF, + 0x10F0,0x10F1,0x10F2,0x10F3,0x10F4,0x10F5,0x10F6,0x10F7,0x10F8,0x10F9,0x10FA,0x10FB,0x10FC,0x10FD,0x10FE,0x10FF, + 0x1100,0x1101,0x1102,0x1103,0x1104,0x1105,0x1106,0x1107,0x1108,0x1109,0x110A,0x110B,0x110C,0x110D,0x110E,0x110F, + 0x1110,0x1111,0x1112,0x1113,0x1114,0x1115,0x1116,0x1117,0x1118,0x1119,0x111A,0x111B,0x111C,0x111D,0x111E,0x111F, + 0x1120,0x1121,0x1122,0x1123,0x1124,0x1125,0x1126,0x1127,0x1128,0x1129,0x112A,0x112B,0x112C,0x112D,0x112E,0x112F, + 0x1130,0x1131,0x1132,0x1133,0x1134,0x1135,0x1136,0x1137,0x1138,0x1139,0x113A,0x113B,0x113C,0x113D,0x113E,0x113F, + 0x1140,0x1141,0x1142,0x1143,0x1144,0x1145,0x1146,0x1147,0x1148,0x1149,0x114A,0x114B,0x114C,0x114D,0x114E,0x114F, + 0x1150,0x1151,0x1152,0x1153,0x1154,0x1155,0x1156,0x1157,0x1158,0x1159,0x115A,0x115B,0x115C,0x115D,0x115E,0x115F, + 0x1160,0x1161,0x1162,0x1163,0x1164,0x1165,0x1166,0x1167,0x1168,0x1169,0x116A,0x116B,0x116C,0x116D,0x116E,0x116F, + 0x1170,0x1171,0x1172,0x1173,0x1174,0x1175,0x1176,0x1177,0x1178,0x1179,0x117A,0x117B,0x117C,0x117D,0x117E,0x117F, + 0x1180,0x1181,0x1182,0x1183,0x1184,0x1185,0x1186,0x1187,0x1188,0x1189,0x118A,0x118B,0x118C,0x118D,0x118E,0x118F, + 0x1190,0x1191,0x1192,0x1193,0x1194,0x1195,0x1196,0x1197,0x1198,0x1199,0x119A,0x119B,0x119C,0x119D,0x119E,0x119F, + 0x11A0,0x11A1,0x11A2,0x11A3,0x11A4,0x11A5,0x11A6,0x11A7,0x11A8,0x11A9,0x11AA,0x11AB,0x11AC,0x11AD,0x11AE,0x11AF, + 0x11B0,0x11B1,0x11B2,0x11B3,0x11B4,0x11B5,0x11B6,0x11B7,0x11B8,0x11B9,0x11BA,0x11BB,0x11BC,0x11BD,0x11BE,0x11BF, + 0x11C0,0x11C1,0x11C2,0x11C3,0x11C4,0x11C5,0x11C6,0x11C7,0x11C8,0x11C9,0x11CA,0x11CB,0x11CC,0x11CD,0x11CE,0x11CF, + 0x11D0,0x11D1,0x11D2,0x11D3,0x11D4,0x11D5,0x11D6,0x11D7,0x11D8,0x11D9,0x11DA,0x11DB,0x11DC,0x11DD,0x11DE,0x11DF, + 0x11E0,0x11E1,0x11E2,0x11E3,0x11E4,0x11E5,0x11E6,0x11E7,0x11E8,0x11E9,0x11EA,0x11EB,0x11EC,0x11ED,0x11EE,0x11EF, + 0x11F0,0x11F1,0x11F2,0x11F3,0x11F4,0x11F5,0x11F6,0x11F7,0x11F8,0x11F9,0x11FA,0x11FB,0x11FC,0x11FD,0x11FE,0x11FF, + 0x1200,0x1201,0x1202,0x1203,0x1204,0x1205,0x1206,0x1207,0x1208,0x1209,0x120A,0x120B,0x120C,0x120D,0x120E,0x120F, + 0x1210,0x1211,0x1212,0x1213,0x1214,0x1215,0x1216,0x1217,0x1218,0x1219,0x121A,0x121B,0x121C,0x121D,0x121E,0x121F, + 0x1220,0x1221,0x1222,0x1223,0x1224,0x1225,0x1226,0x1227,0x1228,0x1229,0x122A,0x122B,0x122C,0x122D,0x122E,0x122F, + 0x1230,0x1231,0x1232,0x1233,0x1234,0x1235,0x1236,0x1237,0x1238,0x1239,0x123A,0x123B,0x123C,0x123D,0x123E,0x123F, + 0x1240,0x1241,0x1242,0x1243,0x1244,0x1245,0x1246,0x1247,0x1248,0x1249,0x124A,0x124B,0x124C,0x124D,0x124E,0x124F, + 0x1250,0x1251,0x1252,0x1253,0x1254,0x1255,0x1256,0x1257,0x1258,0x1259,0x125A,0x125B,0x125C,0x125D,0x125E,0x125F, + 0x1260,0x1261,0x1262,0x1263,0x1264,0x1265,0x1266,0x1267,0x1268,0x1269,0x126A,0x126B,0x126C,0x126D,0x126E,0x126F, + 0x1270,0x1271,0x1272,0x1273,0x1274,0x1275,0x1276,0x1277,0x1278,0x1279,0x127A,0x127B,0x127C,0x127D,0x127E,0x127F, + 0x1280,0x1281,0x1282,0x1283,0x1284,0x1285,0x1286,0x1287,0x1288,0x1289,0x128A,0x128B,0x128C,0x128D,0x128E,0x128F, + 0x1290,0x1291,0x1292,0x1293,0x1294,0x1295,0x1296,0x1297,0x1298,0x1299,0x129A,0x129B,0x129C,0x129D,0x129E,0x129F, + 0x12A0,0x12A1,0x12A2,0x12A3,0x12A4,0x12A5,0x12A6,0x12A7,0x12A8,0x12A9,0x12AA,0x12AB,0x12AC,0x12AD,0x12AE,0x12AF, + 0x12B0,0x12B1,0x12B2,0x12B3,0x12B4,0x12B5,0x12B6,0x12B7,0x12B8,0x12B9,0x12BA,0x12BB,0x12BC,0x12BD,0x12BE,0x12BF, + 0x12C0,0x12C1,0x12C2,0x12C3,0x12C4,0x12C5,0x12C6,0x12C7,0x12C8,0x12C9,0x12CA,0x12CB,0x12CC,0x12CD,0x12CE,0x12CF, + 0x12D0,0x12D1,0x12D2,0x12D3,0x12D4,0x12D5,0x12D6,0x12D7,0x12D8,0x12D9,0x12DA,0x12DB,0x12DC,0x12DD,0x12DE,0x12DF, + 0x12E0,0x12E1,0x12E2,0x12E3,0x12E4,0x12E5,0x12E6,0x12E7,0x12E8,0x12E9,0x12EA,0x12EB,0x12EC,0x12ED,0x12EE,0x12EF, + 0x12F0,0x12F1,0x12F2,0x12F3,0x12F4,0x12F5,0x12F6,0x12F7,0x12F8,0x12F9,0x12FA,0x12FB,0x12FC,0x12FD,0x12FE,0x12FF, + 0x1300,0x1301,0x1302,0x1303,0x1304,0x1305,0x1306,0x1307,0x1308,0x1309,0x130A,0x130B,0x130C,0x130D,0x130E,0x130F, + 0x1310,0x1311,0x1312,0x1313,0x1314,0x1315,0x1316,0x1317,0x1318,0x1319,0x131A,0x131B,0x131C,0x131D,0x131E,0x131F, + 0x1320,0x1321,0x1322,0x1323,0x1324,0x1325,0x1326,0x1327,0x1328,0x1329,0x132A,0x132B,0x132C,0x132D,0x132E,0x132F, + 0x1330,0x1331,0x1332,0x1333,0x1334,0x1335,0x1336,0x1337,0x1338,0x1339,0x133A,0x133B,0x133C,0x133D,0x133E,0x133F, + 0x1340,0x1341,0x1342,0x1343,0x1344,0x1345,0x1346,0x1347,0x1348,0x1349,0x134A,0x134B,0x134C,0x134D,0x134E,0x134F, + 0x1350,0x1351,0x1352,0x1353,0x1354,0x1355,0x1356,0x1357,0x1358,0x1359,0x135A,0x135B,0x135C,0x135D,0x135E,0x135F, + 0x1360,0x1361,0x1362,0x1363,0x1364,0x1365,0x1366,0x1367,0x1368,0x1369,0x136A,0x136B,0x136C,0x136D,0x136E,0x136F, + 0x1370,0x1371,0x1372,0x1373,0x1374,0x1375,0x1376,0x1377,0x1378,0x1379,0x137A,0x137B,0x137C,0x137D,0x137E,0x137F, + 0x1380,0x1381,0x1382,0x1383,0x1384,0x1385,0x1386,0x1387,0x1388,0x1389,0x138A,0x138B,0x138C,0x138D,0x138E,0x138F, + 0x1390,0x1391,0x1392,0x1393,0x1394,0x1395,0x1396,0x1397,0x1398,0x1399,0x139A,0x139B,0x139C,0x139D,0x139E,0x139F, + 0x13A0,0x13A1,0x13A2,0x13A3,0x13A4,0x13A5,0x13A6,0x13A7,0x13A8,0x13A9,0x13AA,0x13AB,0x13AC,0x13AD,0x13AE,0x13AF, + 0x13B0,0x13B1,0x13B2,0x13B3,0x13B4,0x13B5,0x13B6,0x13B7,0x13B8,0x13B9,0x13BA,0x13BB,0x13BC,0x13BD,0x13BE,0x13BF, + 0x13C0,0x13C1,0x13C2,0x13C3,0x13C4,0x13C5,0x13C6,0x13C7,0x13C8,0x13C9,0x13CA,0x13CB,0x13CC,0x13CD,0x13CE,0x13CF, + 0x13D0,0x13D1,0x13D2,0x13D3,0x13D4,0x13D5,0x13D6,0x13D7,0x13D8,0x13D9,0x13DA,0x13DB,0x13DC,0x13DD,0x13DE,0x13DF, + 0x13E0,0x13E1,0x13E2,0x13E3,0x13E4,0x13E5,0x13E6,0x13E7,0x13E8,0x13E9,0x13EA,0x13EB,0x13EC,0x13ED,0x13EE,0x13EF, + 0x13F0,0x13F1,0x13F2,0x13F3,0x13F4,0x13F5,0x13F6,0x13F7,0x13F8,0x13F9,0x13FA,0x13FB,0x13FC,0x13FD,0x13FE,0x13FF, + 0x1400,0x1401,0x1402,0x1403,0x1404,0x1405,0x1406,0x1407,0x1408,0x1409,0x140A,0x140B,0x140C,0x140D,0x140E,0x140F, + 0x1410,0x1411,0x1412,0x1413,0x1414,0x1415,0x1416,0x1417,0x1418,0x1419,0x141A,0x141B,0x141C,0x141D,0x141E,0x141F, + 0x1420,0x1421,0x1422,0x1423,0x1424,0x1425,0x1426,0x1427,0x1428,0x1429,0x142A,0x142B,0x142C,0x142D,0x142E,0x142F, + 0x1430,0x1431,0x1432,0x1433,0x1434,0x1435,0x1436,0x1437,0x1438,0x1439,0x143A,0x143B,0x143C,0x143D,0x143E,0x143F, + 0x1440,0x1441,0x1442,0x1443,0x1444,0x1445,0x1446,0x1447,0x1448,0x1449,0x144A,0x144B,0x144C,0x144D,0x144E,0x144F, + 0x1450,0x1451,0x1452,0x1453,0x1454,0x1455,0x1456,0x1457,0x1458,0x1459,0x145A,0x145B,0x145C,0x145D,0x145E,0x145F, + 0x1460,0x1461,0x1462,0x1463,0x1464,0x1465,0x1466,0x1467,0x1468,0x1469,0x146A,0x146B,0x146C,0x146D,0x146E,0x146F, + 0x1470,0x1471,0x1472,0x1473,0x1474,0x1475,0x1476,0x1477,0x1478,0x1479,0x147A,0x147B,0x147C,0x147D,0x147E,0x147F, + 0x1480,0x1481,0x1482,0x1483,0x1484,0x1485,0x1486,0x1487,0x1488,0x1489,0x148A,0x148B,0x148C,0x148D,0x148E,0x148F, + 0x1490,0x1491,0x1492,0x1493,0x1494,0x1495,0x1496,0x1497,0x1498,0x1499,0x149A,0x149B,0x149C,0x149D,0x149E,0x149F, + 0x14A0,0x14A1,0x14A2,0x14A3,0x14A4,0x14A5,0x14A6,0x14A7,0x14A8,0x14A9,0x14AA,0x14AB,0x14AC,0x14AD,0x14AE,0x14AF, + 0x14B0,0x14B1,0x14B2,0x14B3,0x14B4,0x14B5,0x14B6,0x14B7,0x14B8,0x14B9,0x14BA,0x14BB,0x14BC,0x14BD,0x14BE,0x14BF, + 0x14C0,0x14C1,0x14C2,0x14C3,0x14C4,0x14C5,0x14C6,0x14C7,0x14C8,0x14C9,0x14CA,0x14CB,0x14CC,0x14CD,0x14CE,0x14CF, + 0x14D0,0x14D1,0x14D2,0x14D3,0x14D4,0x14D5,0x14D6,0x14D7,0x14D8,0x14D9,0x14DA,0x14DB,0x14DC,0x14DD,0x14DE,0x14DF, + 0x14E0,0x14E1,0x14E2,0x14E3,0x14E4,0x14E5,0x14E6,0x14E7,0x14E8,0x14E9,0x14EA,0x14EB,0x14EC,0x14ED,0x14EE,0x14EF, + 0x14F0,0x14F1,0x14F2,0x14F3,0x14F4,0x14F5,0x14F6,0x14F7,0x14F8,0x14F9,0x14FA,0x14FB,0x14FC,0x14FD,0x14FE,0x14FF, + 0x1500,0x1501,0x1502,0x1503,0x1504,0x1505,0x1506,0x1507,0x1508,0x1509,0x150A,0x150B,0x150C,0x150D,0x150E,0x150F, + 0x1510,0x1511,0x1512,0x1513,0x1514,0x1515,0x1516,0x1517,0x1518,0x1519,0x151A,0x151B,0x151C,0x151D,0x151E,0x151F, + 0x1520,0x1521,0x1522,0x1523,0x1524,0x1525,0x1526,0x1527,0x1528,0x1529,0x152A,0x152B,0x152C,0x152D,0x152E,0x152F, + 0x1530,0x1531,0x1532,0x1533,0x1534,0x1535,0x1536,0x1537,0x1538,0x1539,0x153A,0x153B,0x153C,0x153D,0x153E,0x153F, + 0x1540,0x1541,0x1542,0x1543,0x1544,0x1545,0x1546,0x1547,0x1548,0x1549,0x154A,0x154B,0x154C,0x154D,0x154E,0x154F, + 0x1550,0x1551,0x1552,0x1553,0x1554,0x1555,0x1556,0x1557,0x1558,0x1559,0x155A,0x155B,0x155C,0x155D,0x155E,0x155F, + 0x1560,0x1561,0x1562,0x1563,0x1564,0x1565,0x1566,0x1567,0x1568,0x1569,0x156A,0x156B,0x156C,0x156D,0x156E,0x156F, + 0x1570,0x1571,0x1572,0x1573,0x1574,0x1575,0x1576,0x1577,0x1578,0x1579,0x157A,0x157B,0x157C,0x157D,0x157E,0x157F, + 0x1580,0x1581,0x1582,0x1583,0x1584,0x1585,0x1586,0x1587,0x1588,0x1589,0x158A,0x158B,0x158C,0x158D,0x158E,0x158F, + 0x1590,0x1591,0x1592,0x1593,0x1594,0x1595,0x1596,0x1597,0x1598,0x1599,0x159A,0x159B,0x159C,0x159D,0x159E,0x159F, + 0x15A0,0x15A1,0x15A2,0x15A3,0x15A4,0x15A5,0x15A6,0x15A7,0x15A8,0x15A9,0x15AA,0x15AB,0x15AC,0x15AD,0x15AE,0x15AF, + 0x15B0,0x15B1,0x15B2,0x15B3,0x15B4,0x15B5,0x15B6,0x15B7,0x15B8,0x15B9,0x15BA,0x15BB,0x15BC,0x15BD,0x15BE,0x15BF, + 0x15C0,0x15C1,0x15C2,0x15C3,0x15C4,0x15C5,0x15C6,0x15C7,0x15C8,0x15C9,0x15CA,0x15CB,0x15CC,0x15CD,0x15CE,0x15CF, + 0x15D0,0x15D1,0x15D2,0x15D3,0x15D4,0x15D5,0x15D6,0x15D7,0x15D8,0x15D9,0x15DA,0x15DB,0x15DC,0x15DD,0x15DE,0x15DF, + 0x15E0,0x15E1,0x15E2,0x15E3,0x15E4,0x15E5,0x15E6,0x15E7,0x15E8,0x15E9,0x15EA,0x15EB,0x15EC,0x15ED,0x15EE,0x15EF, + 0x15F0,0x15F1,0x15F2,0x15F3,0x15F4,0x15F5,0x15F6,0x15F7,0x15F8,0x15F9,0x15FA,0x15FB,0x15FC,0x15FD,0x15FE,0x15FF, + 0x1600,0x1601,0x1602,0x1603,0x1604,0x1605,0x1606,0x1607,0x1608,0x1609,0x160A,0x160B,0x160C,0x160D,0x160E,0x160F, + 0x1610,0x1611,0x1612,0x1613,0x1614,0x1615,0x1616,0x1617,0x1618,0x1619,0x161A,0x161B,0x161C,0x161D,0x161E,0x161F, + 0x1620,0x1621,0x1622,0x1623,0x1624,0x1625,0x1626,0x1627,0x1628,0x1629,0x162A,0x162B,0x162C,0x162D,0x162E,0x162F, + 0x1630,0x1631,0x1632,0x1633,0x1634,0x1635,0x1636,0x1637,0x1638,0x1639,0x163A,0x163B,0x163C,0x163D,0x163E,0x163F, + 0x1640,0x1641,0x1642,0x1643,0x1644,0x1645,0x1646,0x1647,0x1648,0x1649,0x164A,0x164B,0x164C,0x164D,0x164E,0x164F, + 0x1650,0x1651,0x1652,0x1653,0x1654,0x1655,0x1656,0x1657,0x1658,0x1659,0x165A,0x165B,0x165C,0x165D,0x165E,0x165F, + 0x1660,0x1661,0x1662,0x1663,0x1664,0x1665,0x1666,0x1667,0x1668,0x1669,0x166A,0x166B,0x166C,0x166D,0x166E,0x166F, + 0x1670,0x1671,0x1672,0x1673,0x1674,0x1675,0x1676,0x1677,0x1678,0x1679,0x167A,0x167B,0x167C,0x167D,0x167E,0x167F, + 0x1680,0x1681,0x1682,0x1683,0x1684,0x1685,0x1686,0x1687,0x1688,0x1689,0x168A,0x168B,0x168C,0x168D,0x168E,0x168F, + 0x1690,0x1691,0x1692,0x1693,0x1694,0x1695,0x1696,0x1697,0x1698,0x1699,0x169A,0x169B,0x169C,0x169D,0x169E,0x169F, + 0x16A0,0x16A1,0x16A2,0x16A3,0x16A4,0x16A5,0x16A6,0x16A7,0x16A8,0x16A9,0x16AA,0x16AB,0x16AC,0x16AD,0x16AE,0x16AF, + 0x16B0,0x16B1,0x16B2,0x16B3,0x16B4,0x16B5,0x16B6,0x16B7,0x16B8,0x16B9,0x16BA,0x16BB,0x16BC,0x16BD,0x16BE,0x16BF, + 0x16C0,0x16C1,0x16C2,0x16C3,0x16C4,0x16C5,0x16C6,0x16C7,0x16C8,0x16C9,0x16CA,0x16CB,0x16CC,0x16CD,0x16CE,0x16CF, + 0x16D0,0x16D1,0x16D2,0x16D3,0x16D4,0x16D5,0x16D6,0x16D7,0x16D8,0x16D9,0x16DA,0x16DB,0x16DC,0x16DD,0x16DE,0x16DF, + 0x16E0,0x16E1,0x16E2,0x16E3,0x16E4,0x16E5,0x16E6,0x16E7,0x16E8,0x16E9,0x16EA,0x16EB,0x16EC,0x16ED,0x16EE,0x16EF, + 0x16F0,0x16F1,0x16F2,0x16F3,0x16F4,0x16F5,0x16F6,0x16F7,0x16F8,0x16F9,0x16FA,0x16FB,0x16FC,0x16FD,0x16FE,0x16FF, + 0x1700,0x1701,0x1702,0x1703,0x1704,0x1705,0x1706,0x1707,0x1708,0x1709,0x170A,0x170B,0x170C,0x170D,0x170E,0x170F, + 0x1710,0x1711,0x1712,0x1713,0x1714,0x1715,0x1716,0x1717,0x1718,0x1719,0x171A,0x171B,0x171C,0x171D,0x171E,0x171F, + 0x1720,0x1721,0x1722,0x1723,0x1724,0x1725,0x1726,0x1727,0x1728,0x1729,0x172A,0x172B,0x172C,0x172D,0x172E,0x172F, + 0x1730,0x1731,0x1732,0x1733,0x1734,0x1735,0x1736,0x1737,0x1738,0x1739,0x173A,0x173B,0x173C,0x173D,0x173E,0x173F, + 0x1740,0x1741,0x1742,0x1743,0x1744,0x1745,0x1746,0x1747,0x1748,0x1749,0x174A,0x174B,0x174C,0x174D,0x174E,0x174F, + 0x1750,0x1751,0x1752,0x1753,0x1754,0x1755,0x1756,0x1757,0x1758,0x1759,0x175A,0x175B,0x175C,0x175D,0x175E,0x175F, + 0x1760,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1768,0x1769,0x176A,0x176B,0x176C,0x176D,0x176E,0x176F, + 0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x1776,0x1777,0x1778,0x1779,0x177A,0x177B,0x177C,0x177D,0x177E,0x177F, + 0x1780,0x1781,0x1782,0x1783,0x1784,0x1785,0x1786,0x1787,0x1788,0x1789,0x178A,0x178B,0x178C,0x178D,0x178E,0x178F, + 0x1790,0x1791,0x1792,0x1793,0x1794,0x1795,0x1796,0x1797,0x1798,0x1799,0x179A,0x179B,0x179C,0x179D,0x179E,0x179F, + 0x17A0,0x17A1,0x17A2,0x17A3,0x17A4,0x17A5,0x17A6,0x17A7,0x17A8,0x17A9,0x17AA,0x17AB,0x17AC,0x17AD,0x17AE,0x17AF, + 0x17B0,0x17B1,0x17B2,0x17B3,0x17B4,0x17B5,0x17B6,0x17B7,0x17B8,0x17B9,0x17BA,0x17BB,0x17BC,0x17BD,0x17BE,0x17BF, + 0x17C0,0x17C1,0x17C2,0x17C3,0x17C4,0x17C5,0x17C6,0x17C7,0x17C8,0x17C9,0x17CA,0x17CB,0x17CC,0x17CD,0x17CE,0x17CF, + 0x17D0,0x17D1,0x17D2,0x17D3,0x17D4,0x17D5,0x17D6,0x17D7,0x17D8,0x17D9,0x17DA,0x17DB,0x17DC,0x17DD,0x17DE,0x17DF, + 0x17E0,0x17E1,0x17E2,0x17E3,0x17E4,0x17E5,0x17E6,0x17E7,0x17E8,0x17E9,0x17EA,0x17EB,0x17EC,0x17ED,0x17EE,0x17EF, + 0x17F0,0x17F1,0x17F2,0x17F3,0x17F4,0x17F5,0x17F6,0x17F7,0x17F8,0x17F9,0x17FA,0x17FB,0x17FC,0x17FD,0x17FE,0x17FF, + 0x1800,0x1801,0x1802,0x1803,0x1804,0x1805,0x1806,0x1807,0x1808,0x1809,0x180A,0x180B,0x180C,0x180D,0x180E,0x180F, + 0x1810,0x1811,0x1812,0x1813,0x1814,0x1815,0x1816,0x1817,0x1818,0x1819,0x181A,0x181B,0x181C,0x181D,0x181E,0x181F, + 0x1820,0x1821,0x1822,0x1823,0x1824,0x1825,0x1826,0x1827,0x1828,0x1829,0x182A,0x182B,0x182C,0x182D,0x182E,0x182F, + 0x1830,0x1831,0x1832,0x1833,0x1834,0x1835,0x1836,0x1837,0x1838,0x1839,0x183A,0x183B,0x183C,0x183D,0x183E,0x183F, + 0x1840,0x1841,0x1842,0x1843,0x1844,0x1845,0x1846,0x1847,0x1848,0x1849,0x184A,0x184B,0x184C,0x184D,0x184E,0x184F, + 0x1850,0x1851,0x1852,0x1853,0x1854,0x1855,0x1856,0x1857,0x1858,0x1859,0x185A,0x185B,0x185C,0x185D,0x185E,0x185F, + 0x1860,0x1861,0x1862,0x1863,0x1864,0x1865,0x1866,0x1867,0x1868,0x1869,0x186A,0x186B,0x186C,0x186D,0x186E,0x186F, + 0x1870,0x1871,0x1872,0x1873,0x1874,0x1875,0x1876,0x1877,0x1878,0x1879,0x187A,0x187B,0x187C,0x187D,0x187E,0x187F, + 0x1880,0x1881,0x1882,0x1883,0x1884,0x1885,0x1886,0x1887,0x1888,0x1889,0x188A,0x188B,0x188C,0x188D,0x188E,0x188F, + 0x1890,0x1891,0x1892,0x1893,0x1894,0x1895,0x1896,0x1897,0x1898,0x1899,0x189A,0x189B,0x189C,0x189D,0x189E,0x189F, + 0x18A0,0x18A1,0x18A2,0x18A3,0x18A4,0x18A5,0x18A6,0x18A7,0x18A8,0x18A9,0x18AA,0x18AB,0x18AC,0x18AD,0x18AE,0x18AF, + 0x18B0,0x18B1,0x18B2,0x18B3,0x18B4,0x18B5,0x18B6,0x18B7,0x18B8,0x18B9,0x18BA,0x18BB,0x18BC,0x18BD,0x18BE,0x18BF, + 0x18C0,0x18C1,0x18C2,0x18C3,0x18C4,0x18C5,0x18C6,0x18C7,0x18C8,0x18C9,0x18CA,0x18CB,0x18CC,0x18CD,0x18CE,0x18CF, + 0x18D0,0x18D1,0x18D2,0x18D3,0x18D4,0x18D5,0x18D6,0x18D7,0x18D8,0x18D9,0x18DA,0x18DB,0x18DC,0x18DD,0x18DE,0x18DF, + 0x18E0,0x18E1,0x18E2,0x18E3,0x18E4,0x18E5,0x18E6,0x18E7,0x18E8,0x18E9,0x18EA,0x18EB,0x18EC,0x18ED,0x18EE,0x18EF, + 0x18F0,0x18F1,0x18F2,0x18F3,0x18F4,0x18F5,0x18F6,0x18F7,0x18F8,0x18F9,0x18FA,0x18FB,0x18FC,0x18FD,0x18FE,0x18FF, + 0x1900,0x1901,0x1902,0x1903,0x1904,0x1905,0x1906,0x1907,0x1908,0x1909,0x190A,0x190B,0x190C,0x190D,0x190E,0x190F, + 0x1910,0x1911,0x1912,0x1913,0x1914,0x1915,0x1916,0x1917,0x1918,0x1919,0x191A,0x191B,0x191C,0x191D,0x191E,0x191F, + 0x1920,0x1921,0x1922,0x1923,0x1924,0x1925,0x1926,0x1927,0x1928,0x1929,0x192A,0x192B,0x192C,0x192D,0x192E,0x192F, + 0x1930,0x1931,0x1932,0x1933,0x1934,0x1935,0x1936,0x1937,0x1938,0x1939,0x193A,0x193B,0x193C,0x193D,0x193E,0x193F, + 0x1940,0x1941,0x1942,0x1943,0x1944,0x1945,0x1946,0x1947,0x1948,0x1949,0x194A,0x194B,0x194C,0x194D,0x194E,0x194F, + 0x1950,0x1951,0x1952,0x1953,0x1954,0x1955,0x1956,0x1957,0x1958,0x1959,0x195A,0x195B,0x195C,0x195D,0x195E,0x195F, + 0x1960,0x1961,0x1962,0x1963,0x1964,0x1965,0x1966,0x1967,0x1968,0x1969,0x196A,0x196B,0x196C,0x196D,0x196E,0x196F, + 0x1970,0x1971,0x1972,0x1973,0x1974,0x1975,0x1976,0x1977,0x1978,0x1979,0x197A,0x197B,0x197C,0x197D,0x197E,0x197F, + 0x1980,0x1981,0x1982,0x1983,0x1984,0x1985,0x1986,0x1987,0x1988,0x1989,0x198A,0x198B,0x198C,0x198D,0x198E,0x198F, + 0x1990,0x1991,0x1992,0x1993,0x1994,0x1995,0x1996,0x1997,0x1998,0x1999,0x199A,0x199B,0x199C,0x199D,0x199E,0x199F, + 0x19A0,0x19A1,0x19A2,0x19A3,0x19A4,0x19A5,0x19A6,0x19A7,0x19A8,0x19A9,0x19AA,0x19AB,0x19AC,0x19AD,0x19AE,0x19AF, + 0x19B0,0x19B1,0x19B2,0x19B3,0x19B4,0x19B5,0x19B6,0x19B7,0x19B8,0x19B9,0x19BA,0x19BB,0x19BC,0x19BD,0x19BE,0x19BF, + 0x19C0,0x19C1,0x19C2,0x19C3,0x19C4,0x19C5,0x19C6,0x19C7,0x19C8,0x19C9,0x19CA,0x19CB,0x19CC,0x19CD,0x19CE,0x19CF, + 0x19D0,0x19D1,0x19D2,0x19D3,0x19D4,0x19D5,0x19D6,0x19D7,0x19D8,0x19D9,0x19DA,0x19DB,0x19DC,0x19DD,0x19DE,0x19DF, + 0x19E0,0x19E1,0x19E2,0x19E3,0x19E4,0x19E5,0x19E6,0x19E7,0x19E8,0x19E9,0x19EA,0x19EB,0x19EC,0x19ED,0x19EE,0x19EF, + 0x19F0,0x19F1,0x19F2,0x19F3,0x19F4,0x19F5,0x19F6,0x19F7,0x19F8,0x19F9,0x19FA,0x19FB,0x19FC,0x19FD,0x19FE,0x19FF, + 0x1A00,0x1A01,0x1A02,0x1A03,0x1A04,0x1A05,0x1A06,0x1A07,0x1A08,0x1A09,0x1A0A,0x1A0B,0x1A0C,0x1A0D,0x1A0E,0x1A0F, + 0x1A10,0x1A11,0x1A12,0x1A13,0x1A14,0x1A15,0x1A16,0x1A17,0x1A18,0x1A19,0x1A1A,0x1A1B,0x1A1C,0x1A1D,0x1A1E,0x1A1F, + 0x1A20,0x1A21,0x1A22,0x1A23,0x1A24,0x1A25,0x1A26,0x1A27,0x1A28,0x1A29,0x1A2A,0x1A2B,0x1A2C,0x1A2D,0x1A2E,0x1A2F, + 0x1A30,0x1A31,0x1A32,0x1A33,0x1A34,0x1A35,0x1A36,0x1A37,0x1A38,0x1A39,0x1A3A,0x1A3B,0x1A3C,0x1A3D,0x1A3E,0x1A3F, + 0x1A40,0x1A41,0x1A42,0x1A43,0x1A44,0x1A45,0x1A46,0x1A47,0x1A48,0x1A49,0x1A4A,0x1A4B,0x1A4C,0x1A4D,0x1A4E,0x1A4F, + 0x1A50,0x1A51,0x1A52,0x1A53,0x1A54,0x1A55,0x1A56,0x1A57,0x1A58,0x1A59,0x1A5A,0x1A5B,0x1A5C,0x1A5D,0x1A5E,0x1A5F, + 0x1A60,0x1A61,0x1A62,0x1A63,0x1A64,0x1A65,0x1A66,0x1A67,0x1A68,0x1A69,0x1A6A,0x1A6B,0x1A6C,0x1A6D,0x1A6E,0x1A6F, + 0x1A70,0x1A71,0x1A72,0x1A73,0x1A74,0x1A75,0x1A76,0x1A77,0x1A78,0x1A79,0x1A7A,0x1A7B,0x1A7C,0x1A7D,0x1A7E,0x1A7F, + 0x1A80,0x1A81,0x1A82,0x1A83,0x1A84,0x1A85,0x1A86,0x1A87,0x1A88,0x1A89,0x1A8A,0x1A8B,0x1A8C,0x1A8D,0x1A8E,0x1A8F, + 0x1A90,0x1A91,0x1A92,0x1A93,0x1A94,0x1A95,0x1A96,0x1A97,0x1A98,0x1A99,0x1A9A,0x1A9B,0x1A9C,0x1A9D,0x1A9E,0x1A9F, + 0x1AA0,0x1AA1,0x1AA2,0x1AA3,0x1AA4,0x1AA5,0x1AA6,0x1AA7,0x1AA8,0x1AA9,0x1AAA,0x1AAB,0x1AAC,0x1AAD,0x1AAE,0x1AAF, + 0x1AB0,0x1AB1,0x1AB2,0x1AB3,0x1AB4,0x1AB5,0x1AB6,0x1AB7,0x1AB8,0x1AB9,0x1ABA,0x1ABB,0x1ABC,0x1ABD,0x1ABE,0x1ABF, + 0x1AC0,0x1AC1,0x1AC2,0x1AC3,0x1AC4,0x1AC5,0x1AC6,0x1AC7,0x1AC8,0x1AC9,0x1ACA,0x1ACB,0x1ACC,0x1ACD,0x1ACE,0x1ACF, + 0x1AD0,0x1AD1,0x1AD2,0x1AD3,0x1AD4,0x1AD5,0x1AD6,0x1AD7,0x1AD8,0x1AD9,0x1ADA,0x1ADB,0x1ADC,0x1ADD,0x1ADE,0x1ADF, + 0x1AE0,0x1AE1,0x1AE2,0x1AE3,0x1AE4,0x1AE5,0x1AE6,0x1AE7,0x1AE8,0x1AE9,0x1AEA,0x1AEB,0x1AEC,0x1AED,0x1AEE,0x1AEF, + 0x1AF0,0x1AF1,0x1AF2,0x1AF3,0x1AF4,0x1AF5,0x1AF6,0x1AF7,0x1AF8,0x1AF9,0x1AFA,0x1AFB,0x1AFC,0x1AFD,0x1AFE,0x1AFF, + 0x1B00,0x1B01,0x1B02,0x1B03,0x1B04,0x1B05,0x1B06,0x1B07,0x1B08,0x1B09,0x1B0A,0x1B0B,0x1B0C,0x1B0D,0x1B0E,0x1B0F, + 0x1B10,0x1B11,0x1B12,0x1B13,0x1B14,0x1B15,0x1B16,0x1B17,0x1B18,0x1B19,0x1B1A,0x1B1B,0x1B1C,0x1B1D,0x1B1E,0x1B1F, + 0x1B20,0x1B21,0x1B22,0x1B23,0x1B24,0x1B25,0x1B26,0x1B27,0x1B28,0x1B29,0x1B2A,0x1B2B,0x1B2C,0x1B2D,0x1B2E,0x1B2F, + 0x1B30,0x1B31,0x1B32,0x1B33,0x1B34,0x1B35,0x1B36,0x1B37,0x1B38,0x1B39,0x1B3A,0x1B3B,0x1B3C,0x1B3D,0x1B3E,0x1B3F, + 0x1B40,0x1B41,0x1B42,0x1B43,0x1B44,0x1B45,0x1B46,0x1B47,0x1B48,0x1B49,0x1B4A,0x1B4B,0x1B4C,0x1B4D,0x1B4E,0x1B4F, + 0x1B50,0x1B51,0x1B52,0x1B53,0x1B54,0x1B55,0x1B56,0x1B57,0x1B58,0x1B59,0x1B5A,0x1B5B,0x1B5C,0x1B5D,0x1B5E,0x1B5F, + 0x1B60,0x1B61,0x1B62,0x1B63,0x1B64,0x1B65,0x1B66,0x1B67,0x1B68,0x1B69,0x1B6A,0x1B6B,0x1B6C,0x1B6D,0x1B6E,0x1B6F, + 0x1B70,0x1B71,0x1B72,0x1B73,0x1B74,0x1B75,0x1B76,0x1B77,0x1B78,0x1B79,0x1B7A,0x1B7B,0x1B7C,0x1B7D,0x1B7E,0x1B7F, + 0x1B80,0x1B81,0x1B82,0x1B83,0x1B84,0x1B85,0x1B86,0x1B87,0x1B88,0x1B89,0x1B8A,0x1B8B,0x1B8C,0x1B8D,0x1B8E,0x1B8F, + 0x1B90,0x1B91,0x1B92,0x1B93,0x1B94,0x1B95,0x1B96,0x1B97,0x1B98,0x1B99,0x1B9A,0x1B9B,0x1B9C,0x1B9D,0x1B9E,0x1B9F, + 0x1BA0,0x1BA1,0x1BA2,0x1BA3,0x1BA4,0x1BA5,0x1BA6,0x1BA7,0x1BA8,0x1BA9,0x1BAA,0x1BAB,0x1BAC,0x1BAD,0x1BAE,0x1BAF, + 0x1BB0,0x1BB1,0x1BB2,0x1BB3,0x1BB4,0x1BB5,0x1BB6,0x1BB7,0x1BB8,0x1BB9,0x1BBA,0x1BBB,0x1BBC,0x1BBD,0x1BBE,0x1BBF, + 0x1BC0,0x1BC1,0x1BC2,0x1BC3,0x1BC4,0x1BC5,0x1BC6,0x1BC7,0x1BC8,0x1BC9,0x1BCA,0x1BCB,0x1BCC,0x1BCD,0x1BCE,0x1BCF, + 0x1BD0,0x1BD1,0x1BD2,0x1BD3,0x1BD4,0x1BD5,0x1BD6,0x1BD7,0x1BD8,0x1BD9,0x1BDA,0x1BDB,0x1BDC,0x1BDD,0x1BDE,0x1BDF, + 0x1BE0,0x1BE1,0x1BE2,0x1BE3,0x1BE4,0x1BE5,0x1BE6,0x1BE7,0x1BE8,0x1BE9,0x1BEA,0x1BEB,0x1BEC,0x1BED,0x1BEE,0x1BEF, + 0x1BF0,0x1BF1,0x1BF2,0x1BF3,0x1BF4,0x1BF5,0x1BF6,0x1BF7,0x1BF8,0x1BF9,0x1BFA,0x1BFB,0x1BFC,0x1BFD,0x1BFE,0x1BFF, + 0x1C00,0x1C01,0x1C02,0x1C03,0x1C04,0x1C05,0x1C06,0x1C07,0x1C08,0x1C09,0x1C0A,0x1C0B,0x1C0C,0x1C0D,0x1C0E,0x1C0F, + 0x1C10,0x1C11,0x1C12,0x1C13,0x1C14,0x1C15,0x1C16,0x1C17,0x1C18,0x1C19,0x1C1A,0x1C1B,0x1C1C,0x1C1D,0x1C1E,0x1C1F, + 0x1C20,0x1C21,0x1C22,0x1C23,0x1C24,0x1C25,0x1C26,0x1C27,0x1C28,0x1C29,0x1C2A,0x1C2B,0x1C2C,0x1C2D,0x1C2E,0x1C2F, + 0x1C30,0x1C31,0x1C32,0x1C33,0x1C34,0x1C35,0x1C36,0x1C37,0x1C38,0x1C39,0x1C3A,0x1C3B,0x1C3C,0x1C3D,0x1C3E,0x1C3F, + 0x1C40,0x1C41,0x1C42,0x1C43,0x1C44,0x1C45,0x1C46,0x1C47,0x1C48,0x1C49,0x1C4A,0x1C4B,0x1C4C,0x1C4D,0x1C4E,0x1C4F, + 0x1C50,0x1C51,0x1C52,0x1C53,0x1C54,0x1C55,0x1C56,0x1C57,0x1C58,0x1C59,0x1C5A,0x1C5B,0x1C5C,0x1C5D,0x1C5E,0x1C5F, + 0x1C60,0x1C61,0x1C62,0x1C63,0x1C64,0x1C65,0x1C66,0x1C67,0x1C68,0x1C69,0x1C6A,0x1C6B,0x1C6C,0x1C6D,0x1C6E,0x1C6F, + 0x1C70,0x1C71,0x1C72,0x1C73,0x1C74,0x1C75,0x1C76,0x1C77,0x1C78,0x1C79,0x1C7A,0x1C7B,0x1C7C,0x1C7D,0x1C7E,0x1C7F, + 0x1C80,0x1C81,0x1C82,0x1C83,0x1C84,0x1C85,0x1C86,0x1C87,0x1C88,0x1C89,0x1C8A,0x1C8B,0x1C8C,0x1C8D,0x1C8E,0x1C8F, + 0x1C90,0x1C91,0x1C92,0x1C93,0x1C94,0x1C95,0x1C96,0x1C97,0x1C98,0x1C99,0x1C9A,0x1C9B,0x1C9C,0x1C9D,0x1C9E,0x1C9F, + 0x1CA0,0x1CA1,0x1CA2,0x1CA3,0x1CA4,0x1CA5,0x1CA6,0x1CA7,0x1CA8,0x1CA9,0x1CAA,0x1CAB,0x1CAC,0x1CAD,0x1CAE,0x1CAF, + 0x1CB0,0x1CB1,0x1CB2,0x1CB3,0x1CB4,0x1CB5,0x1CB6,0x1CB7,0x1CB8,0x1CB9,0x1CBA,0x1CBB,0x1CBC,0x1CBD,0x1CBE,0x1CBF, + 0x1CC0,0x1CC1,0x1CC2,0x1CC3,0x1CC4,0x1CC5,0x1CC6,0x1CC7,0x1CC8,0x1CC9,0x1CCA,0x1CCB,0x1CCC,0x1CCD,0x1CCE,0x1CCF, + 0x1CD0,0x1CD1,0x1CD2,0x1CD3,0x1CD4,0x1CD5,0x1CD6,0x1CD7,0x1CD8,0x1CD9,0x1CDA,0x1CDB,0x1CDC,0x1CDD,0x1CDE,0x1CDF, + 0x1CE0,0x1CE1,0x1CE2,0x1CE3,0x1CE4,0x1CE5,0x1CE6,0x1CE7,0x1CE8,0x1CE9,0x1CEA,0x1CEB,0x1CEC,0x1CED,0x1CEE,0x1CEF, + 0x1CF0,0x1CF1,0x1CF2,0x1CF3,0x1CF4,0x1CF5,0x1CF6,0x1CF7,0x1CF8,0x1CF9,0x1CFA,0x1CFB,0x1CFC,0x1CFD,0x1CFE,0x1CFF, + 0x1D00,0x1D01,0x1D02,0x1D03,0x1D04,0x1D05,0x1D06,0x1D07,0x1D08,0x1D09,0x1D0A,0x1D0B,0x1D0C,0x1D0D,0x1D0E,0x1D0F, + 0x1D10,0x1D11,0x1D12,0x1D13,0x1D14,0x1D15,0x1D16,0x1D17,0x1D18,0x1D19,0x1D1A,0x1D1B,0x1D1C,0x1D1D,0x1D1E,0x1D1F, + 0x1D20,0x1D21,0x1D22,0x1D23,0x1D24,0x1D25,0x1D26,0x1D27,0x1D28,0x1D29,0x1D2A,0x1D2B,0x1D2C,0x1D2D,0x1D2E,0x1D2F, + 0x1D30,0x1D31,0x1D32,0x1D33,0x1D34,0x1D35,0x1D36,0x1D37,0x1D38,0x1D39,0x1D3A,0x1D3B,0x1D3C,0x1D3D,0x1D3E,0x1D3F, + 0x1D40,0x1D41,0x1D42,0x1D43,0x1D44,0x1D45,0x1D46,0x1D47,0x1D48,0x1D49,0x1D4A,0x1D4B,0x1D4C,0x1D4D,0x1D4E,0x1D4F, + 0x1D50,0x1D51,0x1D52,0x1D53,0x1D54,0x1D55,0x1D56,0x1D57,0x1D58,0x1D59,0x1D5A,0x1D5B,0x1D5C,0x1D5D,0x1D5E,0x1D5F, + 0x1D60,0x1D61,0x1D62,0x1D63,0x1D64,0x1D65,0x1D66,0x1D67,0x1D68,0x1D69,0x1D6A,0x1D6B,0x1D6C,0x1D6D,0x1D6E,0x1D6F, + 0x1D70,0x1D71,0x1D72,0x1D73,0x1D74,0x1D75,0x1D76,0x1D77,0x1D78,0x1D79,0x1D7A,0x1D7B,0x1D7C,0x1D7D,0x1D7E,0x1D7F, + 0x1D80,0x1D81,0x1D82,0x1D83,0x1D84,0x1D85,0x1D86,0x1D87,0x1D88,0x1D89,0x1D8A,0x1D8B,0x1D8C,0x1D8D,0x1D8E,0x1D8F, + 0x1D90,0x1D91,0x1D92,0x1D93,0x1D94,0x1D95,0x1D96,0x1D97,0x1D98,0x1D99,0x1D9A,0x1D9B,0x1D9C,0x1D9D,0x1D9E,0x1D9F, + 0x1DA0,0x1DA1,0x1DA2,0x1DA3,0x1DA4,0x1DA5,0x1DA6,0x1DA7,0x1DA8,0x1DA9,0x1DAA,0x1DAB,0x1DAC,0x1DAD,0x1DAE,0x1DAF, + 0x1DB0,0x1DB1,0x1DB2,0x1DB3,0x1DB4,0x1DB5,0x1DB6,0x1DB7,0x1DB8,0x1DB9,0x1DBA,0x1DBB,0x1DBC,0x1DBD,0x1DBE,0x1DBF, + 0x1DC0,0x1DC1,0x1DC2,0x1DC3,0x1DC4,0x1DC5,0x1DC6,0x1DC7,0x1DC8,0x1DC9,0x1DCA,0x1DCB,0x1DCC,0x1DCD,0x1DCE,0x1DCF, + 0x1DD0,0x1DD1,0x1DD2,0x1DD3,0x1DD4,0x1DD5,0x1DD6,0x1DD7,0x1DD8,0x1DD9,0x1DDA,0x1DDB,0x1DDC,0x1DDD,0x1DDE,0x1DDF, + 0x1DE0,0x1DE1,0x1DE2,0x1DE3,0x1DE4,0x1DE5,0x1DE6,0x1DE7,0x1DE8,0x1DE9,0x1DEA,0x1DEB,0x1DEC,0x1DED,0x1DEE,0x1DEF, + 0x1DF0,0x1DF1,0x1DF2,0x1DF3,0x1DF4,0x1DF5,0x1DF6,0x1DF7,0x1DF8,0x1DF9,0x1DFA,0x1DFB,0x1DFC,0x1DFD,0x1DFE,0x1DFF, + 0x1E00,0x1E01,0x1E02,0x1E03,0x1E04,0x1E05,0x1E06,0x1E07,0x1E08,0x1E09,0x1E0A,0x1E0B,0x1E0C,0x1E0D,0x1E0E,0x1E0F, + 0x1E10,0x1E11,0x1E12,0x1E13,0x1E14,0x1E15,0x1E16,0x1E17,0x1E18,0x1E19,0x1E1A,0x1E1B,0x1E1C,0x1E1D,0x1E1E,0x1E1F, + 0x1E20,0x1E21,0x1E22,0x1E23,0x1E24,0x1E25,0x1E26,0x1E27,0x1E28,0x1E29,0x1E2A,0x1E2B,0x1E2C,0x1E2D,0x1E2E,0x1E2F, + 0x1E30,0x1E31,0x1E32,0x1E33,0x1E34,0x1E35,0x1E36,0x1E37,0x1E38,0x1E39,0x1E3A,0x1E3B,0x1E3C,0x1E3D,0x1E3E,0x1E3F, + 0x1E40,0x1E41,0x1E42,0x1E43,0x1E44,0x1E45,0x1E46,0x1E47,0x1E48,0x1E49,0x1E4A,0x1E4B,0x1E4C,0x1E4D,0x1E4E,0x1E4F, + 0x1E50,0x1E51,0x1E52,0x1E53,0x1E54,0x1E55,0x1E56,0x1E57,0x1E58,0x1E59,0x1E5A,0x1E5B,0x1E5C,0x1E5D,0x1E5E,0x1E5F, + 0x1E60,0x1E61,0x1E62,0x1E63,0x1E64,0x1E65,0x1E66,0x1E67,0x1E68,0x1E69,0x1E6A,0x1E6B,0x1E6C,0x1E6D,0x1E6E,0x1E6F, + 0x1E70,0x1E71,0x1E72,0x1E73,0x1E74,0x1E75,0x1E76,0x1E77,0x1E78,0x1E79,0x1E7A,0x1E7B,0x1E7C,0x1E7D,0x1E7E,0x1E7F, + 0x1E80,0x1E81,0x1E82,0x1E83,0x1E84,0x1E85,0x1E86,0x1E87,0x1E88,0x1E89,0x1E8A,0x1E8B,0x1E8C,0x1E8D,0x1E8E,0x1E8F, + 0x1E90,0x1E91,0x1E92,0x1E93,0x1E94,0x1E95,0x1E96,0x1E97,0x1E98,0x1E99,0x1E9A,0x1E9B,0x1E9C,0x1E9D,0x1E9E,0x1E9F, + 0x1EA0,0x1EA1,0x1EA2,0x1EA3,0x1EA4,0x1EA5,0x1EA6,0x1EA7,0x1EA8,0x1EA9,0x1EAA,0x1EAB,0x1EAC,0x1EAD,0x1EAE,0x1EAF, + 0x1EB0,0x1EB1,0x1EB2,0x1EB3,0x1EB4,0x1EB5,0x1EB6,0x1EB7,0x1EB8,0x1EB9,0x1EBA,0x1EBB,0x1EBC,0x1EBD,0x1EBE,0x1EBF, + 0x1EC0,0x1EC1,0x1EC2,0x1EC3,0x1EC4,0x1EC5,0x1EC6,0x1EC7,0x1EC8,0x1EC9,0x1ECA,0x1ECB,0x1ECC,0x1ECD,0x1ECE,0x1ECF, + 0x1ED0,0x1ED1,0x1ED2,0x1ED3,0x1ED4,0x1ED5,0x1ED6,0x1ED7,0x1ED8,0x1ED9,0x1EDA,0x1EDB,0x1EDC,0x1EDD,0x1EDE,0x1EDF, + 0x1EE0,0x1EE1,0x1EE2,0x1EE3,0x1EE4,0x1EE5,0x1EE6,0x1EE7,0x1EE8,0x1EE9,0x1EEA,0x1EEB,0x1EEC,0x1EED,0x1EEE,0x1EEF, + 0x1EF0,0x1EF1,0x1EF2,0x1EF3,0x1EF4,0x1EF5,0x1EF6,0x1EF7,0x1EF8,0x1EF9,0x1EFA,0x1EFB,0x1EFC,0x1EFD,0x1EFE,0x1EFF, + 0x1F00,0x1F01,0x1F02,0x1F03,0x1F04,0x1F05,0x1F06,0x1F07,0x1F08,0x1F09,0x1F0A,0x1F0B,0x1F0C,0x1F0D,0x1F0E,0x1F0F, + 0x1F10,0x1F11,0x1F12,0x1F13,0x1F14,0x1F15,0x1F16,0x1F17,0x1F18,0x1F19,0x1F1A,0x1F1B,0x1F1C,0x1F1D,0x1F1E,0x1F1F, + 0x1F20,0x1F21,0x1F22,0x1F23,0x1F24,0x1F25,0x1F26,0x1F27,0x1F28,0x1F29,0x1F2A,0x1F2B,0x1F2C,0x1F2D,0x1F2E,0x1F2F, + 0x1F30,0x1F31,0x1F32,0x1F33,0x1F34,0x1F35,0x1F36,0x1F37,0x1F38,0x1F39,0x1F3A,0x1F3B,0x1F3C,0x1F3D,0x1F3E,0x1F3F, + 0x1F40,0x1F41,0x1F42,0x1F43,0x1F44,0x1F45,0x1F46,0x1F47,0x1F48,0x1F49,0x1F4A,0x1F4B,0x1F4C,0x1F4D,0x1F4E,0x1F4F, + 0x1F50,0x1F51,0x1F52,0x1F53,0x1F54,0x1F55,0x1F56,0x1F57,0x1F58,0x1F59,0x1F5A,0x1F5B,0x1F5C,0x1F5D,0x1F5E,0x1F5F, + 0x1F60,0x1F61,0x1F62,0x1F63,0x1F64,0x1F65,0x1F66,0x1F67,0x1F68,0x1F69,0x1F6A,0x1F6B,0x1F6C,0x1F6D,0x1F6E,0x1F6F, + 0x1F70,0x1F71,0x1F72,0x1F73,0x1F74,0x1F75,0x1F76,0x1F77,0x1F78,0x1F79,0x1F7A,0x1F7B,0x1F7C,0x1F7D,0x1F7E,0x1F7F, + 0x1F80,0x1F81,0x1F82,0x1F83,0x1F84,0x1F85,0x1F86,0x1F87,0x1F88,0x1F89,0x1F8A,0x1F8B,0x1F8C,0x1F8D,0x1F8E,0x1F8F, + 0x1F90,0x1F91,0x1F92,0x1F93,0x1F94,0x1F95,0x1F96,0x1F97,0x1F98,0x1F99,0x1F9A,0x1F9B,0x1F9C,0x1F9D,0x1F9E,0x1F9F, + 0x1FA0,0x1FA1,0x1FA2,0x1FA3,0x1FA4,0x1FA5,0x1FA6,0x1FA7,0x1FA8,0x1FA9,0x1FAA,0x1FAB,0x1FAC,0x1FAD,0x1FAE,0x1FAF, + 0x1FB0,0x1FB1,0x1FB2,0x1FB3,0x1FB4,0x1FB5,0x1FB6,0x1FB7,0x1FB8,0x1FB9,0x1FBA,0x1FBB,0x1FBC,0x1FBD,0x1FBE,0x1FBF, + 0x1FC0,0x1FC1,0x1FC2,0x1FC3,0x1FC4,0x1FC5,0x1FC6,0x1FC7,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FCC,0x1FCD,0x1FCE,0x1FCF, + 0x1FD0,0x1FD1,0x1FD2,0x1FD3,0x1FD4,0x1FD5,0x1FD6,0x1FD7,0x1FD8,0x1FD9,0x1FDA,0x1FDB,0x1FDC,0x1FDD,0x1FDE,0x1FDF, + 0x1FE0,0x1FE1,0x1FE2,0x1FE3,0x1FE4,0x1FE5,0x1FE6,0x1FE7,0x1FE8,0x1FE9,0x1FEA,0x1FEB,0x1FEC,0x1FED,0x1FEE,0x1FEF, + 0x1FF0,0x1FF1,0x1FF2,0x1FF3,0x1FF4,0x1FF5,0x1FF6,0x1FF7,0x1FF8,0x1FF9,0x1FFA,0x1FFB,0x1FFC,0x1FFD,0x1FFE,0x1FFF, + 0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,0x2008,0x2009,0x200A,0x200B,0x200C,0x200D,0x200E,0x200F, + 0x2010,0x2011,0x2012,0x2013,0x2014,0x2015,0x2016,0x2017,0x2018,0x2019,0x201A,0x201B,0x201C,0x201D,0x201E,0x201F, + 0x2020,0x2021,0x2022,0x2023,0x2024,0x2025,0x2026,0x2027,0x2028,0x2029,0x202A,0x202B,0x202C,0x202D,0x202E,0x202F, + 0x2030,0x2031,0x2032,0x2033,0x2034,0x2035,0x2036,0x2037,0x2038,0x2039,0x203A,0x203B,0x203C,0x203D,0x203E,0x203F, + 0x2040,0x2041,0x2042,0x2043,0x2044,0x2045,0x2046,0x2047,0x2048,0x2049,0x204A,0x204B,0x204C,0x204D,0x204E,0x204F, + 0x2050,0x2051,0x2052,0x2053,0x2054,0x2055,0x2056,0x2057,0x2058,0x2059,0x205A,0x205B,0x205C,0x205D,0x205E,0x205F, + 0x2060,0x2061,0x2062,0x2063,0x2064,0x2065,0x2066,0x2067,0x2068,0x2069,0x206A,0x206B,0x206C,0x206D,0x206E,0x206F, + 0x2070,0x2071,0x2072,0x2073,0x2074,0x2075,0x2076,0x2077,0x2078,0x2079,0x207A,0x207B,0x207C,0x207D,0x207E,0x207F, + 0x2080,0x2081,0x2082,0x2083,0x2084,0x2085,0x2086,0x2087,0x2088,0x2089,0x208A,0x208B,0x208C,0x208D,0x208E,0x208F, + 0x2090,0x2091,0x2092,0x2093,0x2094,0x2095,0x2096,0x2097,0x2098,0x2099,0x209A,0x209B,0x209C,0x209D,0x209E,0x209F, + 0x20A0,0x20A1,0x20A2,0x20A3,0x20A4,0x20A5,0x20A6,0x20A7,0x20A8,0x20A9,0x20AA,0x20AB,0x20AC,0x20AD,0x20AE,0x20AF, + 0x20B0,0x20B1,0x20B2,0x20B3,0x20B4,0x20B5,0x20B6,0x20B7,0x20B8,0x20B9,0x20BA,0x20BB,0x20BC,0x20BD,0x20BE,0x20BF, + 0x20C0,0x20C1,0x20C2,0x20C3,0x20C4,0x20C5,0x20C6,0x20C7,0x20C8,0x20C9,0x20CA,0x20CB,0x20CC,0x20CD,0x20CE,0x20CF, + 0x20D0,0x20D1,0x20D2,0x20D3,0x20D4,0x20D5,0x20D6,0x20D7,0x20D8,0x20D9,0x20DA,0x20DB,0x20DC,0x20DD,0x20DE,0x20DF, + 0x20E0,0x20E1,0x20E2,0x20E3,0x20E4,0x20E5,0x20E6,0x20E7,0x20E8,0x20E9,0x20EA,0x20EB,0x20EC,0x20ED,0x20EE,0x20EF, + 0x20F0,0x20F1,0x20F2,0x20F3,0x20F4,0x20F5,0x20F6,0x20F7,0x20F8,0x20F9,0x20FA,0x20FB,0x20FC,0x20FD,0x20FE,0x20FF, + 0x2100,0x2101,0x2102,0x2103,0x2104,0x2105,0x2106,0x2107,0x2108,0x2109,0x210A,0x210B,0x210C,0x210D,0x210E,0x210F, + 0x2110,0x2111,0x2112,0x2113,0x2114,0x2115,0x2116,0x2117,0x2118,0x2119,0x211A,0x211B,0x211C,0x211D,0x211E,0x211F, + 0x2120,0x2121,0x2122,0x2123,0x2124,0x2125,0x2126,0x2127,0x2128,0x2129,0x212A,0x212B,0x212C,0x212D,0x212E,0x212F, + 0x2130,0x2131,0x2132,0x2133,0x2134,0x2135,0x2136,0x2137,0x2138,0x2139,0x213A,0x213B,0x213C,0x213D,0x213E,0x213F, + 0x2140,0x2141,0x2142,0x2143,0x2144,0x2145,0x2146,0x2147,0x2148,0x2149,0x214A,0x214B,0x214C,0x214D,0x214E,0x214F, + 0x2150,0x2151,0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,0x215A,0x215B,0x215C,0x215D,0x215E,0x215F, + 0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,0x216A,0x216B,0x216C,0x216D,0x216E,0x216F, + 0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0x217A,0x217B,0x217C,0x217D,0x217E,0x217F, + 0x2180,0x2181,0x2182,0x2183,0x2184,0x2185,0x2186,0x2187,0x2188,0x2189,0x218A,0x218B,0x218C,0x218D,0x218E,0x218F, + 0x2190,0x2191,0x2192,0x2193,0x2194,0x2195,0x2196,0x2197,0x2198,0x2199,0x219A,0x219B,0x219C,0x219D,0x219E,0x219F, + 0x21A0,0x21A1,0x21A2,0x21A3,0x21A4,0x21A5,0x21A6,0x21A7,0x21A8,0x21A9,0x21AA,0x21AB,0x21AC,0x21AD,0x21AE,0x21AF, + 0x21B0,0x21B1,0x21B2,0x21B3,0x21B4,0x21B5,0x21B6,0x21B7,0x21B8,0x21B9,0x21BA,0x21BB,0x21BC,0x21BD,0x21BE,0x21BF, + 0x21C0,0x21C1,0x21C2,0x21C3,0x21C4,0x21C5,0x21C6,0x21C7,0x21C8,0x21C9,0x21CA,0x21CB,0x21CC,0x21CD,0x21CE,0x21CF, + 0x21D0,0x21D1,0x21D2,0x21D3,0x21D4,0x21D5,0x21D6,0x21D7,0x21D8,0x21D9,0x21DA,0x21DB,0x21DC,0x21DD,0x21DE,0x21DF, + 0x21E0,0x21E1,0x21E2,0x21E3,0x21E4,0x21E5,0x21E6,0x21E7,0x21E8,0x21E9,0x21EA,0x21EB,0x21EC,0x21ED,0x21EE,0x21EF, + 0x21F0,0x21F1,0x21F2,0x21F3,0x21F4,0x21F5,0x21F6,0x21F7,0x21F8,0x21F9,0x21FA,0x21FB,0x21FC,0x21FD,0x21FE,0x21FF, + 0x2200,0x2201,0x2202,0x2203,0x2204,0x2205,0x2206,0x2207,0x2208,0x2209,0x220A,0x220B,0x220C,0x220D,0x220E,0x220F, + 0x2210,0x2211,0x2212,0x2213,0x2214,0x2215,0x2216,0x2217,0x2218,0x2219,0x221A,0x221B,0x221C,0x221D,0x221E,0x221F, + 0x2220,0x2221,0x2222,0x2223,0x2224,0x2225,0x2226,0x2227,0x2228,0x2229,0x222A,0x222B,0x222C,0x222D,0x222E,0x222F, + 0x2230,0x2231,0x2232,0x2233,0x2234,0x2235,0x2236,0x2237,0x2238,0x2239,0x223A,0x223B,0x223C,0x223D,0x223E,0x223F, + 0x2240,0x2241,0x2242,0x2243,0x2244,0x2245,0x2246,0x2247,0x2248,0x2249,0x224A,0x224B,0x224C,0x224D,0x224E,0x224F, + 0x2250,0x2251,0x2252,0x2253,0x2254,0x2255,0x2256,0x2257,0x2258,0x2259,0x225A,0x225B,0x225C,0x225D,0x225E,0x225F, + 0x2260,0x2261,0x2262,0x2263,0x2264,0x2265,0x2266,0x2267,0x2268,0x2269,0x226A,0x226B,0x226C,0x226D,0x226E,0x226F, + 0x2270,0x2271,0x2272,0x2273,0x2274,0x2275,0x2276,0x2277,0x2278,0x2279,0x227A,0x227B,0x227C,0x227D,0x227E,0x227F, + 0x2280,0x2281,0x2282,0x2283,0x2284,0x2285,0x2286,0x2287,0x2288,0x2289,0x228A,0x228B,0x228C,0x228D,0x228E,0x228F, + 0x2290,0x2291,0x2292,0x2293,0x2294,0x2295,0x2296,0x2297,0x2298,0x2299,0x229A,0x229B,0x229C,0x229D,0x229E,0x229F, + 0x22A0,0x22A1,0x22A2,0x22A3,0x22A4,0x22A5,0x22A6,0x22A7,0x22A8,0x22A9,0x22AA,0x22AB,0x22AC,0x22AD,0x22AE,0x22AF, + 0x22B0,0x22B1,0x22B2,0x22B3,0x22B4,0x22B5,0x22B6,0x22B7,0x22B8,0x22B9,0x22BA,0x22BB,0x22BC,0x22BD,0x22BE,0x22BF, + 0x22C0,0x22C1,0x22C2,0x22C3,0x22C4,0x22C5,0x22C6,0x22C7,0x22C8,0x22C9,0x22CA,0x22CB,0x22CC,0x22CD,0x22CE,0x22CF, + 0x22D0,0x22D1,0x22D2,0x22D3,0x22D4,0x22D5,0x22D6,0x22D7,0x22D8,0x22D9,0x22DA,0x22DB,0x22DC,0x22DD,0x22DE,0x22DF, + 0x22E0,0x22E1,0x22E2,0x22E3,0x22E4,0x22E5,0x22E6,0x22E7,0x22E8,0x22E9,0x22EA,0x22EB,0x22EC,0x22ED,0x22EE,0x22EF, + 0x22F0,0x22F1,0x22F2,0x22F3,0x22F4,0x22F5,0x22F6,0x22F7,0x22F8,0x22F9,0x22FA,0x22FB,0x22FC,0x22FD,0x22FE,0x22FF, + 0x2300,0x2301,0x2302,0x2303,0x2304,0x2305,0x2306,0x2307,0x2308,0x2309,0x230A,0x230B,0x230C,0x230D,0x230E,0x230F, + 0x2310,0x2311,0x2312,0x2313,0x2314,0x2315,0x2316,0x2317,0x2318,0x2319,0x231A,0x231B,0x231C,0x231D,0x231E,0x231F, + 0x2320,0x2321,0x2322,0x2323,0x2324,0x2325,0x2326,0x2327,0x2328,0x2329,0x232A,0x232B,0x232C,0x232D,0x232E,0x232F, + 0x2330,0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,0x2339,0x233A,0x233B,0x233C,0x233D,0x233E,0x233F, + 0x2340,0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,0x2348,0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F, + 0x2350,0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,0x2358,0x2359,0x235A,0x235B,0x235C,0x235D,0x235E,0x235F, + 0x2360,0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,0x2368,0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F, + 0x2370,0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,0x2378,0x2379,0x237A,0x237B,0x237C,0x237D,0x237E,0x237F, + 0x2380,0x2381,0x2382,0x2383,0x2384,0x2385,0x2386,0x2387,0x2388,0x2389,0x238A,0x238B,0x238C,0x238D,0x238E,0x238F, + 0x2390,0x2391,0x2392,0x2393,0x2394,0x2395,0x2396,0x2397,0x2398,0x2399,0x239A,0x239B,0x239C,0x239D,0x239E,0x239F, + 0x23A0,0x23A1,0x23A2,0x23A3,0x23A4,0x23A5,0x23A6,0x23A7,0x23A8,0x23A9,0x23AA,0x23AB,0x23AC,0x23AD,0x23AE,0x23AF, + 0x23B0,0x23B1,0x23B2,0x23B3,0x23B4,0x23B5,0x23B6,0x23B7,0x23B8,0x23B9,0x23BA,0x23BB,0x23BC,0x23BD,0x23BE,0x23BF, + 0x23C0,0x23C1,0x23C2,0x23C3,0x23C4,0x23C5,0x23C6,0x23C7,0x23C8,0x23C9,0x23CA,0x23CB,0x23CC,0x23CD,0x23CE,0x23CF, + 0x23D0,0x23D1,0x23D2,0x23D3,0x23D4,0x23D5,0x23D6,0x23D7,0x23D8,0x23D9,0x23DA,0x23DB,0x23DC,0x23DD,0x23DE,0x23DF, + 0x23E0,0x23E1,0x23E2,0x23E3,0x23E4,0x23E5,0x23E6,0x23E7,0x23E8,0x23E9,0x23EA,0x23EB,0x23EC,0x23ED,0x23EE,0x23EF, + 0x23F0,0x23F1,0x23F2,0x23F3,0x23F4,0x23F5,0x23F6,0x23F7,0x23F8,0x23F9,0x23FA,0x23FB,0x23FC,0x23FD,0x23FE,0x23FF, + 0x2400,0x2401,0x2402,0x2403,0x2404,0x2405,0x2406,0x2407,0x2408,0x2409,0x240A,0x240B,0x240C,0x240D,0x240E,0x240F, + 0x2410,0x2411,0x2412,0x2413,0x2414,0x2415,0x2416,0x2417,0x2418,0x2419,0x241A,0x241B,0x241C,0x241D,0x241E,0x241F, + 0x2420,0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,0x2428,0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F, + 0x2430,0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,0x2438,0x2439,0x243A,0x243B,0x243C,0x243D,0x243E,0x243F, + 0x2440,0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447,0x2448,0x2449,0x244A,0x244B,0x244C,0x244D,0x244E,0x244F, + 0x2450,0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457,0x2458,0x2459,0x245A,0x245B,0x245C,0x245D,0x245E,0x245F, + 0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F, + 0x2470,0x2471,0x2472,0x2473,0x2474,0x2475,0x2476,0x2477,0x2478,0x2479,0x247A,0x247B,0x247C,0x247D,0x247E,0x247F, + 0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,0x2487,0x2488,0x2489,0x248A,0x248B,0x248C,0x248D,0x248E,0x248F, + 0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,0x2497,0x2498,0x2499,0x249A,0x249B,0x249C,0x249D,0x249E,0x249F, + 0x24A0,0x24A1,0x24A2,0x24A3,0x24A4,0x24A5,0x24A6,0x24A7,0x24A8,0x24A9,0x24AA,0x24AB,0x24AC,0x24AD,0x24AE,0x24AF, + 0x24B0,0x24B1,0x24B2,0x24B3,0x24B4,0x24B5,0x24B6,0x24B7,0x24B8,0x24B9,0x24BA,0x24BB,0x24BC,0x24BD,0x24BE,0x24BF, + 0x24C0,0x24C1,0x24C2,0x24C3,0x24C4,0x24C5,0x24C6,0x24C7,0x24C8,0x24C9,0x24CA,0x24CB,0x24CC,0x24CD,0x24CE,0x24CF, + 0x24D0,0x24D1,0x24D2,0x24D3,0x24D4,0x24D5,0x24D6,0x24D7,0x24D8,0x24D9,0x24DA,0x24DB,0x24DC,0x24DD,0x24DE,0x24DF, + 0x24E0,0x24E1,0x24E2,0x24E3,0x24E4,0x24E5,0x24E6,0x24E7,0x24E8,0x24E9,0x24EA,0x24EB,0x24EC,0x24ED,0x24EE,0x24EF, + 0x24F0,0x24F1,0x24F2,0x24F3,0x24F4,0x24F5,0x24F6,0x24F7,0x24F8,0x24F9,0x24FA,0x24FB,0x24FC,0x24FD,0x24FE,0x24FF, + 0x2500,0x2501,0x2502,0x2503,0x2504,0x2505,0x2506,0x2507,0x2508,0x2509,0x250A,0x250B,0x250C,0x250D,0x250E,0x250F, + 0x2510,0x2511,0x2512,0x2513,0x2514,0x2515,0x2516,0x2517,0x2518,0x2519,0x251A,0x251B,0x251C,0x251D,0x251E,0x251F, + 0x2520,0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527,0x2528,0x2529,0x252A,0x252B,0x252C,0x252D,0x252E,0x252F, + 0x2530,0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537,0x2538,0x2539,0x253A,0x253B,0x253C,0x253D,0x253E,0x253F, + 0x2540,0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B,0x254C,0x254D,0x254E,0x254F, + 0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,0x2558,0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,0x255F, + 0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,0x2568,0x2569,0x256A,0x256B,0x256C,0x256D,0x256E,0x256F, + 0x2570,0x2571,0x2572,0x2573,0x2574,0x2575,0x2576,0x2577,0x2578,0x2579,0x257A,0x257B,0x257C,0x257D,0x257E,0x257F, + 0x2580,0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,0x2587,0x2588,0x2589,0x258A,0x258B,0x258C,0x258D,0x258E,0x258F, + 0x2590,0x2591,0x2592,0x2593,0x2594,0x2595,0x2596,0x2597,0x2598,0x2599,0x259A,0x259B,0x259C,0x259D,0x259E,0x259F, + 0x25A0,0x25A1,0x25A2,0x25A3,0x25A4,0x25A5,0x25A6,0x25A7,0x25A8,0x25A9,0x25AA,0x25AB,0x25AC,0x25AD,0x25AE,0x25AF, + 0x25B0,0x25B1,0x25B2,0x25B3,0x25B4,0x25B5,0x25B6,0x25B7,0x25B8,0x25B9,0x25BA,0x25BB,0x25BC,0x25BD,0x25BE,0x25BF, + 0x25C0,0x25C1,0x25C2,0x25C3,0x25C4,0x25C5,0x25C6,0x25C7,0x25C8,0x25C9,0x25CA,0x25CB,0x25CC,0x25CD,0x25CE,0x25CF, + 0x25D0,0x25D1,0x25D2,0x25D3,0x25D4,0x25D5,0x25D6,0x25D7,0x25D8,0x25D9,0x25DA,0x25DB,0x25DC,0x25DD,0x25DE,0x25DF, + 0x25E0,0x25E1,0x25E2,0x25E3,0x25E4,0x25E5,0x25E6,0x25E7,0x25E8,0x25E9,0x25EA,0x25EB,0x25EC,0x25ED,0x25EE,0x25EF, + 0x25F0,0x25F1,0x25F2,0x25F3,0x25F4,0x25F5,0x25F6,0x25F7,0x25F8,0x25F9,0x25FA,0x25FB,0x25FC,0x25FD,0x25FE,0x25FF, + 0x2600,0x2601,0x2602,0x2603,0x2604,0x2605,0x2606,0x2607,0x2608,0x2609,0x260A,0x260B,0x260C,0x260D,0x260E,0x260F, + 0x2610,0x2611,0x2612,0x2613,0x2614,0x2615,0x2616,0x2617,0x2618,0x2619,0x261A,0x261B,0x261C,0x261D,0x261E,0x261F, + 0x2620,0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,0x2628,0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F, + 0x2630,0x2631,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637,0x2638,0x2639,0x263A,0x263B,0x263C,0x263D,0x263E,0x263F, + 0x2640,0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,0x2647,0x2648,0x2649,0x264A,0x264B,0x264C,0x264D,0x264E,0x264F, + 0x2650,0x2651,0x2652,0x2653,0x2654,0x2655,0x2656,0x2657,0x2658,0x2659,0x265A,0x265B,0x265C,0x265D,0x265E,0x265F, + 0x2660,0x2661,0x2662,0x2663,0x2664,0x2665,0x2666,0x2667,0x2668,0x2669,0x266A,0x266B,0x266C,0x266D,0x266E,0x266F, + 0x2670,0x2671,0x2672,0x2673,0x2674,0x2675,0x2676,0x2677,0x2678,0x2679,0x267A,0x267B,0x267C,0x267D,0x267E,0x267F, + 0x2680,0x2681,0x2682,0x2683,0x2684,0x2685,0x2686,0x2687,0x2688,0x2689,0x268A,0x268B,0x268C,0x268D,0x268E,0x268F, + 0x2690,0x2691,0x2692,0x2693,0x2694,0x2695,0x2696,0x2697,0x2698,0x2699,0x269A,0x269B,0x269C,0x269D,0x269E,0x269F, + 0x26A0,0x26A1,0x26A2,0x26A3,0x26A4,0x26A5,0x26A6,0x26A7,0x26A8,0x26A9,0x26AA,0x26AB,0x26AC,0x26AD,0x26AE,0x26AF, + 0x26B0,0x26B1,0x26B2,0x26B3,0x26B4,0x26B5,0x26B6,0x26B7,0x26B8,0x26B9,0x26BA,0x26BB,0x26BC,0x26BD,0x26BE,0x26BF, + 0x26C0,0x26C1,0x26C2,0x26C3,0x26C4,0x26C5,0x26C6,0x26C7,0x26C8,0x26C9,0x26CA,0x26CB,0x26CC,0x26CD,0x26CE,0x26CF, + 0x26D0,0x26D1,0x26D2,0x26D3,0x26D4,0x26D5,0x26D6,0x26D7,0x26D8,0x26D9,0x26DA,0x26DB,0x26DC,0x26DD,0x26DE,0x26DF, + 0x26E0,0x26E1,0x26E2,0x26E3,0x26E4,0x26E5,0x26E6,0x26E7,0x26E8,0x26E9,0x26EA,0x26EB,0x26EC,0x26ED,0x26EE,0x26EF, + 0x26F0,0x26F1,0x26F2,0x26F3,0x26F4,0x26F5,0x26F6,0x26F7,0x26F8,0x26F9,0x26FA,0x26FB,0x26FC,0x26FD,0x26FE,0x26FF, + 0x2700,0x2701,0x2702,0x2703,0x2704,0x2705,0x2706,0x2707,0x2708,0x2709,0x270A,0x270B,0x270C,0x270D,0x270E,0x270F, + 0x2710,0x2711,0x2712,0x2713,0x2714,0x2715,0x2716,0x2717,0x2718,0x2719,0x271A,0x271B,0x271C,0x271D,0x271E,0x271F, + 0x2720,0x2721,0x2722,0x2723,0x2724,0x2725,0x2726,0x2727,0x2728,0x2729,0x272A,0x272B,0x272C,0x272D,0x272E,0x272F, + 0x2730,0x2731,0x2732,0x2733,0x2734,0x2735,0x2736,0x2737,0x2738,0x2739,0x273A,0x273B,0x273C,0x273D,0x273E,0x273F, + 0x2740,0x2741,0x2742,0x2743,0x2744,0x2745,0x2746,0x2747,0x2748,0x2749,0x274A,0x274B,0x274C,0x274D,0x274E,0x274F, + 0x2750,0x2751,0x2752,0x2753,0x2754,0x2755,0x2756,0x2757,0x2758,0x2759,0x275A,0x275B,0x275C,0x275D,0x275E,0x275F, + 0x2760,0x2761,0x2762,0x2763,0x2764,0x2765,0x2766,0x2767,0x2768,0x2769,0x276A,0x276B,0x276C,0x276D,0x276E,0x276F, + 0x2770,0x2771,0x2772,0x2773,0x2774,0x2775,0x2776,0x2777,0x2778,0x2779,0x277A,0x277B,0x277C,0x277D,0x277E,0x277F, + 0x2780,0x2781,0x2782,0x2783,0x2784,0x2785,0x2786,0x2787,0x2788,0x2789,0x278A,0x278B,0x278C,0x278D,0x278E,0x278F, + 0x2790,0x2791,0x2792,0x2793,0x2794,0x2795,0x2796,0x2797,0x2798,0x2799,0x279A,0x279B,0x279C,0x279D,0x279E,0x279F, + 0x27A0,0x27A1,0x27A2,0x27A3,0x27A4,0x27A5,0x27A6,0x27A7,0x27A8,0x27A9,0x27AA,0x27AB,0x27AC,0x27AD,0x27AE,0x27AF, + 0x27B0,0x27B1,0x27B2,0x27B3,0x27B4,0x27B5,0x27B6,0x27B7,0x27B8,0x27B9,0x27BA,0x27BB,0x27BC,0x27BD,0x27BE,0x27BF, + 0x27C0,0x27C1,0x27C2,0x27C3,0x27C4,0x27C5,0x27C6,0x27C7,0x27C8,0x27C9,0x27CA,0x27CB,0x27CC,0x27CD,0x27CE,0x27CF, + 0x27D0,0x27D1,0x27D2,0x27D3,0x27D4,0x27D5,0x27D6,0x27D7,0x27D8,0x27D9,0x27DA,0x27DB,0x27DC,0x27DD,0x27DE,0x27DF, + 0x27E0,0x27E1,0x27E2,0x27E3,0x27E4,0x27E5,0x27E6,0x27E7,0x27E8,0x27E9,0x27EA,0x27EB,0x27EC,0x27ED,0x27EE,0x27EF, + 0x27F0,0x27F1,0x27F2,0x27F3,0x27F4,0x27F5,0x27F6,0x27F7,0x27F8,0x27F9,0x27FA,0x27FB,0x27FC,0x27FD,0x27FE,0x27FF, + 0x2800,0x2801,0x2802,0x2803,0x2804,0x2805,0x2806,0x2807,0x2808,0x2809,0x280A,0x280B,0x280C,0x280D,0x280E,0x280F, + 0x2810,0x2811,0x2812,0x2813,0x2814,0x2815,0x2816,0x2817,0x2818,0x2819,0x281A,0x281B,0x281C,0x281D,0x281E,0x281F, + 0x2820,0x2821,0x2822,0x2823,0x2824,0x2825,0x2826,0x2827,0x2828,0x2829,0x282A,0x282B,0x282C,0x282D,0x282E,0x282F, + 0x2830,0x2831,0x2832,0x2833,0x2834,0x2835,0x2836,0x2837,0x2838,0x2839,0x283A,0x283B,0x283C,0x283D,0x283E,0x283F, + 0x2840,0x2841,0x2842,0x2843,0x2844,0x2845,0x2846,0x2847,0x2848,0x2849,0x284A,0x284B,0x284C,0x284D,0x284E,0x284F, + 0x2850,0x2851,0x2852,0x2853,0x2854,0x2855,0x2856,0x2857,0x2858,0x2859,0x285A,0x285B,0x285C,0x285D,0x285E,0x285F, + 0x2860,0x2861,0x2862,0x2863,0x2864,0x2865,0x2866,0x2867,0x2868,0x2869,0x286A,0x286B,0x286C,0x286D,0x286E,0x286F, + 0x2870,0x2871,0x2872,0x2873,0x2874,0x2875,0x2876,0x2877,0x2878,0x2879,0x287A,0x287B,0x287C,0x287D,0x287E,0x287F, + 0x2880,0x2881,0x2882,0x2883,0x2884,0x2885,0x2886,0x2887,0x2888,0x2889,0x288A,0x288B,0x288C,0x288D,0x288E,0x288F, + 0x2890,0x2891,0x2892,0x2893,0x2894,0x2895,0x2896,0x2897,0x2898,0x2899,0x289A,0x289B,0x289C,0x289D,0x289E,0x289F, + 0x28A0,0x28A1,0x28A2,0x28A3,0x28A4,0x28A5,0x28A6,0x28A7,0x28A8,0x28A9,0x28AA,0x28AB,0x28AC,0x28AD,0x28AE,0x28AF, + 0x28B0,0x28B1,0x28B2,0x28B3,0x28B4,0x28B5,0x28B6,0x28B7,0x28B8,0x28B9,0x28BA,0x28BB,0x28BC,0x28BD,0x28BE,0x28BF, + 0x28C0,0x28C1,0x28C2,0x28C3,0x28C4,0x28C5,0x28C6,0x28C7,0x28C8,0x28C9,0x28CA,0x28CB,0x28CC,0x28CD,0x28CE,0x28CF, + 0x28D0,0x28D1,0x28D2,0x28D3,0x28D4,0x28D5,0x28D6,0x28D7,0x28D8,0x28D9,0x28DA,0x28DB,0x28DC,0x28DD,0x28DE,0x28DF, + 0x28E0,0x28E1,0x28E2,0x28E3,0x28E4,0x28E5,0x28E6,0x28E7,0x28E8,0x28E9,0x28EA,0x28EB,0x28EC,0x28ED,0x28EE,0x28EF, + 0x28F0,0x28F1,0x28F2,0x28F3,0x28F4,0x28F5,0x28F6,0x28F7,0x28F8,0x28F9,0x28FA,0x28FB,0x28FC,0x28FD,0x28FE,0x28FF, + 0x2900,0x2901,0x2902,0x2903,0x2904,0x2905,0x2906,0x2907,0x2908,0x2909,0x290A,0x290B,0x290C,0x290D,0x290E,0x290F, + 0x2910,0x2911,0x2912,0x2913,0x2914,0x2915,0x2916,0x2917,0x2918,0x2919,0x291A,0x291B,0x291C,0x291D,0x291E,0x291F, + 0x2920,0x2921,0x2922,0x2923,0x2924,0x2925,0x2926,0x2927,0x2928,0x2929,0x292A,0x292B,0x292C,0x292D,0x292E,0x292F, + 0x2930,0x2931,0x2932,0x2933,0x2934,0x2935,0x2936,0x2937,0x2938,0x2939,0x293A,0x293B,0x293C,0x293D,0x293E,0x293F, + 0x2940,0x2941,0x2942,0x2943,0x2944,0x2945,0x2946,0x2947,0x2948,0x2949,0x294A,0x294B,0x294C,0x294D,0x294E,0x294F, + 0x2950,0x2951,0x2952,0x2953,0x2954,0x2955,0x2956,0x2957,0x2958,0x2959,0x295A,0x295B,0x295C,0x295D,0x295E,0x295F, + 0x2960,0x2961,0x2962,0x2963,0x2964,0x2965,0x2966,0x2967,0x2968,0x2969,0x296A,0x296B,0x296C,0x296D,0x296E,0x296F, + 0x2970,0x2971,0x2972,0x2973,0x2974,0x2975,0x2976,0x2977,0x2978,0x2979,0x297A,0x297B,0x297C,0x297D,0x297E,0x297F, + 0x2980,0x2981,0x2982,0x2983,0x2984,0x2985,0x2986,0x2987,0x2988,0x2989,0x298A,0x298B,0x298C,0x298D,0x298E,0x298F, + 0x2990,0x2991,0x2992,0x2993,0x2994,0x2995,0x2996,0x2997,0x2998,0x2999,0x299A,0x299B,0x299C,0x299D,0x299E,0x299F, + 0x29A0,0x29A1,0x29A2,0x29A3,0x29A4,0x29A5,0x29A6,0x29A7,0x29A8,0x29A9,0x29AA,0x29AB,0x29AC,0x29AD,0x29AE,0x29AF, + 0x29B0,0x29B1,0x29B2,0x29B3,0x29B4,0x29B5,0x29B6,0x29B7,0x29B8,0x29B9,0x29BA,0x29BB,0x29BC,0x29BD,0x29BE,0x29BF, + 0x29C0,0x29C1,0x29C2,0x29C3,0x29C4,0x29C5,0x29C6,0x29C7,0x29C8,0x29C9,0x29CA,0x29CB,0x29CC,0x29CD,0x29CE,0x29CF, + 0x29D0,0x29D1,0x29D2,0x29D3,0x29D4,0x29D5,0x29D6,0x29D7,0x29D8,0x29D9,0x29DA,0x29DB,0x29DC,0x29DD,0x29DE,0x29DF, + 0x29E0,0x29E1,0x29E2,0x29E3,0x29E4,0x29E5,0x29E6,0x29E7,0x29E8,0x29E9,0x29EA,0x29EB,0x29EC,0x29ED,0x29EE,0x29EF, + 0x29F0,0x29F1,0x29F2,0x29F3,0x29F4,0x29F5,0x29F6,0x29F7,0x29F8,0x29F9,0x29FA,0x29FB,0x29FC,0x29FD,0x29FE,0x29FF, + 0x2A00,0x2A01,0x2A02,0x2A03,0x2A04,0x2A05,0x2A06,0x2A07,0x2A08,0x2A09,0x2A0A,0x2A0B,0x2A0C,0x2A0D,0x2A0E,0x2A0F, + 0x2A10,0x2A11,0x2A12,0x2A13,0x2A14,0x2A15,0x2A16,0x2A17,0x2A18,0x2A19,0x2A1A,0x2A1B,0x2A1C,0x2A1D,0x2A1E,0x2A1F, + 0x2A20,0x2A21,0x2A22,0x2A23,0x2A24,0x2A25,0x2A26,0x2A27,0x2A28,0x2A29,0x2A2A,0x2A2B,0x2A2C,0x2A2D,0x2A2E,0x2A2F, + 0x2A30,0x2A31,0x2A32,0x2A33,0x2A34,0x2A35,0x2A36,0x2A37,0x2A38,0x2A39,0x2A3A,0x2A3B,0x2A3C,0x2A3D,0x2A3E,0x2A3F, + 0x2A40,0x2A41,0x2A42,0x2A43,0x2A44,0x2A45,0x2A46,0x2A47,0x2A48,0x2A49,0x2A4A,0x2A4B,0x2A4C,0x2A4D,0x2A4E,0x2A4F, + 0x2A50,0x2A51,0x2A52,0x2A53,0x2A54,0x2A55,0x2A56,0x2A57,0x2A58,0x2A59,0x2A5A,0x2A5B,0x2A5C,0x2A5D,0x2A5E,0x2A5F, + 0x2A60,0x2A61,0x2A62,0x2A63,0x2A64,0x2A65,0x2A66,0x2A67,0x2A68,0x2A69,0x2A6A,0x2A6B,0x2A6C,0x2A6D,0x2A6E,0x2A6F, + 0x2A70,0x2A71,0x2A72,0x2A73,0x2A74,0x2A75,0x2A76,0x2A77,0x2A78,0x2A79,0x2A7A,0x2A7B,0x2A7C,0x2A7D,0x2A7E,0x2A7F, + 0x2A80,0x2A81,0x2A82,0x2A83,0x2A84,0x2A85,0x2A86,0x2A87,0x2A88,0x2A89,0x2A8A,0x2A8B,0x2A8C,0x2A8D,0x2A8E,0x2A8F, + 0x2A90,0x2A91,0x2A92,0x2A93,0x2A94,0x2A95,0x2A96,0x2A97,0x2A98,0x2A99,0x2A9A,0x2A9B,0x2A9C,0x2A9D,0x2A9E,0x2A9F, + 0x2AA0,0x2AA1,0x2AA2,0x2AA3,0x2AA4,0x2AA5,0x2AA6,0x2AA7,0x2AA8,0x2AA9,0x2AAA,0x2AAB,0x2AAC,0x2AAD,0x2AAE,0x2AAF, + 0x2AB0,0x2AB1,0x2AB2,0x2AB3,0x2AB4,0x2AB5,0x2AB6,0x2AB7,0x2AB8,0x2AB9,0x2ABA,0x2ABB,0x2ABC,0x2ABD,0x2ABE,0x2ABF, + 0x2AC0,0x2AC1,0x2AC2,0x2AC3,0x2AC4,0x2AC5,0x2AC6,0x2AC7,0x2AC8,0x2AC9,0x2ACA,0x2ACB,0x2ACC,0x2ACD,0x2ACE,0x2ACF, + 0x2AD0,0x2AD1,0x2AD2,0x2AD3,0x2AD4,0x2AD5,0x2AD6,0x2AD7,0x2AD8,0x2AD9,0x2ADA,0x2ADB,0x2ADC,0x2ADD,0x2ADE,0x2ADF, + 0x2AE0,0x2AE1,0x2AE2,0x2AE3,0x2AE4,0x2AE5,0x2AE6,0x2AE7,0x2AE8,0x2AE9,0x2AEA,0x2AEB,0x2AEC,0x2AED,0x2AEE,0x2AEF, + 0x2AF0,0x2AF1,0x2AF2,0x2AF3,0x2AF4,0x2AF5,0x2AF6,0x2AF7,0x2AF8,0x2AF9,0x2AFA,0x2AFB,0x2AFC,0x2AFD,0x2AFE,0x2AFF, + 0x2B00,0x2B01,0x2B02,0x2B03,0x2B04,0x2B05,0x2B06,0x2B07,0x2B08,0x2B09,0x2B0A,0x2B0B,0x2B0C,0x2B0D,0x2B0E,0x2B0F, + 0x2B10,0x2B11,0x2B12,0x2B13,0x2B14,0x2B15,0x2B16,0x2B17,0x2B18,0x2B19,0x2B1A,0x2B1B,0x2B1C,0x2B1D,0x2B1E,0x2B1F, + 0x2B20,0x2B21,0x2B22,0x2B23,0x2B24,0x2B25,0x2B26,0x2B27,0x2B28,0x2B29,0x2B2A,0x2B2B,0x2B2C,0x2B2D,0x2B2E,0x2B2F, + 0x2B30,0x2B31,0x2B32,0x2B33,0x2B34,0x2B35,0x2B36,0x2B37,0x2B38,0x2B39,0x2B3A,0x2B3B,0x2B3C,0x2B3D,0x2B3E,0x2B3F, + 0x2B40,0x2B41,0x2B42,0x2B43,0x2B44,0x2B45,0x2B46,0x2B47,0x2B48,0x2B49,0x2B4A,0x2B4B,0x2B4C,0x2B4D,0x2B4E,0x2B4F, + 0x2B50,0x2B51,0x2B52,0x2B53,0x2B54,0x2B55,0x2B56,0x2B57,0x2B58,0x2B59,0x2B5A,0x2B5B,0x2B5C,0x2B5D,0x2B5E,0x2B5F, + 0x2B60,0x2B61,0x2B62,0x2B63,0x2B64,0x2B65,0x2B66,0x2B67,0x2B68,0x2B69,0x2B6A,0x2B6B,0x2B6C,0x2B6D,0x2B6E,0x2B6F, + 0x2B70,0x2B71,0x2B72,0x2B73,0x2B74,0x2B75,0x2B76,0x2B77,0x2B78,0x2B79,0x2B7A,0x2B7B,0x2B7C,0x2B7D,0x2B7E,0x2B7F, + 0x2B80,0x2B81,0x2B82,0x2B83,0x2B84,0x2B85,0x2B86,0x2B87,0x2B88,0x2B89,0x2B8A,0x2B8B,0x2B8C,0x2B8D,0x2B8E,0x2B8F, + 0x2B90,0x2B91,0x2B92,0x2B93,0x2B94,0x2B95,0x2B96,0x2B97,0x2B98,0x2B99,0x2B9A,0x2B9B,0x2B9C,0x2B9D,0x2B9E,0x2B9F, + 0x2BA0,0x2BA1,0x2BA2,0x2BA3,0x2BA4,0x2BA5,0x2BA6,0x2BA7,0x2BA8,0x2BA9,0x2BAA,0x2BAB,0x2BAC,0x2BAD,0x2BAE,0x2BAF, + 0x2BB0,0x2BB1,0x2BB2,0x2BB3,0x2BB4,0x2BB5,0x2BB6,0x2BB7,0x2BB8,0x2BB9,0x2BBA,0x2BBB,0x2BBC,0x2BBD,0x2BBE,0x2BBF, + 0x2BC0,0x2BC1,0x2BC2,0x2BC3,0x2BC4,0x2BC5,0x2BC6,0x2BC7,0x2BC8,0x2BC9,0x2BCA,0x2BCB,0x2BCC,0x2BCD,0x2BCE,0x2BCF, + 0x2BD0,0x2BD1,0x2BD2,0x2BD3,0x2BD4,0x2BD5,0x2BD6,0x2BD7,0x2BD8,0x2BD9,0x2BDA,0x2BDB,0x2BDC,0x2BDD,0x2BDE,0x2BDF, + 0x2BE0,0x2BE1,0x2BE2,0x2BE3,0x2BE4,0x2BE5,0x2BE6,0x2BE7,0x2BE8,0x2BE9,0x2BEA,0x2BEB,0x2BEC,0x2BED,0x2BEE,0x2BEF, + 0x2BF0,0x2BF1,0x2BF2,0x2BF3,0x2BF4,0x2BF5,0x2BF6,0x2BF7,0x2BF8,0x2BF9,0x2BFA,0x2BFB,0x2BFC,0x2BFD,0x2BFE,0x2BFF, + 0x2C00,0x2C01,0x2C02,0x2C03,0x2C04,0x2C05,0x2C06,0x2C07,0x2C08,0x2C09,0x2C0A,0x2C0B,0x2C0C,0x2C0D,0x2C0E,0x2C0F, + 0x2C10,0x2C11,0x2C12,0x2C13,0x2C14,0x2C15,0x2C16,0x2C17,0x2C18,0x2C19,0x2C1A,0x2C1B,0x2C1C,0x2C1D,0x2C1E,0x2C1F, + 0x2C20,0x2C21,0x2C22,0x2C23,0x2C24,0x2C25,0x2C26,0x2C27,0x2C28,0x2C29,0x2C2A,0x2C2B,0x2C2C,0x2C2D,0x2C2E,0x2C2F, + 0x2C30,0x2C31,0x2C32,0x2C33,0x2C34,0x2C35,0x2C36,0x2C37,0x2C38,0x2C39,0x2C3A,0x2C3B,0x2C3C,0x2C3D,0x2C3E,0x2C3F, + 0x2C40,0x2C41,0x2C42,0x2C43,0x2C44,0x2C45,0x2C46,0x2C47,0x2C48,0x2C49,0x2C4A,0x2C4B,0x2C4C,0x2C4D,0x2C4E,0x2C4F, + 0x2C50,0x2C51,0x2C52,0x2C53,0x2C54,0x2C55,0x2C56,0x2C57,0x2C58,0x2C59,0x2C5A,0x2C5B,0x2C5C,0x2C5D,0x2C5E,0x2C5F, + 0x2C60,0x2C61,0x2C62,0x2C63,0x2C64,0x2C65,0x2C66,0x2C67,0x2C68,0x2C69,0x2C6A,0x2C6B,0x2C6C,0x2C6D,0x2C6E,0x2C6F, + 0x2C70,0x2C71,0x2C72,0x2C73,0x2C74,0x2C75,0x2C76,0x2C77,0x2C78,0x2C79,0x2C7A,0x2C7B,0x2C7C,0x2C7D,0x2C7E,0x2C7F, + 0x2C80,0x2C81,0x2C82,0x2C83,0x2C84,0x2C85,0x2C86,0x2C87,0x2C88,0x2C89,0x2C8A,0x2C8B,0x2C8C,0x2C8D,0x2C8E,0x2C8F, + 0x2C90,0x2C91,0x2C92,0x2C93,0x2C94,0x2C95,0x2C96,0x2C97,0x2C98,0x2C99,0x2C9A,0x2C9B,0x2C9C,0x2C9D,0x2C9E,0x2C9F, + 0x2CA0,0x2CA1,0x2CA2,0x2CA3,0x2CA4,0x2CA5,0x2CA6,0x2CA7,0x2CA8,0x2CA9,0x2CAA,0x2CAB,0x2CAC,0x2CAD,0x2CAE,0x2CAF, + 0x2CB0,0x2CB1,0x2CB2,0x2CB3,0x2CB4,0x2CB5,0x2CB6,0x2CB7,0x2CB8,0x2CB9,0x2CBA,0x2CBB,0x2CBC,0x2CBD,0x2CBE,0x2CBF, + 0x2CC0,0x2CC1,0x2CC2,0x2CC3,0x2CC4,0x2CC5,0x2CC6,0x2CC7,0x2CC8,0x2CC9,0x2CCA,0x2CCB,0x2CCC,0x2CCD,0x2CCE,0x2CCF, + 0x2CD0,0x2CD1,0x2CD2,0x2CD3,0x2CD4,0x2CD5,0x2CD6,0x2CD7,0x2CD8,0x2CD9,0x2CDA,0x2CDB,0x2CDC,0x2CDD,0x2CDE,0x2CDF, + 0x2CE0,0x2CE1,0x2CE2,0x2CE3,0x2CE4,0x2CE5,0x2CE6,0x2CE7,0x2CE8,0x2CE9,0x2CEA,0x2CEB,0x2CEC,0x2CED,0x2CEE,0x2CEF, + 0x2CF0,0x2CF1,0x2CF2,0x2CF3,0x2CF4,0x2CF5,0x2CF6,0x2CF7,0x2CF8,0x2CF9,0x2CFA,0x2CFB,0x2CFC,0x2CFD,0x2CFE,0x2CFF, + 0x2D00,0x2D01,0x2D02,0x2D03,0x2D04,0x2D05,0x2D06,0x2D07,0x2D08,0x2D09,0x2D0A,0x2D0B,0x2D0C,0x2D0D,0x2D0E,0x2D0F, + 0x2D10,0x2D11,0x2D12,0x2D13,0x2D14,0x2D15,0x2D16,0x2D17,0x2D18,0x2D19,0x2D1A,0x2D1B,0x2D1C,0x2D1D,0x2D1E,0x2D1F, + 0x2D20,0x2D21,0x2D22,0x2D23,0x2D24,0x2D25,0x2D26,0x2D27,0x2D28,0x2D29,0x2D2A,0x2D2B,0x2D2C,0x2D2D,0x2D2E,0x2D2F, + 0x2D30,0x2D31,0x2D32,0x2D33,0x2D34,0x2D35,0x2D36,0x2D37,0x2D38,0x2D39,0x2D3A,0x2D3B,0x2D3C,0x2D3D,0x2D3E,0x2D3F, + 0x2D40,0x2D41,0x2D42,0x2D43,0x2D44,0x2D45,0x2D46,0x2D47,0x2D48,0x2D49,0x2D4A,0x2D4B,0x2D4C,0x2D4D,0x2D4E,0x2D4F, + 0x2D50,0x2D51,0x2D52,0x2D53,0x2D54,0x2D55,0x2D56,0x2D57,0x2D58,0x2D59,0x2D5A,0x2D5B,0x2D5C,0x2D5D,0x2D5E,0x2D5F, + 0x2D60,0x2D61,0x2D62,0x2D63,0x2D64,0x2D65,0x2D66,0x2D67,0x2D68,0x2D69,0x2D6A,0x2D6B,0x2D6C,0x2D6D,0x2D6E,0x2D6F, + 0x2D70,0x2D71,0x2D72,0x2D73,0x2D74,0x2D75,0x2D76,0x2D77,0x2D78,0x2D79,0x2D7A,0x2D7B,0x2D7C,0x2D7D,0x2D7E,0x2D7F, + 0x2D80,0x2D81,0x2D82,0x2D83,0x2D84,0x2D85,0x2D86,0x2D87,0x2D88,0x2D89,0x2D8A,0x2D8B,0x2D8C,0x2D8D,0x2D8E,0x2D8F, + 0x2D90,0x2D91,0x2D92,0x2D93,0x2D94,0x2D95,0x2D96,0x2D97,0x2D98,0x2D99,0x2D9A,0x2D9B,0x2D9C,0x2D9D,0x2D9E,0x2D9F, + 0x2DA0,0x2DA1,0x2DA2,0x2DA3,0x2DA4,0x2DA5,0x2DA6,0x2DA7,0x2DA8,0x2DA9,0x2DAA,0x2DAB,0x2DAC,0x2DAD,0x2DAE,0x2DAF, + 0x2DB0,0x2DB1,0x2DB2,0x2DB3,0x2DB4,0x2DB5,0x2DB6,0x2DB7,0x2DB8,0x2DB9,0x2DBA,0x2DBB,0x2DBC,0x2DBD,0x2DBE,0x2DBF, + 0x2DC0,0x2DC1,0x2DC2,0x2DC3,0x2DC4,0x2DC5,0x2DC6,0x2DC7,0x2DC8,0x2DC9,0x2DCA,0x2DCB,0x2DCC,0x2DCD,0x2DCE,0x2DCF, + 0x2DD0,0x2DD1,0x2DD2,0x2DD3,0x2DD4,0x2DD5,0x2DD6,0x2DD7,0x2DD8,0x2DD9,0x2DDA,0x2DDB,0x2DDC,0x2DDD,0x2DDE,0x2DDF, + 0x2DE0,0x2DE1,0x2DE2,0x2DE3,0x2DE4,0x2DE5,0x2DE6,0x2DE7,0x2DE8,0x2DE9,0x2DEA,0x2DEB,0x2DEC,0x2DED,0x2DEE,0x2DEF, + 0x2DF0,0x2DF1,0x2DF2,0x2DF3,0x2DF4,0x2DF5,0x2DF6,0x2DF7,0x2DF8,0x2DF9,0x2DFA,0x2DFB,0x2DFC,0x2DFD,0x2DFE,0x2DFF, + 0x2E00,0x2E01,0x2E02,0x2E03,0x2E04,0x2E05,0x2E06,0x2E07,0x2E08,0x2E09,0x2E0A,0x2E0B,0x2E0C,0x2E0D,0x2E0E,0x2E0F, + 0x2E10,0x2E11,0x2E12,0x2E13,0x2E14,0x2E15,0x2E16,0x2E17,0x2E18,0x2E19,0x2E1A,0x2E1B,0x2E1C,0x2E1D,0x2E1E,0x2E1F, + 0x2E20,0x2E21,0x2E22,0x2E23,0x2E24,0x2E25,0x2E26,0x2E27,0x2E28,0x2E29,0x2E2A,0x2E2B,0x2E2C,0x2E2D,0x2E2E,0x2E2F, + 0x2E30,0x2E31,0x2E32,0x2E33,0x2E34,0x2E35,0x2E36,0x2E37,0x2E38,0x2E39,0x2E3A,0x2E3B,0x2E3C,0x2E3D,0x2E3E,0x2E3F, + 0x2E40,0x2E41,0x2E42,0x2E43,0x2E44,0x2E45,0x2E46,0x2E47,0x2E48,0x2E49,0x2E4A,0x2E4B,0x2E4C,0x2E4D,0x2E4E,0x2E4F, + 0x2E50,0x2E51,0x2E52,0x2E53,0x2E54,0x2E55,0x2E56,0x2E57,0x2E58,0x2E59,0x2E5A,0x2E5B,0x2E5C,0x2E5D,0x2E5E,0x2E5F, + 0x2E60,0x2E61,0x2E62,0x2E63,0x2E64,0x2E65,0x2E66,0x2E67,0x2E68,0x2E69,0x2E6A,0x2E6B,0x2E6C,0x2E6D,0x2E6E,0x2E6F, + 0x2E70,0x2E71,0x2E72,0x2E73,0x2E74,0x2E75,0x2E76,0x2E77,0x2E78,0x2E79,0x2E7A,0x2E7B,0x2E7C,0x2E7D,0x2E7E,0x2E7F, + 0x2E80,0x2E81,0x2E82,0x2E83,0x2E84,0x2E85,0x2E86,0x2E87,0x2E88,0x2E89,0x2E8A,0x2E8B,0x2E8C,0x2E8D,0x2E8E,0x2E8F, + 0x2E90,0x2E91,0x2E92,0x2E93,0x2E94,0x2E95,0x2E96,0x2E97,0x2E98,0x2E99,0x2E9A,0x2E9B,0x2E9C,0x2E9D,0x2E9E,0x2E9F, + 0x2EA0,0x2EA1,0x2EA2,0x2EA3,0x2EA4,0x2EA5,0x2EA6,0x2EA7,0x2EA8,0x2EA9,0x2EAA,0x2EAB,0x2EAC,0x2EAD,0x2EAE,0x2EAF, + 0x2EB0,0x2EB1,0x2EB2,0x2EB3,0x2EB4,0x2EB5,0x2EB6,0x2EB7,0x2EB8,0x2EB9,0x2EBA,0x2EBB,0x2EBC,0x2EBD,0x2EBE,0x2EBF, + 0x2EC0,0x2EC1,0x2EC2,0x2EC3,0x2EC4,0x2EC5,0x2EC6,0x2EC7,0x2EC8,0x2EC9,0x2ECA,0x2ECB,0x2ECC,0x2ECD,0x2ECE,0x2ECF, + 0x2ED0,0x2ED1,0x2ED2,0x2ED3,0x2ED4,0x2ED5,0x2ED6,0x2ED7,0x2ED8,0x2ED9,0x2EDA,0x2EDB,0x2EDC,0x2EDD,0x2EDE,0x2EDF, + 0x2EE0,0x2EE1,0x2EE2,0x2EE3,0x2EE4,0x2EE5,0x2EE6,0x2EE7,0x2EE8,0x2EE9,0x2EEA,0x2EEB,0x2EEC,0x2EED,0x2EEE,0x2EEF, + 0x2EF0,0x2EF1,0x2EF2,0x2EF3,0x2EF4,0x2EF5,0x2EF6,0x2EF7,0x2EF8,0x2EF9,0x2EFA,0x2EFB,0x2EFC,0x2EFD,0x2EFE,0x2EFF, + 0x2F00,0x2F01,0x2F02,0x2F03,0x2F04,0x2F05,0x2F06,0x2F07,0x2F08,0x2F09,0x2F0A,0x2F0B,0x2F0C,0x2F0D,0x2F0E,0x2F0F, + 0x2F10,0x2F11,0x2F12,0x2F13,0x2F14,0x2F15,0x2F16,0x2F17,0x2F18,0x2F19,0x2F1A,0x2F1B,0x2F1C,0x2F1D,0x2F1E,0x2F1F, + 0x2F20,0x2F21,0x2F22,0x2F23,0x2F24,0x2F25,0x2F26,0x2F27,0x2F28,0x2F29,0x2F2A,0x2F2B,0x2F2C,0x2F2D,0x2F2E,0x2F2F, + 0x2F30,0x2F31,0x2F32,0x2F33,0x2F34,0x2F35,0x2F36,0x2F37,0x2F38,0x2F39,0x2F3A,0x2F3B,0x2F3C,0x2F3D,0x2F3E,0x2F3F, + 0x2F40,0x2F41,0x2F42,0x2F43,0x2F44,0x2F45,0x2F46,0x2F47,0x2F48,0x2F49,0x2F4A,0x2F4B,0x2F4C,0x2F4D,0x2F4E,0x2F4F, + 0x2F50,0x2F51,0x2F52,0x2F53,0x2F54,0x2F55,0x2F56,0x2F57,0x2F58,0x2F59,0x2F5A,0x2F5B,0x2F5C,0x2F5D,0x2F5E,0x2F5F, + 0x2F60,0x2F61,0x2F62,0x2F63,0x2F64,0x2F65,0x2F66,0x2F67,0x2F68,0x2F69,0x2F6A,0x2F6B,0x2F6C,0x2F6D,0x2F6E,0x2F6F, + 0x2F70,0x2F71,0x2F72,0x2F73,0x2F74,0x2F75,0x2F76,0x2F77,0x2F78,0x2F79,0x2F7A,0x2F7B,0x2F7C,0x2F7D,0x2F7E,0x2F7F, + 0x2F80,0x2F81,0x2F82,0x2F83,0x2F84,0x2F85,0x2F86,0x2F87,0x2F88,0x2F89,0x2F8A,0x2F8B,0x2F8C,0x2F8D,0x2F8E,0x2F8F, + 0x2F90,0x2F91,0x2F92,0x2F93,0x2F94,0x2F95,0x2F96,0x2F97,0x2F98,0x2F99,0x2F9A,0x2F9B,0x2F9C,0x2F9D,0x2F9E,0x2F9F, + 0x2FA0,0x2FA1,0x2FA2,0x2FA3,0x2FA4,0x2FA5,0x2FA6,0x2FA7,0x2FA8,0x2FA9,0x2FAA,0x2FAB,0x2FAC,0x2FAD,0x2FAE,0x2FAF, + 0x2FB0,0x2FB1,0x2FB2,0x2FB3,0x2FB4,0x2FB5,0x2FB6,0x2FB7,0x2FB8,0x2FB9,0x2FBA,0x2FBB,0x2FBC,0x2FBD,0x2FBE,0x2FBF, + 0x2FC0,0x2FC1,0x2FC2,0x2FC3,0x2FC4,0x2FC5,0x2FC6,0x2FC7,0x2FC8,0x2FC9,0x2FCA,0x2FCB,0x2FCC,0x2FCD,0x2FCE,0x2FCF, + 0x2FD0,0x2FD1,0x2FD2,0x2FD3,0x2FD4,0x2FD5,0x2FD6,0x2FD7,0x2FD8,0x2FD9,0x2FDA,0x2FDB,0x2FDC,0x2FDD,0x2FDE,0x2FDF, + 0x2FE0,0x2FE1,0x2FE2,0x2FE3,0x2FE4,0x2FE5,0x2FE6,0x2FE7,0x2FE8,0x2FE9,0x2FEA,0x2FEB,0x2FEC,0x2FED,0x2FEE,0x2FEF, + 0x2FF0,0x2FF1,0x2FF2,0x2FF3,0x2FF4,0x2FF5,0x2FF6,0x2FF7,0x2FF8,0x2FF9,0x2FFA,0x2FFB,0x2FFC,0x2FFD,0x2FFE,0x2FFF, + 0x3000,0x3001,0x3002,0x3003,0x3004,0x3005,0x3006,0x3007,0x3008,0x3009,0x300A,0x300B,0x300C,0x300D,0x300E,0x300F, + 0x3010,0x3011,0x3012,0x3013,0x3014,0x3015,0x3016,0x3017,0x3018,0x3019,0x301A,0x301B,0x301C,0x301D,0x301E,0x301F, + 0x3020,0x3021,0x3022,0x3023,0x3024,0x3025,0x3026,0x3027,0x3028,0x3029,0x302A,0x302B,0x302C,0x302D,0x302E,0x302F, + 0x3030,0x3031,0x3032,0x3033,0x3034,0x3035,0x3036,0x3037,0x3038,0x3039,0x303A,0x303B,0x303C,0x303D,0x303E,0x303F, + 0x3040,0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F, + 0x3050,0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F, + 0x3060,0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F, + 0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F, + 0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F, + 0x3090,0x3091,0x3092,0x3093,0x3094,0x3095,0x3096,0x3097,0x3098,0x3099,0x309A,0x309B,0x309C,0x309D,0x309E,0x309F, + 0x30A0,0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF, + 0x30B0,0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF, + 0x30C0,0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF, + 0x30D0,0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF, + 0x30E0,0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF, + 0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6,0x30F7,0x30F8,0x30F9,0x30FA,0x30FB,0x30FC,0x30FD,0x30FE,0x30FF, + 0x3100,0x3101,0x3102,0x3103,0x3104,0x3105,0x3106,0x3107,0x3108,0x3109,0x310A,0x310B,0x310C,0x310D,0x310E,0x310F, + 0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117,0x3118,0x3119,0x311A,0x311B,0x311C,0x311D,0x311E,0x311F, + 0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127,0x3128,0x3129,0x312A,0x312B,0x312C,0x312D,0x312E,0x312F, + 0x3130,0x3131,0x3132,0x3133,0x3134,0x3135,0x3136,0x3137,0x3138,0x3139,0x313A,0x313B,0x313C,0x313D,0x313E,0x313F, + 0x3140,0x3141,0x3142,0x3143,0x3144,0x3145,0x3146,0x3147,0x3148,0x3149,0x314A,0x314B,0x314C,0x314D,0x314E,0x314F, + 0x3150,0x3151,0x3152,0x3153,0x3154,0x3155,0x3156,0x3157,0x3158,0x3159,0x315A,0x315B,0x315C,0x315D,0x315E,0x315F, + 0x3160,0x3161,0x3162,0x3163,0x3164,0x3165,0x3166,0x3167,0x3168,0x3169,0x316A,0x316B,0x316C,0x316D,0x316E,0x316F, + 0x3170,0x3171,0x3172,0x3173,0x3174,0x3175,0x3176,0x3177,0x3178,0x3179,0x317A,0x317B,0x317C,0x317D,0x317E,0x317F, + 0x3180,0x3181,0x3182,0x3183,0x3184,0x3185,0x3186,0x3187,0x3188,0x3189,0x318A,0x318B,0x318C,0x318D,0x318E,0x318F, + 0x3190,0x3191,0x3192,0x3193,0x3194,0x3195,0x3196,0x3197,0x3198,0x3199,0x319A,0x319B,0x319C,0x319D,0x319E,0x319F, + 0x31A0,0x31A1,0x31A2,0x31A3,0x31A4,0x31A5,0x31A6,0x31A7,0x31A8,0x31A9,0x31AA,0x31AB,0x31AC,0x31AD,0x31AE,0x31AF, + 0x31B0,0x31B1,0x31B2,0x31B3,0x31B4,0x31B5,0x31B6,0x31B7,0x31B8,0x31B9,0x31BA,0x31BB,0x31BC,0x31BD,0x31BE,0x31BF, + 0x31C0,0x31C1,0x31C2,0x31C3,0x31C4,0x31C5,0x31C6,0x31C7,0x31C8,0x31C9,0x31CA,0x31CB,0x31CC,0x31CD,0x31CE,0x31CF, + 0x31D0,0x31D1,0x31D2,0x31D3,0x31D4,0x31D5,0x31D6,0x31D7,0x31D8,0x31D9,0x31DA,0x31DB,0x31DC,0x31DD,0x31DE,0x31DF, + 0x31E0,0x31E1,0x31E2,0x31E3,0x31E4,0x31E5,0x31E6,0x31E7,0x31E8,0x31E9,0x31EA,0x31EB,0x31EC,0x31ED,0x31EE,0x31EF, + 0x31F0,0x31F1,0x31F2,0x31F3,0x31F4,0x31F5,0x31F6,0x31F7,0x31F8,0x31F9,0x31FA,0x31FB,0x31FC,0x31FD,0x31FE,0x31FF, + 0x3200,0x3201,0x3202,0x3203,0x3204,0x3205,0x3206,0x3207,0x3208,0x3209,0x320A,0x320B,0x320C,0x320D,0x320E,0x320F, + 0x3210,0x3211,0x3212,0x3213,0x3214,0x3215,0x3216,0x3217,0x3218,0x3219,0x321A,0x321B,0x321C,0x321D,0x321E,0x321F, + 0x3220,0x3221,0x3222,0x3223,0x3224,0x3225,0x3226,0x3227,0x3228,0x3229,0x322A,0x322B,0x322C,0x322D,0x322E,0x322F, + 0x3230,0x3231,0x3232,0x3233,0x3234,0x3235,0x3236,0x3237,0x3238,0x3239,0x323A,0x323B,0x323C,0x323D,0x323E,0x323F, + 0x3240,0x3241,0x3242,0x3243,0x3244,0x3245,0x3246,0x3247,0x3248,0x3249,0x324A,0x324B,0x324C,0x324D,0x324E,0x324F, + 0x3250,0x3251,0x3252,0x3253,0x3254,0x3255,0x3256,0x3257,0x3258,0x3259,0x325A,0x325B,0x325C,0x325D,0x325E,0x325F, + 0x3260,0x3261,0x3262,0x3263,0x3264,0x3265,0x3266,0x3267,0x3268,0x3269,0x326A,0x326B,0x326C,0x326D,0x326E,0x326F, + 0x3270,0x3271,0x3272,0x3273,0x3274,0x3275,0x3276,0x3277,0x3278,0x3279,0x327A,0x327B,0x327C,0x327D,0x327E,0x327F, + 0x3280,0x3281,0x3282,0x3283,0x3284,0x3285,0x3286,0x3287,0x3288,0x3289,0x328A,0x328B,0x328C,0x328D,0x328E,0x328F, + 0x3290,0x3291,0x3292,0x3293,0x3294,0x3295,0x3296,0x3297,0x3298,0x3299,0x329A,0x329B,0x329C,0x329D,0x329E,0x329F, + 0x32A0,0x32A1,0x32A2,0x32A3,0x32A4,0x32A5,0x32A6,0x32A7,0x32A8,0x32A9,0x32AA,0x32AB,0x32AC,0x32AD,0x32AE,0x32AF, + 0x32B0,0x32B1,0x32B2,0x32B3,0x32B4,0x32B5,0x32B6,0x32B7,0x32B8,0x32B9,0x32BA,0x32BB,0x32BC,0x32BD,0x32BE,0x32BF, + 0x32C0,0x32C1,0x32C2,0x32C3,0x32C4,0x32C5,0x32C6,0x32C7,0x32C8,0x32C9,0x32CA,0x32CB,0x32CC,0x32CD,0x32CE,0x32CF, + 0x32D0,0x32D1,0x32D2,0x32D3,0x32D4,0x32D5,0x32D6,0x32D7,0x32D8,0x32D9,0x32DA,0x32DB,0x32DC,0x32DD,0x32DE,0x32DF, + 0x32E0,0x32E1,0x32E2,0x32E3,0x32E4,0x32E5,0x32E6,0x32E7,0x32E8,0x32E9,0x32EA,0x32EB,0x32EC,0x32ED,0x32EE,0x32EF, + 0x32F0,0x32F1,0x32F2,0x32F3,0x32F4,0x32F5,0x32F6,0x32F7,0x32F8,0x32F9,0x32FA,0x32FB,0x32FC,0x32FD,0x32FE,0x32FF, + 0x3300,0x3301,0x3302,0x3303,0x3304,0x3305,0x3306,0x3307,0x3308,0x3309,0x330A,0x330B,0x330C,0x330D,0x330E,0x330F, + 0x3310,0x3311,0x3312,0x3313,0x3314,0x3315,0x3316,0x3317,0x3318,0x3319,0x331A,0x331B,0x331C,0x331D,0x331E,0x331F, + 0x3320,0x3321,0x3322,0x3323,0x3324,0x3325,0x3326,0x3327,0x3328,0x3329,0x332A,0x332B,0x332C,0x332D,0x332E,0x332F, + 0x3330,0x3331,0x3332,0x3333,0x3334,0x3335,0x3336,0x3337,0x3338,0x3339,0x333A,0x333B,0x333C,0x333D,0x333E,0x333F, + 0x3340,0x3341,0x3342,0x3343,0x3344,0x3345,0x3346,0x3347,0x3348,0x3349,0x334A,0x334B,0x334C,0x334D,0x334E,0x334F, + 0x3350,0x3351,0x3352,0x3353,0x3354,0x3355,0x3356,0x3357,0x3358,0x3359,0x335A,0x335B,0x335C,0x335D,0x335E,0x335F, + 0x3360,0x3361,0x3362,0x3363,0x3364,0x3365,0x3366,0x3367,0x3368,0x3369,0x336A,0x336B,0x336C,0x336D,0x336E,0x336F, + 0x3370,0x3371,0x3372,0x3373,0x3374,0x3375,0x3376,0x3377,0x3378,0x3379,0x337A,0x337B,0x337C,0x337D,0x337E,0x337F, + 0x3380,0x3381,0x3382,0x3383,0x3384,0x3385,0x3386,0x3387,0x3388,0x3389,0x338A,0x338B,0x338C,0x338D,0x338E,0x338F, + 0x3390,0x3391,0x3392,0x3393,0x3394,0x3395,0x3396,0x3397,0x3398,0x3399,0x339A,0x339B,0x339C,0x339D,0x339E,0x339F, + 0x33A0,0x33A1,0x33A2,0x33A3,0x33A4,0x33A5,0x33A6,0x33A7,0x33A8,0x33A9,0x33AA,0x33AB,0x33AC,0x33AD,0x33AE,0x33AF, + 0x33B0,0x33B1,0x33B2,0x33B3,0x33B4,0x33B5,0x33B6,0x33B7,0x33B8,0x33B9,0x33BA,0x33BB,0x33BC,0x33BD,0x33BE,0x33BF, + 0x33C0,0x33C1,0x33C2,0x33C3,0x33C4,0x33C5,0x33C6,0x33C7,0x33C8,0x33C9,0x33CA,0x33CB,0x33CC,0x33CD,0x33CE,0x33CF, + 0x33D0,0x33D1,0x33D2,0x33D3,0x33D4,0x33D5,0x33D6,0x33D7,0x33D8,0x33D9,0x33DA,0x33DB,0x33DC,0x33DD,0x33DE,0x33DF, + 0x33E0,0x33E1,0x33E2,0x33E3,0x33E4,0x33E5,0x33E6,0x33E7,0x33E8,0x33E9,0x33EA,0x33EB,0x33EC,0x33ED,0x33EE,0x33EF, + 0x33F0,0x33F1,0x33F2,0x33F3,0x33F4,0x33F5,0x33F6,0x33F7,0x33F8,0x33F9,0x33FA,0x33FB,0x33FC,0x33FD,0x33FE,0x33FF, + 0x3400,0x3401,0x3402,0x3403,0x3404,0x3405,0x3406,0x3407,0x3408,0x3409,0x340A,0x340B,0x340C,0x340D,0x340E,0x340F, + 0x3410,0x3411,0x3412,0x3413,0x3414,0x3415,0x3416,0x3417,0x3418,0x3419,0x341A,0x341B,0x341C,0x341D,0x341E,0x341F, + 0x3420,0x3421,0x3422,0x3423,0x3424,0x3425,0x3426,0x3427,0x3428,0x3429,0x342A,0x342B,0x342C,0x342D,0x342E,0x342F, + 0x3430,0x3431,0x3432,0x3433,0x3434,0x3435,0x3436,0x3437,0x3438,0x3439,0x343A,0x343B,0x343C,0x343D,0x343E,0x343F, + 0x3440,0x3441,0x3442,0x3443,0x3444,0x3445,0x3446,0x3447,0x3448,0x3449,0x344A,0x344B,0x344C,0x344D,0x344E,0x344F, + 0x3450,0x3451,0x3452,0x3453,0x3454,0x3455,0x3456,0x3457,0x3458,0x3459,0x345A,0x345B,0x345C,0x345D,0x345E,0x345F, + 0x3460,0x3461,0x3462,0x3463,0x3464,0x3465,0x3466,0x3467,0x3468,0x3469,0x346A,0x346B,0x346C,0x346D,0x346E,0x346F, + 0x3470,0x3471,0x3472,0x3473,0x3474,0x3475,0x3476,0x3477,0x3478,0x3479,0x347A,0x347B,0x347C,0x347D,0x347E,0x347F, + 0x3480,0x3481,0x3482,0x3483,0x3484,0x3485,0x3486,0x3487,0x3488,0x3489,0x348A,0x348B,0x348C,0x348D,0x348E,0x348F, + 0x3490,0x3491,0x3492,0x3493,0x3494,0x3495,0x3496,0x3497,0x3498,0x3499,0x349A,0x349B,0x349C,0x349D,0x349E,0x349F, + 0x34A0,0x34A1,0x34A2,0x34A3,0x34A4,0x34A5,0x34A6,0x34A7,0x34A8,0x34A9,0x34AA,0x34AB,0x34AC,0x34AD,0x34AE,0x34AF, + 0x34B0,0x34B1,0x34B2,0x34B3,0x34B4,0x34B5,0x34B6,0x34B7,0x34B8,0x34B9,0x34BA,0x34BB,0x34BC,0x34BD,0x34BE,0x34BF, + 0x34C0,0x34C1,0x34C2,0x34C3,0x34C4,0x34C5,0x34C6,0x34C7,0x34C8,0x34C9,0x34CA,0x34CB,0x34CC,0x34CD,0x34CE,0x34CF, + 0x34D0,0x34D1,0x34D2,0x34D3,0x34D4,0x34D5,0x34D6,0x34D7,0x34D8,0x34D9,0x34DA,0x34DB,0x34DC,0x34DD,0x34DE,0x34DF, + 0x34E0,0x34E1,0x34E2,0x34E3,0x34E4,0x34E5,0x34E6,0x34E7,0x34E8,0x34E9,0x34EA,0x34EB,0x34EC,0x34ED,0x34EE,0x34EF, + 0x34F0,0x34F1,0x34F2,0x34F3,0x34F4,0x34F5,0x34F6,0x34F7,0x34F8,0x34F9,0x34FA,0x34FB,0x34FC,0x34FD,0x34FE,0x34FF, + 0x3500,0x3501,0x3502,0x3503,0x3504,0x3505,0x3506,0x3507,0x3508,0x3509,0x350A,0x350B,0x350C,0x350D,0x350E,0x350F, + 0x3510,0x3511,0x3512,0x3513,0x3514,0x3515,0x3516,0x3517,0x3518,0x3519,0x351A,0x351B,0x351C,0x351D,0x351E,0x351F, + 0x3520,0x3521,0x3522,0x3523,0x3524,0x3525,0x3526,0x3527,0x3528,0x3529,0x352A,0x352B,0x352C,0x352D,0x352E,0x352F, + 0x3530,0x3531,0x3532,0x3533,0x3534,0x3535,0x3536,0x3537,0x3538,0x3539,0x353A,0x353B,0x353C,0x353D,0x353E,0x353F, + 0x3540,0x3541,0x3542,0x3543,0x3544,0x3545,0x3546,0x3547,0x3548,0x3549,0x354A,0x354B,0x354C,0x354D,0x354E,0x354F, + 0x3550,0x3551,0x3552,0x3553,0x3554,0x3555,0x3556,0x3557,0x3558,0x3559,0x355A,0x355B,0x355C,0x355D,0x355E,0x355F, + 0x3560,0x3561,0x3562,0x3563,0x3564,0x3565,0x3566,0x3567,0x3568,0x3569,0x356A,0x356B,0x356C,0x356D,0x356E,0x356F, + 0x3570,0x3571,0x3572,0x3573,0x3574,0x3575,0x3576,0x3577,0x3578,0x3579,0x357A,0x357B,0x357C,0x357D,0x357E,0x357F, + 0x3580,0x3581,0x3582,0x3583,0x3584,0x3585,0x3586,0x3587,0x3588,0x3589,0x358A,0x358B,0x358C,0x358D,0x358E,0x358F, + 0x3590,0x3591,0x3592,0x3593,0x3594,0x3595,0x3596,0x3597,0x3598,0x3599,0x359A,0x359B,0x359C,0x359D,0x359E,0x359F, + 0x35A0,0x35A1,0x35A2,0x35A3,0x35A4,0x35A5,0x35A6,0x35A7,0x35A8,0x35A9,0x35AA,0x35AB,0x35AC,0x35AD,0x35AE,0x35AF, + 0x35B0,0x35B1,0x35B2,0x35B3,0x35B4,0x35B5,0x35B6,0x35B7,0x35B8,0x35B9,0x35BA,0x35BB,0x35BC,0x35BD,0x35BE,0x35BF, + 0x35C0,0x35C1,0x35C2,0x35C3,0x35C4,0x35C5,0x35C6,0x35C7,0x35C8,0x35C9,0x35CA,0x35CB,0x35CC,0x35CD,0x35CE,0x35CF, + 0x35D0,0x35D1,0x35D2,0x35D3,0x35D4,0x35D5,0x35D6,0x35D7,0x35D8,0x35D9,0x35DA,0x35DB,0x35DC,0x35DD,0x35DE,0x35DF, + 0x35E0,0x35E1,0x35E2,0x35E3,0x35E4,0x35E5,0x35E6,0x35E7,0x35E8,0x35E9,0x35EA,0x35EB,0x35EC,0x35ED,0x35EE,0x35EF, + 0x35F0,0x35F1,0x35F2,0x35F3,0x35F4,0x35F5,0x35F6,0x35F7,0x35F8,0x35F9,0x35FA,0x35FB,0x35FC,0x35FD,0x35FE,0x35FF, + 0x3600,0x3601,0x3602,0x3603,0x3604,0x3605,0x3606,0x3607,0x3608,0x3609,0x360A,0x360B,0x360C,0x360D,0x360E,0x360F, + 0x3610,0x3611,0x3612,0x3613,0x3614,0x3615,0x3616,0x3617,0x3618,0x3619,0x361A,0x361B,0x361C,0x361D,0x361E,0x361F, + 0x3620,0x3621,0x3622,0x3623,0x3624,0x3625,0x3626,0x3627,0x3628,0x3629,0x362A,0x362B,0x362C,0x362D,0x362E,0x362F, + 0x3630,0x3631,0x3632,0x3633,0x3634,0x3635,0x3636,0x3637,0x3638,0x3639,0x363A,0x363B,0x363C,0x363D,0x363E,0x363F, + 0x3640,0x3641,0x3642,0x3643,0x3644,0x3645,0x3646,0x3647,0x3648,0x3649,0x364A,0x364B,0x364C,0x364D,0x364E,0x364F, + 0x3650,0x3651,0x3652,0x3653,0x3654,0x3655,0x3656,0x3657,0x3658,0x3659,0x365A,0x365B,0x365C,0x365D,0x365E,0x365F, + 0x3660,0x3661,0x3662,0x3663,0x3664,0x3665,0x3666,0x3667,0x3668,0x3669,0x366A,0x366B,0x366C,0x366D,0x366E,0x366F, + 0x3670,0x3671,0x3672,0x3673,0x3674,0x3675,0x3676,0x3677,0x3678,0x3679,0x367A,0x367B,0x367C,0x367D,0x367E,0x367F, + 0x3680,0x3681,0x3682,0x3683,0x3684,0x3685,0x3686,0x3687,0x3688,0x3689,0x368A,0x368B,0x368C,0x368D,0x368E,0x368F, + 0x3690,0x3691,0x3692,0x3693,0x3694,0x3695,0x3696,0x3697,0x3698,0x3699,0x369A,0x369B,0x369C,0x369D,0x369E,0x369F, + 0x36A0,0x36A1,0x36A2,0x36A3,0x36A4,0x36A5,0x36A6,0x36A7,0x36A8,0x36A9,0x36AA,0x36AB,0x36AC,0x36AD,0x36AE,0x36AF, + 0x36B0,0x36B1,0x36B2,0x36B3,0x36B4,0x36B5,0x36B6,0x36B7,0x36B8,0x36B9,0x36BA,0x36BB,0x36BC,0x36BD,0x36BE,0x36BF, + 0x36C0,0x36C1,0x36C2,0x36C3,0x36C4,0x36C5,0x36C6,0x36C7,0x36C8,0x36C9,0x36CA,0x36CB,0x36CC,0x36CD,0x36CE,0x36CF, + 0x36D0,0x36D1,0x36D2,0x36D3,0x36D4,0x36D5,0x36D6,0x36D7,0x36D8,0x36D9,0x36DA,0x36DB,0x36DC,0x36DD,0x36DE,0x36DF, + 0x36E0,0x36E1,0x36E2,0x36E3,0x36E4,0x36E5,0x36E6,0x36E7,0x36E8,0x36E9,0x36EA,0x36EB,0x36EC,0x36ED,0x36EE,0x36EF, + 0x36F0,0x36F1,0x36F2,0x36F3,0x36F4,0x36F5,0x36F6,0x36F7,0x36F8,0x36F9,0x36FA,0x36FB,0x36FC,0x36FD,0x36FE,0x36FF, + 0x3700,0x3701,0x3702,0x3703,0x3704,0x3705,0x3706,0x3707,0x3708,0x3709,0x370A,0x370B,0x370C,0x370D,0x370E,0x370F, + 0x3710,0x3711,0x3712,0x3713,0x3714,0x3715,0x3716,0x3717,0x3718,0x3719,0x371A,0x371B,0x371C,0x371D,0x371E,0x371F, + 0x3720,0x3721,0x3722,0x3723,0x3724,0x3725,0x3726,0x3727,0x3728,0x3729,0x372A,0x372B,0x372C,0x372D,0x372E,0x372F, + 0x3730,0x3731,0x3732,0x3733,0x3734,0x3735,0x3736,0x3737,0x3738,0x3739,0x373A,0x373B,0x373C,0x373D,0x373E,0x373F, + 0x3740,0x3741,0x3742,0x3743,0x3744,0x3745,0x3746,0x3747,0x3748,0x3749,0x374A,0x374B,0x374C,0x374D,0x374E,0x374F, + 0x3750,0x3751,0x3752,0x3753,0x3754,0x3755,0x3756,0x3757,0x3758,0x3759,0x375A,0x375B,0x375C,0x375D,0x375E,0x375F, + 0x3760,0x3761,0x3762,0x3763,0x3764,0x3765,0x3766,0x3767,0x3768,0x3769,0x376A,0x376B,0x376C,0x376D,0x376E,0x376F, + 0x3770,0x3771,0x3772,0x3773,0x3774,0x3775,0x3776,0x3777,0x3778,0x3779,0x377A,0x377B,0x377C,0x377D,0x377E,0x377F, + 0x3780,0x3781,0x3782,0x3783,0x3784,0x3785,0x3786,0x3787,0x3788,0x3789,0x378A,0x378B,0x378C,0x378D,0x378E,0x378F, + 0x3790,0x3791,0x3792,0x3793,0x3794,0x3795,0x3796,0x3797,0x3798,0x3799,0x379A,0x379B,0x379C,0x379D,0x379E,0x379F, + 0x37A0,0x37A1,0x37A2,0x37A3,0x37A4,0x37A5,0x37A6,0x37A7,0x37A8,0x37A9,0x37AA,0x37AB,0x37AC,0x37AD,0x37AE,0x37AF, + 0x37B0,0x37B1,0x37B2,0x37B3,0x37B4,0x37B5,0x37B6,0x37B7,0x37B8,0x37B9,0x37BA,0x37BB,0x37BC,0x37BD,0x37BE,0x37BF, + 0x37C0,0x37C1,0x37C2,0x37C3,0x37C4,0x37C5,0x37C6,0x37C7,0x37C8,0x37C9,0x37CA,0x37CB,0x37CC,0x37CD,0x37CE,0x37CF, + 0x37D0,0x37D1,0x37D2,0x37D3,0x37D4,0x37D5,0x37D6,0x37D7,0x37D8,0x37D9,0x37DA,0x37DB,0x37DC,0x37DD,0x37DE,0x37DF, + 0x37E0,0x37E1,0x37E2,0x37E3,0x37E4,0x37E5,0x37E6,0x37E7,0x37E8,0x37E9,0x37EA,0x37EB,0x37EC,0x37ED,0x37EE,0x37EF, + 0x37F0,0x37F1,0x37F2,0x37F3,0x37F4,0x37F5,0x37F6,0x37F7,0x37F8,0x37F9,0x37FA,0x37FB,0x37FC,0x37FD,0x37FE,0x37FF, + 0x3800,0x3801,0x3802,0x3803,0x3804,0x3805,0x3806,0x3807,0x3808,0x3809,0x380A,0x380B,0x380C,0x380D,0x380E,0x380F, + 0x3810,0x3811,0x3812,0x3813,0x3814,0x3815,0x3816,0x3817,0x3818,0x3819,0x381A,0x381B,0x381C,0x381D,0x381E,0x381F, + 0x3820,0x3821,0x3822,0x3823,0x3824,0x3825,0x3826,0x3827,0x3828,0x3829,0x382A,0x382B,0x382C,0x382D,0x382E,0x382F, + 0x3830,0x3831,0x3832,0x3833,0x3834,0x3835,0x3836,0x3837,0x3838,0x3839,0x383A,0x383B,0x383C,0x383D,0x383E,0x383F, + 0x3840,0x3841,0x3842,0x3843,0x3844,0x3845,0x3846,0x3847,0x3848,0x3849,0x384A,0x384B,0x384C,0x384D,0x384E,0x384F, + 0x3850,0x3851,0x3852,0x3853,0x3854,0x3855,0x3856,0x3857,0x3858,0x3859,0x385A,0x385B,0x385C,0x385D,0x385E,0x385F, + 0x3860,0x3861,0x3862,0x3863,0x3864,0x3865,0x3866,0x3867,0x3868,0x3869,0x386A,0x386B,0x386C,0x386D,0x386E,0x386F, + 0x3870,0x3871,0x3872,0x3873,0x3874,0x3875,0x3876,0x3877,0x3878,0x3879,0x387A,0x387B,0x387C,0x387D,0x387E,0x387F, + 0x3880,0x3881,0x3882,0x3883,0x3884,0x3885,0x3886,0x3887,0x3888,0x3889,0x388A,0x388B,0x388C,0x388D,0x388E,0x388F, + 0x3890,0x3891,0x3892,0x3893,0x3894,0x3895,0x3896,0x3897,0x3898,0x3899,0x389A,0x389B,0x389C,0x389D,0x389E,0x389F, + 0x38A0,0x38A1,0x38A2,0x38A3,0x38A4,0x38A5,0x38A6,0x38A7,0x38A8,0x38A9,0x38AA,0x38AB,0x38AC,0x38AD,0x38AE,0x38AF, + 0x38B0,0x38B1,0x38B2,0x38B3,0x38B4,0x38B5,0x38B6,0x38B7,0x38B8,0x38B9,0x38BA,0x38BB,0x38BC,0x38BD,0x38BE,0x38BF, + 0x38C0,0x38C1,0x38C2,0x38C3,0x38C4,0x38C5,0x38C6,0x38C7,0x38C8,0x38C9,0x38CA,0x38CB,0x38CC,0x38CD,0x38CE,0x38CF, + 0x38D0,0x38D1,0x38D2,0x38D3,0x38D4,0x38D5,0x38D6,0x38D7,0x38D8,0x38D9,0x38DA,0x38DB,0x38DC,0x38DD,0x38DE,0x38DF, + 0x38E0,0x38E1,0x38E2,0x38E3,0x38E4,0x38E5,0x38E6,0x38E7,0x38E8,0x38E9,0x38EA,0x38EB,0x38EC,0x38ED,0x38EE,0x38EF, + 0x38F0,0x38F1,0x38F2,0x38F3,0x38F4,0x38F5,0x38F6,0x38F7,0x38F8,0x38F9,0x38FA,0x38FB,0x38FC,0x38FD,0x38FE,0x38FF, + 0x3900,0x3901,0x3902,0x3903,0x3904,0x3905,0x3906,0x3907,0x3908,0x3909,0x390A,0x390B,0x390C,0x390D,0x390E,0x390F, + 0x3910,0x3911,0x3912,0x3913,0x3914,0x3915,0x3916,0x3917,0x3918,0x3919,0x391A,0x391B,0x391C,0x391D,0x391E,0x391F, + 0x3920,0x3921,0x3922,0x3923,0x3924,0x3925,0x3926,0x3927,0x3928,0x3929,0x392A,0x392B,0x392C,0x392D,0x392E,0x392F, + 0x3930,0x3931,0x3932,0x3933,0x3934,0x3935,0x3936,0x3937,0x3938,0x3939,0x393A,0x393B,0x393C,0x393D,0x393E,0x393F, + 0x3940,0x3941,0x3942,0x3943,0x3944,0x3945,0x3946,0x3947,0x3948,0x3949,0x394A,0x394B,0x394C,0x394D,0x394E,0x394F, + 0x3950,0x3951,0x3952,0x3953,0x3954,0x3955,0x3956,0x3957,0x3958,0x3959,0x395A,0x395B,0x395C,0x395D,0x395E,0x395F, + 0x3960,0x3961,0x3962,0x3963,0x3964,0x3965,0x3966,0x3967,0x3968,0x3969,0x396A,0x396B,0x396C,0x396D,0x396E,0x396F, + 0x3970,0x3971,0x3972,0x3973,0x3974,0x3975,0x3976,0x3977,0x3978,0x3979,0x397A,0x397B,0x397C,0x397D,0x397E,0x397F, + 0x3980,0x3981,0x3982,0x3983,0x3984,0x3985,0x3986,0x3987,0x3988,0x3989,0x398A,0x398B,0x398C,0x398D,0x398E,0x398F, + 0x3990,0x3991,0x3992,0x3993,0x3994,0x3995,0x3996,0x3997,0x3998,0x3999,0x399A,0x399B,0x399C,0x399D,0x399E,0x399F, + 0x39A0,0x39A1,0x39A2,0x39A3,0x39A4,0x39A5,0x39A6,0x39A7,0x39A8,0x39A9,0x39AA,0x39AB,0x39AC,0x39AD,0x39AE,0x39AF, + 0x39B0,0x39B1,0x39B2,0x39B3,0x39B4,0x39B5,0x39B6,0x39B7,0x39B8,0x39B9,0x39BA,0x39BB,0x39BC,0x39BD,0x39BE,0x39BF, + 0x39C0,0x39C1,0x39C2,0x39C3,0x39C4,0x39C5,0x39C6,0x39C7,0x39C8,0x39C9,0x39CA,0x39CB,0x39CC,0x39CD,0x39CE,0x39CF, + 0x39D0,0x39D1,0x39D2,0x39D3,0x39D4,0x39D5,0x39D6,0x39D7,0x39D8,0x39D9,0x39DA,0x39DB,0x39DC,0x39DD,0x39DE,0x39DF, + 0x39E0,0x39E1,0x39E2,0x39E3,0x39E4,0x39E5,0x39E6,0x39E7,0x39E8,0x39E9,0x39EA,0x39EB,0x39EC,0x39ED,0x39EE,0x39EF, + 0x39F0,0x39F1,0x39F2,0x39F3,0x39F4,0x39F5,0x39F6,0x39F7,0x39F8,0x39F9,0x39FA,0x39FB,0x39FC,0x39FD,0x39FE,0x39FF, + 0x3A00,0x3A01,0x3A02,0x3A03,0x3A04,0x3A05,0x3A06,0x3A07,0x3A08,0x3A09,0x3A0A,0x3A0B,0x3A0C,0x3A0D,0x3A0E,0x3A0F, + 0x3A10,0x3A11,0x3A12,0x3A13,0x3A14,0x3A15,0x3A16,0x3A17,0x3A18,0x3A19,0x3A1A,0x3A1B,0x3A1C,0x3A1D,0x3A1E,0x3A1F, + 0x3A20,0x3A21,0x3A22,0x3A23,0x3A24,0x3A25,0x3A26,0x3A27,0x3A28,0x3A29,0x3A2A,0x3A2B,0x3A2C,0x3A2D,0x3A2E,0x3A2F, + 0x3A30,0x3A31,0x3A32,0x3A33,0x3A34,0x3A35,0x3A36,0x3A37,0x3A38,0x3A39,0x3A3A,0x3A3B,0x3A3C,0x3A3D,0x3A3E,0x3A3F, + 0x3A40,0x3A41,0x3A42,0x3A43,0x3A44,0x3A45,0x3A46,0x3A47,0x3A48,0x3A49,0x3A4A,0x3A4B,0x3A4C,0x3A4D,0x3A4E,0x3A4F, + 0x3A50,0x3A51,0x3A52,0x3A53,0x3A54,0x3A55,0x3A56,0x3A57,0x3A58,0x3A59,0x3A5A,0x3A5B,0x3A5C,0x3A5D,0x3A5E,0x3A5F, + 0x3A60,0x3A61,0x3A62,0x3A63,0x3A64,0x3A65,0x3A66,0x3A67,0x3A68,0x3A69,0x3A6A,0x3A6B,0x3A6C,0x3A6D,0x3A6E,0x3A6F, + 0x3A70,0x3A71,0x3A72,0x3A73,0x3A74,0x3A75,0x3A76,0x3A77,0x3A78,0x3A79,0x3A7A,0x3A7B,0x3A7C,0x3A7D,0x3A7E,0x3A7F, + 0x3A80,0x3A81,0x3A82,0x3A83,0x3A84,0x3A85,0x3A86,0x3A87,0x3A88,0x3A89,0x3A8A,0x3A8B,0x3A8C,0x3A8D,0x3A8E,0x3A8F, + 0x3A90,0x3A91,0x3A92,0x3A93,0x3A94,0x3A95,0x3A96,0x3A97,0x3A98,0x3A99,0x3A9A,0x3A9B,0x3A9C,0x3A9D,0x3A9E,0x3A9F, + 0x3AA0,0x3AA1,0x3AA2,0x3AA3,0x3AA4,0x3AA5,0x3AA6,0x3AA7,0x3AA8,0x3AA9,0x3AAA,0x3AAB,0x3AAC,0x3AAD,0x3AAE,0x3AAF, + 0x3AB0,0x3AB1,0x3AB2,0x3AB3,0x3AB4,0x3AB5,0x3AB6,0x3AB7,0x3AB8,0x3AB9,0x3ABA,0x3ABB,0x3ABC,0x3ABD,0x3ABE,0x3ABF, + 0x3AC0,0x3AC1,0x3AC2,0x3AC3,0x3AC4,0x3AC5,0x3AC6,0x3AC7,0x3AC8,0x3AC9,0x3ACA,0x3ACB,0x3ACC,0x3ACD,0x3ACE,0x3ACF, + 0x3AD0,0x3AD1,0x3AD2,0x3AD3,0x3AD4,0x3AD5,0x3AD6,0x3AD7,0x3AD8,0x3AD9,0x3ADA,0x3ADB,0x3ADC,0x3ADD,0x3ADE,0x3ADF, + 0x3AE0,0x3AE1,0x3AE2,0x3AE3,0x3AE4,0x3AE5,0x3AE6,0x3AE7,0x3AE8,0x3AE9,0x3AEA,0x3AEB,0x3AEC,0x3AED,0x3AEE,0x3AEF, + 0x3AF0,0x3AF1,0x3AF2,0x3AF3,0x3AF4,0x3AF5,0x3AF6,0x3AF7,0x3AF8,0x3AF9,0x3AFA,0x3AFB,0x3AFC,0x3AFD,0x3AFE,0x3AFF, + 0x3B00,0x3B01,0x3B02,0x3B03,0x3B04,0x3B05,0x3B06,0x3B07,0x3B08,0x3B09,0x3B0A,0x3B0B,0x3B0C,0x3B0D,0x3B0E,0x3B0F, + 0x3B10,0x3B11,0x3B12,0x3B13,0x3B14,0x3B15,0x3B16,0x3B17,0x3B18,0x3B19,0x3B1A,0x3B1B,0x3B1C,0x3B1D,0x3B1E,0x3B1F, + 0x3B20,0x3B21,0x3B22,0x3B23,0x3B24,0x3B25,0x3B26,0x3B27,0x3B28,0x3B29,0x3B2A,0x3B2B,0x3B2C,0x3B2D,0x3B2E,0x3B2F, + 0x3B30,0x3B31,0x3B32,0x3B33,0x3B34,0x3B35,0x3B36,0x3B37,0x3B38,0x3B39,0x3B3A,0x3B3B,0x3B3C,0x3B3D,0x3B3E,0x3B3F, + 0x3B40,0x3B41,0x3B42,0x3B43,0x3B44,0x3B45,0x3B46,0x3B47,0x3B48,0x3B49,0x3B4A,0x3B4B,0x3B4C,0x3B4D,0x3B4E,0x3B4F, + 0x3B50,0x3B51,0x3B52,0x3B53,0x3B54,0x3B55,0x3B56,0x3B57,0x3B58,0x3B59,0x3B5A,0x3B5B,0x3B5C,0x3B5D,0x3B5E,0x3B5F, + 0x3B60,0x3B61,0x3B62,0x3B63,0x3B64,0x3B65,0x3B66,0x3B67,0x3B68,0x3B69,0x3B6A,0x3B6B,0x3B6C,0x3B6D,0x3B6E,0x3B6F, + 0x3B70,0x3B71,0x3B72,0x3B73,0x3B74,0x3B75,0x3B76,0x3B77,0x3B78,0x3B79,0x3B7A,0x3B7B,0x3B7C,0x3B7D,0x3B7E,0x3B7F, + 0x3B80,0x3B81,0x3B82,0x3B83,0x3B84,0x3B85,0x3B86,0x3B87,0x3B88,0x3B89,0x3B8A,0x3B8B,0x3B8C,0x3B8D,0x3B8E,0x3B8F, + 0x3B90,0x3B91,0x3B92,0x3B93,0x3B94,0x3B95,0x3B96,0x3B97,0x3B98,0x3B99,0x3B9A,0x3B9B,0x3B9C,0x3B9D,0x3B9E,0x3B9F, + 0x3BA0,0x3BA1,0x3BA2,0x3BA3,0x3BA4,0x3BA5,0x3BA6,0x3BA7,0x3BA8,0x3BA9,0x3BAA,0x3BAB,0x3BAC,0x3BAD,0x3BAE,0x3BAF, + 0x3BB0,0x3BB1,0x3BB2,0x3BB3,0x3BB4,0x3BB5,0x3BB6,0x3BB7,0x3BB8,0x3BB9,0x3BBA,0x3BBB,0x3BBC,0x3BBD,0x3BBE,0x3BBF, + 0x3BC0,0x3BC1,0x3BC2,0x3BC3,0x3BC4,0x3BC5,0x3BC6,0x3BC7,0x3BC8,0x3BC9,0x3BCA,0x3BCB,0x3BCC,0x3BCD,0x3BCE,0x3BCF, + 0x3BD0,0x3BD1,0x3BD2,0x3BD3,0x3BD4,0x3BD5,0x3BD6,0x3BD7,0x3BD8,0x3BD9,0x3BDA,0x3BDB,0x3BDC,0x3BDD,0x3BDE,0x3BDF, + 0x3BE0,0x3BE1,0x3BE2,0x3BE3,0x3BE4,0x3BE5,0x3BE6,0x3BE7,0x3BE8,0x3BE9,0x3BEA,0x3BEB,0x3BEC,0x3BED,0x3BEE,0x3BEF, + 0x3BF0,0x3BF1,0x3BF2,0x3BF3,0x3BF4,0x3BF5,0x3BF6,0x3BF7,0x3BF8,0x3BF9,0x3BFA,0x3BFB,0x3BFC,0x3BFD,0x3BFE,0x3BFF, + 0x3C00,0x3C01,0x3C02,0x3C03,0x3C04,0x3C05,0x3C06,0x3C07,0x3C08,0x3C09,0x3C0A,0x3C0B,0x3C0C,0x3C0D,0x3C0E,0x3C0F, + 0x3C10,0x3C11,0x3C12,0x3C13,0x3C14,0x3C15,0x3C16,0x3C17,0x3C18,0x3C19,0x3C1A,0x3C1B,0x3C1C,0x3C1D,0x3C1E,0x3C1F, + 0x3C20,0x3C21,0x3C22,0x3C23,0x3C24,0x3C25,0x3C26,0x3C27,0x3C28,0x3C29,0x3C2A,0x3C2B,0x3C2C,0x3C2D,0x3C2E,0x3C2F, + 0x3C30,0x3C31,0x3C32,0x3C33,0x3C34,0x3C35,0x3C36,0x3C37,0x3C38,0x3C39,0x3C3A,0x3C3B,0x3C3C,0x3C3D,0x3C3E,0x3C3F, + 0x3C40,0x3C41,0x3C42,0x3C43,0x3C44,0x3C45,0x3C46,0x3C47,0x3C48,0x3C49,0x3C4A,0x3C4B,0x3C4C,0x3C4D,0x3C4E,0x3C4F, + 0x3C50,0x3C51,0x3C52,0x3C53,0x3C54,0x3C55,0x3C56,0x3C57,0x3C58,0x3C59,0x3C5A,0x3C5B,0x3C5C,0x3C5D,0x3C5E,0x3C5F, + 0x3C60,0x3C61,0x3C62,0x3C63,0x3C64,0x3C65,0x3C66,0x3C67,0x3C68,0x3C69,0x3C6A,0x3C6B,0x3C6C,0x3C6D,0x3C6E,0x3C6F, + 0x3C70,0x3C71,0x3C72,0x3C73,0x3C74,0x3C75,0x3C76,0x3C77,0x3C78,0x3C79,0x3C7A,0x3C7B,0x3C7C,0x3C7D,0x3C7E,0x3C7F, + 0x3C80,0x3C81,0x3C82,0x3C83,0x3C84,0x3C85,0x3C86,0x3C87,0x3C88,0x3C89,0x3C8A,0x3C8B,0x3C8C,0x3C8D,0x3C8E,0x3C8F, + 0x3C90,0x3C91,0x3C92,0x3C93,0x3C94,0x3C95,0x3C96,0x3C97,0x3C98,0x3C99,0x3C9A,0x3C9B,0x3C9C,0x3C9D,0x3C9E,0x3C9F, + 0x3CA0,0x3CA1,0x3CA2,0x3CA3,0x3CA4,0x3CA5,0x3CA6,0x3CA7,0x3CA8,0x3CA9,0x3CAA,0x3CAB,0x3CAC,0x3CAD,0x3CAE,0x3CAF, + 0x3CB0,0x3CB1,0x3CB2,0x3CB3,0x3CB4,0x3CB5,0x3CB6,0x3CB7,0x3CB8,0x3CB9,0x3CBA,0x3CBB,0x3CBC,0x3CBD,0x3CBE,0x3CBF, + 0x3CC0,0x3CC1,0x3CC2,0x3CC3,0x3CC4,0x3CC5,0x3CC6,0x3CC7,0x3CC8,0x3CC9,0x3CCA,0x3CCB,0x3CCC,0x3CCD,0x3CCE,0x3CCF, + 0x3CD0,0x3CD1,0x3CD2,0x3CD3,0x3CD4,0x3CD5,0x3CD6,0x3CD7,0x3CD8,0x3CD9,0x3CDA,0x3CDB,0x3CDC,0x3CDD,0x3CDE,0x3CDF, + 0x3CE0,0x3CE1,0x3CE2,0x3CE3,0x3CE4,0x3CE5,0x3CE6,0x3CE7,0x3CE8,0x3CE9,0x3CEA,0x3CEB,0x3CEC,0x3CED,0x3CEE,0x3CEF, + 0x3CF0,0x3CF1,0x3CF2,0x3CF3,0x3CF4,0x3CF5,0x3CF6,0x3CF7,0x3CF8,0x3CF9,0x3CFA,0x3CFB,0x3CFC,0x3CFD,0x3CFE,0x3CFF, + 0x3D00,0x3D01,0x3D02,0x3D03,0x3D04,0x3D05,0x3D06,0x3D07,0x3D08,0x3D09,0x3D0A,0x3D0B,0x3D0C,0x3D0D,0x3D0E,0x3D0F, + 0x3D10,0x3D11,0x3D12,0x3D13,0x3D14,0x3D15,0x3D16,0x3D17,0x3D18,0x3D19,0x3D1A,0x3D1B,0x3D1C,0x3D1D,0x3D1E,0x3D1F, + 0x3D20,0x3D21,0x3D22,0x3D23,0x3D24,0x3D25,0x3D26,0x3D27,0x3D28,0x3D29,0x3D2A,0x3D2B,0x3D2C,0x3D2D,0x3D2E,0x3D2F, + 0x3D30,0x3D31,0x3D32,0x3D33,0x3D34,0x3D35,0x3D36,0x3D37,0x3D38,0x3D39,0x3D3A,0x3D3B,0x3D3C,0x3D3D,0x3D3E,0x3D3F, + 0x3D40,0x3D41,0x3D42,0x3D43,0x3D44,0x3D45,0x3D46,0x3D47,0x3D48,0x3D49,0x3D4A,0x3D4B,0x3D4C,0x3D4D,0x3D4E,0x3D4F, + 0x3D50,0x3D51,0x3D52,0x3D53,0x3D54,0x3D55,0x3D56,0x3D57,0x3D58,0x3D59,0x3D5A,0x3D5B,0x3D5C,0x3D5D,0x3D5E,0x3D5F, + 0x3D60,0x3D61,0x3D62,0x3D63,0x3D64,0x3D65,0x3D66,0x3D67,0x3D68,0x3D69,0x3D6A,0x3D6B,0x3D6C,0x3D6D,0x3D6E,0x3D6F, + 0x3D70,0x3D71,0x3D72,0x3D73,0x3D74,0x3D75,0x3D76,0x3D77,0x3D78,0x3D79,0x3D7A,0x3D7B,0x3D7C,0x3D7D,0x3D7E,0x3D7F, + 0x3D80,0x3D81,0x3D82,0x3D83,0x3D84,0x3D85,0x3D86,0x3D87,0x3D88,0x3D89,0x3D8A,0x3D8B,0x3D8C,0x3D8D,0x3D8E,0x3D8F, + 0x3D90,0x3D91,0x3D92,0x3D93,0x3D94,0x3D95,0x3D96,0x3D97,0x3D98,0x3D99,0x3D9A,0x3D9B,0x3D9C,0x3D9D,0x3D9E,0x3D9F, + 0x3DA0,0x3DA1,0x3DA2,0x3DA3,0x3DA4,0x3DA5,0x3DA6,0x3DA7,0x3DA8,0x3DA9,0x3DAA,0x3DAB,0x3DAC,0x3DAD,0x3DAE,0x3DAF, + 0x3DB0,0x3DB1,0x3DB2,0x3DB3,0x3DB4,0x3DB5,0x3DB6,0x3DB7,0x3DB8,0x3DB9,0x3DBA,0x3DBB,0x3DBC,0x3DBD,0x3DBE,0x3DBF, + 0x3DC0,0x3DC1,0x3DC2,0x3DC3,0x3DC4,0x3DC5,0x3DC6,0x3DC7,0x3DC8,0x3DC9,0x3DCA,0x3DCB,0x3DCC,0x3DCD,0x3DCE,0x3DCF, + 0x3DD0,0x3DD1,0x3DD2,0x3DD3,0x3DD4,0x3DD5,0x3DD6,0x3DD7,0x3DD8,0x3DD9,0x3DDA,0x3DDB,0x3DDC,0x3DDD,0x3DDE,0x3DDF, + 0x3DE0,0x3DE1,0x3DE2,0x3DE3,0x3DE4,0x3DE5,0x3DE6,0x3DE7,0x3DE8,0x3DE9,0x3DEA,0x3DEB,0x3DEC,0x3DED,0x3DEE,0x3DEF, + 0x3DF0,0x3DF1,0x3DF2,0x3DF3,0x3DF4,0x3DF5,0x3DF6,0x3DF7,0x3DF8,0x3DF9,0x3DFA,0x3DFB,0x3DFC,0x3DFD,0x3DFE,0x3DFF, + 0x3E00,0x3E01,0x3E02,0x3E03,0x3E04,0x3E05,0x3E06,0x3E07,0x3E08,0x3E09,0x3E0A,0x3E0B,0x3E0C,0x3E0D,0x3E0E,0x3E0F, + 0x3E10,0x3E11,0x3E12,0x3E13,0x3E14,0x3E15,0x3E16,0x3E17,0x3E18,0x3E19,0x3E1A,0x3E1B,0x3E1C,0x3E1D,0x3E1E,0x3E1F, + 0x3E20,0x3E21,0x3E22,0x3E23,0x3E24,0x3E25,0x3E26,0x3E27,0x3E28,0x3E29,0x3E2A,0x3E2B,0x3E2C,0x3E2D,0x3E2E,0x3E2F, + 0x3E30,0x3E31,0x3E32,0x3E33,0x3E34,0x3E35,0x3E36,0x3E37,0x3E38,0x3E39,0x3E3A,0x3E3B,0x3E3C,0x3E3D,0x3E3E,0x3E3F, + 0x3E40,0x3E41,0x3E42,0x3E43,0x3E44,0x3E45,0x3E46,0x3E47,0x3E48,0x3E49,0x3E4A,0x3E4B,0x3E4C,0x3E4D,0x3E4E,0x3E4F, + 0x3E50,0x3E51,0x3E52,0x3E53,0x3E54,0x3E55,0x3E56,0x3E57,0x3E58,0x3E59,0x3E5A,0x3E5B,0x3E5C,0x3E5D,0x3E5E,0x3E5F, + 0x3E60,0x3E61,0x3E62,0x3E63,0x3E64,0x3E65,0x3E66,0x3E67,0x3E68,0x3E69,0x3E6A,0x3E6B,0x3E6C,0x3E6D,0x3E6E,0x3E6F, + 0x3E70,0x3E71,0x3E72,0x3E73,0x3E74,0x3E75,0x3E76,0x3E77,0x3E78,0x3E79,0x3E7A,0x3E7B,0x3E7C,0x3E7D,0x3E7E,0x3E7F, + 0x3E80,0x3E81,0x3E82,0x3E83,0x3E84,0x3E85,0x3E86,0x3E87,0x3E88,0x3E89,0x3E8A,0x3E8B,0x3E8C,0x3E8D,0x3E8E,0x3E8F, + 0x3E90,0x3E91,0x3E92,0x3E93,0x3E94,0x3E95,0x3E96,0x3E97,0x3E98,0x3E99,0x3E9A,0x3E9B,0x3E9C,0x3E9D,0x3E9E,0x3E9F, + 0x3EA0,0x3EA1,0x3EA2,0x3EA3,0x3EA4,0x3EA5,0x3EA6,0x3EA7,0x3EA8,0x3EA9,0x3EAA,0x3EAB,0x3EAC,0x3EAD,0x3EAE,0x3EAF, + 0x3EB0,0x3EB1,0x3EB2,0x3EB3,0x3EB4,0x3EB5,0x3EB6,0x3EB7,0x3EB8,0x3EB9,0x3EBA,0x3EBB,0x3EBC,0x3EBD,0x3EBE,0x3EBF, + 0x3EC0,0x3EC1,0x3EC2,0x3EC3,0x3EC4,0x3EC5,0x3EC6,0x3EC7,0x3EC8,0x3EC9,0x3ECA,0x3ECB,0x3ECC,0x3ECD,0x3ECE,0x3ECF, + 0x3ED0,0x3ED1,0x3ED2,0x3ED3,0x3ED4,0x3ED5,0x3ED6,0x3ED7,0x3ED8,0x3ED9,0x3EDA,0x3EDB,0x3EDC,0x3EDD,0x3EDE,0x3EDF, + 0x3EE0,0x3EE1,0x3EE2,0x3EE3,0x3EE4,0x3EE5,0x3EE6,0x3EE7,0x3EE8,0x3EE9,0x3EEA,0x3EEB,0x3EEC,0x3EED,0x3EEE,0x3EEF, + 0x3EF0,0x3EF1,0x3EF2,0x3EF3,0x3EF4,0x3EF5,0x3EF6,0x3EF7,0x3EF8,0x3EF9,0x3EFA,0x3EFB,0x3EFC,0x3EFD,0x3EFE,0x3EFF, + 0x3F00,0x3F01,0x3F02,0x3F03,0x3F04,0x3F05,0x3F06,0x3F07,0x3F08,0x3F09,0x3F0A,0x3F0B,0x3F0C,0x3F0D,0x3F0E,0x3F0F, + 0x3F10,0x3F11,0x3F12,0x3F13,0x3F14,0x3F15,0x3F16,0x3F17,0x3F18,0x3F19,0x3F1A,0x3F1B,0x3F1C,0x3F1D,0x3F1E,0x3F1F, + 0x3F20,0x3F21,0x3F22,0x3F23,0x3F24,0x3F25,0x3F26,0x3F27,0x3F28,0x3F29,0x3F2A,0x3F2B,0x3F2C,0x3F2D,0x3F2E,0x3F2F, + 0x3F30,0x3F31,0x3F32,0x3F33,0x3F34,0x3F35,0x3F36,0x3F37,0x3F38,0x3F39,0x3F3A,0x3F3B,0x3F3C,0x3F3D,0x3F3E,0x3F3F, + 0x3F40,0x3F41,0x3F42,0x3F43,0x3F44,0x3F45,0x3F46,0x3F47,0x3F48,0x3F49,0x3F4A,0x3F4B,0x3F4C,0x3F4D,0x3F4E,0x3F4F, + 0x3F50,0x3F51,0x3F52,0x3F53,0x3F54,0x3F55,0x3F56,0x3F57,0x3F58,0x3F59,0x3F5A,0x3F5B,0x3F5C,0x3F5D,0x3F5E,0x3F5F, + 0x3F60,0x3F61,0x3F62,0x3F63,0x3F64,0x3F65,0x3F66,0x3F67,0x3F68,0x3F69,0x3F6A,0x3F6B,0x3F6C,0x3F6D,0x3F6E,0x3F6F, + 0x3F70,0x3F71,0x3F72,0x3F73,0x3F74,0x3F75,0x3F76,0x3F77,0x3F78,0x3F79,0x3F7A,0x3F7B,0x3F7C,0x3F7D,0x3F7E,0x3F7F, + 0x3F80,0x3F81,0x3F82,0x3F83,0x3F84,0x3F85,0x3F86,0x3F87,0x3F88,0x3F89,0x3F8A,0x3F8B,0x3F8C,0x3F8D,0x3F8E,0x3F8F, + 0x3F90,0x3F91,0x3F92,0x3F93,0x3F94,0x3F95,0x3F96,0x3F97,0x3F98,0x3F99,0x3F9A,0x3F9B,0x3F9C,0x3F9D,0x3F9E,0x3F9F, + 0x3FA0,0x3FA1,0x3FA2,0x3FA3,0x3FA4,0x3FA5,0x3FA6,0x3FA7,0x3FA8,0x3FA9,0x3FAA,0x3FAB,0x3FAC,0x3FAD,0x3FAE,0x3FAF, + 0x3FB0,0x3FB1,0x3FB2,0x3FB3,0x3FB4,0x3FB5,0x3FB6,0x3FB7,0x3FB8,0x3FB9,0x3FBA,0x3FBB,0x3FBC,0x3FBD,0x3FBE,0x3FBF, + 0x3FC0,0x3FC1,0x3FC2,0x3FC3,0x3FC4,0x3FC5,0x3FC6,0x3FC7,0x3FC8,0x3FC9,0x3FCA,0x3FCB,0x3FCC,0x3FCD,0x3FCE,0x3FCF, + 0x3FD0,0x3FD1,0x3FD2,0x3FD3,0x3FD4,0x3FD5,0x3FD6,0x3FD7,0x3FD8,0x3FD9,0x3FDA,0x3FDB,0x3FDC,0x3FDD,0x3FDE,0x3FDF, + 0x3FE0,0x3FE1,0x3FE2,0x3FE3,0x3FE4,0x3FE5,0x3FE6,0x3FE7,0x3FE8,0x3FE9,0x3FEA,0x3FEB,0x3FEC,0x3FED,0x3FEE,0x3FEF, + 0x3FF0,0x3FF1,0x3FF2,0x3FF3,0x3FF4,0x3FF5,0x3FF6,0x3FF7,0x3FF8,0x3FF9,0x3FFA,0x3FFB,0x3FFC,0x3FFD,0x3FFE,0x3FFF, + 0x4000,0x4001,0x4002,0x4003,0x4004,0x4005,0x4006,0x4007,0x4008,0x4009,0x400A,0x400B,0x400C,0x400D,0x400E,0x400F, + 0x4010,0x4011,0x4012,0x4013,0x4014,0x4015,0x4016,0x4017,0x4018,0x4019,0x401A,0x401B,0x401C,0x401D,0x401E,0x401F, + 0x4020,0x4021,0x4022,0x4023,0x4024,0x4025,0x4026,0x4027,0x4028,0x4029,0x402A,0x402B,0x402C,0x402D,0x402E,0x402F, + 0x4030,0x4031,0x4032,0x4033,0x4034,0x4035,0x4036,0x4037,0x4038,0x4039,0x403A,0x403B,0x403C,0x403D,0x403E,0x403F, + 0x4040,0x4041,0x4042,0x4043,0x4044,0x4045,0x4046,0x4047,0x4048,0x4049,0x404A,0x404B,0x404C,0x404D,0x404E,0x404F, + 0x4050,0x4051,0x4052,0x4053,0x4054,0x4055,0x4056,0x4057,0x4058,0x4059,0x405A,0x405B,0x405C,0x405D,0x405E,0x405F, + 0x4060,0x4061,0x4062,0x4063,0x4064,0x4065,0x4066,0x4067,0x4068,0x4069,0x406A,0x406B,0x406C,0x406D,0x406E,0x406F, + 0x4070,0x4071,0x4072,0x4073,0x4074,0x4075,0x4076,0x4077,0x4078,0x4079,0x407A,0x407B,0x407C,0x407D,0x407E,0x407F, + 0x4080,0x4081,0x4082,0x4083,0x4084,0x4085,0x4086,0x4087,0x4088,0x4089,0x408A,0x408B,0x408C,0x408D,0x408E,0x408F, + 0x4090,0x4091,0x4092,0x4093,0x4094,0x4095,0x4096,0x4097,0x4098,0x4099,0x409A,0x409B,0x409C,0x409D,0x409E,0x409F, + 0x40A0,0x40A1,0x40A2,0x40A3,0x40A4,0x40A5,0x40A6,0x40A7,0x40A8,0x40A9,0x40AA,0x40AB,0x40AC,0x40AD,0x40AE,0x40AF, + 0x40B0,0x40B1,0x40B2,0x40B3,0x40B4,0x40B5,0x40B6,0x40B7,0x40B8,0x40B9,0x40BA,0x40BB,0x40BC,0x40BD,0x40BE,0x40BF, + 0x40C0,0x40C1,0x40C2,0x40C3,0x40C4,0x40C5,0x40C6,0x40C7,0x40C8,0x40C9,0x40CA,0x40CB,0x40CC,0x40CD,0x40CE,0x40CF, + 0x40D0,0x40D1,0x40D2,0x40D3,0x40D4,0x40D5,0x40D6,0x40D7,0x40D8,0x40D9,0x40DA,0x40DB,0x40DC,0x40DD,0x40DE,0x40DF, + 0x40E0,0x40E1,0x40E2,0x40E3,0x40E4,0x40E5,0x40E6,0x40E7,0x40E8,0x40E9,0x40EA,0x40EB,0x40EC,0x40ED,0x40EE,0x40EF, + 0x40F0,0x40F1,0x40F2,0x40F3,0x40F4,0x40F5,0x40F6,0x40F7,0x40F8,0x40F9,0x40FA,0x40FB,0x40FC,0x40FD,0x40FE,0x40FF, + 0x4100,0x4101,0x4102,0x4103,0x4104,0x4105,0x4106,0x4107,0x4108,0x4109,0x410A,0x410B,0x410C,0x410D,0x410E,0x410F, + 0x4110,0x4111,0x4112,0x4113,0x4114,0x4115,0x4116,0x4117,0x4118,0x4119,0x411A,0x411B,0x411C,0x411D,0x411E,0x411F, + 0x4120,0x4121,0x4122,0x4123,0x4124,0x4125,0x4126,0x4127,0x4128,0x4129,0x412A,0x412B,0x412C,0x412D,0x412E,0x412F, + 0x4130,0x4131,0x4132,0x4133,0x4134,0x4135,0x4136,0x4137,0x4138,0x4139,0x413A,0x413B,0x413C,0x413D,0x413E,0x413F, + 0x4140,0x4141,0x4142,0x4143,0x4144,0x4145,0x4146,0x4147,0x4148,0x4149,0x414A,0x414B,0x414C,0x414D,0x414E,0x414F, + 0x4150,0x4151,0x4152,0x4153,0x4154,0x4155,0x4156,0x4157,0x4158,0x4159,0x415A,0x415B,0x415C,0x415D,0x415E,0x415F, + 0x4160,0x4161,0x4162,0x4163,0x4164,0x4165,0x4166,0x4167,0x4168,0x4169,0x416A,0x416B,0x416C,0x416D,0x416E,0x416F, + 0x4170,0x4171,0x4172,0x4173,0x4174,0x4175,0x4176,0x4177,0x4178,0x4179,0x417A,0x417B,0x417C,0x417D,0x417E,0x417F, + 0x4180,0x4181,0x4182,0x4183,0x4184,0x4185,0x4186,0x4187,0x4188,0x4189,0x418A,0x418B,0x418C,0x418D,0x418E,0x418F, + 0x4190,0x4191,0x4192,0x4193,0x4194,0x4195,0x4196,0x4197,0x4198,0x4199,0x419A,0x419B,0x419C,0x419D,0x419E,0x419F, + 0x41A0,0x41A1,0x41A2,0x41A3,0x41A4,0x41A5,0x41A6,0x41A7,0x41A8,0x41A9,0x41AA,0x41AB,0x41AC,0x41AD,0x41AE,0x41AF, + 0x41B0,0x41B1,0x41B2,0x41B3,0x41B4,0x41B5,0x41B6,0x41B7,0x41B8,0x41B9,0x41BA,0x41BB,0x41BC,0x41BD,0x41BE,0x41BF, + 0x41C0,0x41C1,0x41C2,0x41C3,0x41C4,0x41C5,0x41C6,0x41C7,0x41C8,0x41C9,0x41CA,0x41CB,0x41CC,0x41CD,0x41CE,0x41CF, + 0x41D0,0x41D1,0x41D2,0x41D3,0x41D4,0x41D5,0x41D6,0x41D7,0x41D8,0x41D9,0x41DA,0x41DB,0x41DC,0x41DD,0x41DE,0x41DF, + 0x41E0,0x41E1,0x41E2,0x41E3,0x41E4,0x41E5,0x41E6,0x41E7,0x41E8,0x41E9,0x41EA,0x41EB,0x41EC,0x41ED,0x41EE,0x41EF, + 0x41F0,0x41F1,0x41F2,0x41F3,0x41F4,0x41F5,0x41F6,0x41F7,0x41F8,0x41F9,0x41FA,0x41FB,0x41FC,0x41FD,0x41FE,0x41FF, + 0x4200,0x4201,0x4202,0x4203,0x4204,0x4205,0x4206,0x4207,0x4208,0x4209,0x420A,0x420B,0x420C,0x420D,0x420E,0x420F, + 0x4210,0x4211,0x4212,0x4213,0x4214,0x4215,0x4216,0x4217,0x4218,0x4219,0x421A,0x421B,0x421C,0x421D,0x421E,0x421F, + 0x4220,0x4221,0x4222,0x4223,0x4224,0x4225,0x4226,0x4227,0x4228,0x4229,0x422A,0x422B,0x422C,0x422D,0x422E,0x422F, + 0x4230,0x4231,0x4232,0x4233,0x4234,0x4235,0x4236,0x4237,0x4238,0x4239,0x423A,0x423B,0x423C,0x423D,0x423E,0x423F, + 0x4240,0x4241,0x4242,0x4243,0x4244,0x4245,0x4246,0x4247,0x4248,0x4249,0x424A,0x424B,0x424C,0x424D,0x424E,0x424F, + 0x4250,0x4251,0x4252,0x4253,0x4254,0x4255,0x4256,0x4257,0x4258,0x4259,0x425A,0x425B,0x425C,0x425D,0x425E,0x425F, + 0x4260,0x4261,0x4262,0x4263,0x4264,0x4265,0x4266,0x4267,0x4268,0x4269,0x426A,0x426B,0x426C,0x426D,0x426E,0x426F, + 0x4270,0x4271,0x4272,0x4273,0x4274,0x4275,0x4276,0x4277,0x4278,0x4279,0x427A,0x427B,0x427C,0x427D,0x427E,0x427F, + 0x4280,0x4281,0x4282,0x4283,0x4284,0x4285,0x4286,0x4287,0x4288,0x4289,0x428A,0x428B,0x428C,0x428D,0x428E,0x428F, + 0x4290,0x4291,0x4292,0x4293,0x4294,0x4295,0x4296,0x4297,0x4298,0x4299,0x429A,0x429B,0x429C,0x429D,0x429E,0x429F, + 0x42A0,0x42A1,0x42A2,0x42A3,0x42A4,0x42A5,0x42A6,0x42A7,0x42A8,0x42A9,0x42AA,0x42AB,0x42AC,0x42AD,0x42AE,0x42AF, + 0x42B0,0x42B1,0x42B2,0x42B3,0x42B4,0x42B5,0x42B6,0x42B7,0x42B8,0x42B9,0x42BA,0x42BB,0x42BC,0x42BD,0x42BE,0x42BF, + 0x42C0,0x42C1,0x42C2,0x42C3,0x42C4,0x42C5,0x42C6,0x42C7,0x42C8,0x42C9,0x42CA,0x42CB,0x42CC,0x42CD,0x42CE,0x42CF, + 0x42D0,0x42D1,0x42D2,0x42D3,0x42D4,0x42D5,0x42D6,0x42D7,0x42D8,0x42D9,0x42DA,0x42DB,0x42DC,0x42DD,0x42DE,0x42DF, + 0x42E0,0x42E1,0x42E2,0x42E3,0x42E4,0x42E5,0x42E6,0x42E7,0x42E8,0x42E9,0x42EA,0x42EB,0x42EC,0x42ED,0x42EE,0x42EF, + 0x42F0,0x42F1,0x42F2,0x42F3,0x42F4,0x42F5,0x42F6,0x42F7,0x42F8,0x42F9,0x42FA,0x42FB,0x42FC,0x42FD,0x42FE,0x42FF, + 0x4300,0x4301,0x4302,0x4303,0x4304,0x4305,0x4306,0x4307,0x4308,0x4309,0x430A,0x430B,0x430C,0x430D,0x430E,0x430F, + 0x4310,0x4311,0x4312,0x4313,0x4314,0x4315,0x4316,0x4317,0x4318,0x4319,0x431A,0x431B,0x431C,0x431D,0x431E,0x431F, + 0x4320,0x4321,0x4322,0x4323,0x4324,0x4325,0x4326,0x4327,0x4328,0x4329,0x432A,0x432B,0x432C,0x432D,0x432E,0x432F, + 0x4330,0x4331,0x4332,0x4333,0x4334,0x4335,0x4336,0x4337,0x4338,0x4339,0x433A,0x433B,0x433C,0x433D,0x433E,0x433F, + 0x4340,0x4341,0x4342,0x4343,0x4344,0x4345,0x4346,0x4347,0x4348,0x4349,0x434A,0x434B,0x434C,0x434D,0x434E,0x434F, + 0x4350,0x4351,0x4352,0x4353,0x4354,0x4355,0x4356,0x4357,0x4358,0x4359,0x435A,0x435B,0x435C,0x435D,0x435E,0x435F, + 0x4360,0x4361,0x4362,0x4363,0x4364,0x4365,0x4366,0x4367,0x4368,0x4369,0x436A,0x436B,0x436C,0x436D,0x436E,0x436F, + 0x4370,0x4371,0x4372,0x4373,0x4374,0x4375,0x4376,0x4377,0x4378,0x4379,0x437A,0x437B,0x437C,0x437D,0x437E,0x437F, + 0x4380,0x4381,0x4382,0x4383,0x4384,0x4385,0x4386,0x4387,0x4388,0x4389,0x438A,0x438B,0x438C,0x438D,0x438E,0x438F, + 0x4390,0x4391,0x4392,0x4393,0x4394,0x4395,0x4396,0x4397,0x4398,0x4399,0x439A,0x439B,0x439C,0x439D,0x439E,0x439F, + 0x43A0,0x43A1,0x43A2,0x43A3,0x43A4,0x43A5,0x43A6,0x43A7,0x43A8,0x43A9,0x43AA,0x43AB,0x43AC,0x43AD,0x43AE,0x43AF, + 0x43B0,0x43B1,0x43B2,0x43B3,0x43B4,0x43B5,0x43B6,0x43B7,0x43B8,0x43B9,0x43BA,0x43BB,0x43BC,0x43BD,0x43BE,0x43BF, + 0x43C0,0x43C1,0x43C2,0x43C3,0x43C4,0x43C5,0x43C6,0x43C7,0x43C8,0x43C9,0x43CA,0x43CB,0x43CC,0x43CD,0x43CE,0x43CF, + 0x43D0,0x43D1,0x43D2,0x43D3,0x43D4,0x43D5,0x43D6,0x43D7,0x43D8,0x43D9,0x43DA,0x43DB,0x43DC,0x43DD,0x43DE,0x43DF, + 0x43E0,0x43E1,0x43E2,0x43E3,0x43E4,0x43E5,0x43E6,0x43E7,0x43E8,0x43E9,0x43EA,0x43EB,0x43EC,0x43ED,0x43EE,0x43EF, + 0x43F0,0x43F1,0x43F2,0x43F3,0x43F4,0x43F5,0x43F6,0x43F7,0x43F8,0x43F9,0x43FA,0x43FB,0x43FC,0x43FD,0x43FE,0x43FF, + 0x4400,0x4401,0x4402,0x4403,0x4404,0x4405,0x4406,0x4407,0x4408,0x4409,0x440A,0x440B,0x440C,0x440D,0x440E,0x440F, + 0x4410,0x4411,0x4412,0x4413,0x4414,0x4415,0x4416,0x4417,0x4418,0x4419,0x441A,0x441B,0x441C,0x441D,0x441E,0x441F, + 0x4420,0x4421,0x4422,0x4423,0x4424,0x4425,0x4426,0x4427,0x4428,0x4429,0x442A,0x442B,0x442C,0x442D,0x442E,0x442F, + 0x4430,0x4431,0x4432,0x4433,0x4434,0x4435,0x4436,0x4437,0x4438,0x4439,0x443A,0x443B,0x443C,0x443D,0x443E,0x443F, + 0x4440,0x4441,0x4442,0x4443,0x4444,0x4445,0x4446,0x4447,0x4448,0x4449,0x444A,0x444B,0x444C,0x444D,0x444E,0x444F, + 0x4450,0x4451,0x4452,0x4453,0x4454,0x4455,0x4456,0x4457,0x4458,0x4459,0x445A,0x445B,0x445C,0x445D,0x445E,0x445F, + 0x4460,0x4461,0x4462,0x4463,0x4464,0x4465,0x4466,0x4467,0x4468,0x4469,0x446A,0x446B,0x446C,0x446D,0x446E,0x446F, + 0x4470,0x4471,0x4472,0x4473,0x4474,0x4475,0x4476,0x4477,0x4478,0x4479,0x447A,0x447B,0x447C,0x447D,0x447E,0x447F, + 0x4480,0x4481,0x4482,0x4483,0x4484,0x4485,0x4486,0x4487,0x4488,0x4489,0x448A,0x448B,0x448C,0x448D,0x448E,0x448F, + 0x4490,0x4491,0x4492,0x4493,0x4494,0x4495,0x4496,0x4497,0x4498,0x4499,0x449A,0x449B,0x449C,0x449D,0x449E,0x449F, + 0x44A0,0x44A1,0x44A2,0x44A3,0x44A4,0x44A5,0x44A6,0x44A7,0x44A8,0x44A9,0x44AA,0x44AB,0x44AC,0x44AD,0x44AE,0x44AF, + 0x44B0,0x44B1,0x44B2,0x44B3,0x44B4,0x44B5,0x44B6,0x44B7,0x44B8,0x44B9,0x44BA,0x44BB,0x44BC,0x44BD,0x44BE,0x44BF, + 0x44C0,0x44C1,0x44C2,0x44C3,0x44C4,0x44C5,0x44C6,0x44C7,0x44C8,0x44C9,0x44CA,0x44CB,0x44CC,0x44CD,0x44CE,0x44CF, + 0x44D0,0x44D1,0x44D2,0x44D3,0x44D4,0x44D5,0x44D6,0x44D7,0x44D8,0x44D9,0x44DA,0x44DB,0x44DC,0x44DD,0x44DE,0x44DF, + 0x44E0,0x44E1,0x44E2,0x44E3,0x44E4,0x44E5,0x44E6,0x44E7,0x44E8,0x44E9,0x44EA,0x44EB,0x44EC,0x44ED,0x44EE,0x44EF, + 0x44F0,0x44F1,0x44F2,0x44F3,0x44F4,0x44F5,0x44F6,0x44F7,0x44F8,0x44F9,0x44FA,0x44FB,0x44FC,0x44FD,0x44FE,0x44FF, + 0x4500,0x4501,0x4502,0x4503,0x4504,0x4505,0x4506,0x4507,0x4508,0x4509,0x450A,0x450B,0x450C,0x450D,0x450E,0x450F, + 0x4510,0x4511,0x4512,0x4513,0x4514,0x4515,0x4516,0x4517,0x4518,0x4519,0x451A,0x451B,0x451C,0x451D,0x451E,0x451F, + 0x4520,0x4521,0x4522,0x4523,0x4524,0x4525,0x4526,0x4527,0x4528,0x4529,0x452A,0x452B,0x452C,0x452D,0x452E,0x452F, + 0x4530,0x4531,0x4532,0x4533,0x4534,0x4535,0x4536,0x4537,0x4538,0x4539,0x453A,0x453B,0x453C,0x453D,0x453E,0x453F, + 0x4540,0x4541,0x4542,0x4543,0x4544,0x4545,0x4546,0x4547,0x4548,0x4549,0x454A,0x454B,0x454C,0x454D,0x454E,0x454F, + 0x4550,0x4551,0x4552,0x4553,0x4554,0x4555,0x4556,0x4557,0x4558,0x4559,0x455A,0x455B,0x455C,0x455D,0x455E,0x455F, + 0x4560,0x4561,0x4562,0x4563,0x4564,0x4565,0x4566,0x4567,0x4568,0x4569,0x456A,0x456B,0x456C,0x456D,0x456E,0x456F, + 0x4570,0x4571,0x4572,0x4573,0x4574,0x4575,0x4576,0x4577,0x4578,0x4579,0x457A,0x457B,0x457C,0x457D,0x457E,0x457F, + 0x4580,0x4581,0x4582,0x4583,0x4584,0x4585,0x4586,0x4587,0x4588,0x4589,0x458A,0x458B,0x458C,0x458D,0x458E,0x458F, + 0x4590,0x4591,0x4592,0x4593,0x4594,0x4595,0x4596,0x4597,0x4598,0x4599,0x459A,0x459B,0x459C,0x459D,0x459E,0x459F, + 0x45A0,0x45A1,0x45A2,0x45A3,0x45A4,0x45A5,0x45A6,0x45A7,0x45A8,0x45A9,0x45AA,0x45AB,0x45AC,0x45AD,0x45AE,0x45AF, + 0x45B0,0x45B1,0x45B2,0x45B3,0x45B4,0x45B5,0x45B6,0x45B7,0x45B8,0x45B9,0x45BA,0x45BB,0x45BC,0x45BD,0x45BE,0x45BF, + 0x45C0,0x45C1,0x45C2,0x45C3,0x45C4,0x45C5,0x45C6,0x45C7,0x45C8,0x45C9,0x45CA,0x45CB,0x45CC,0x45CD,0x45CE,0x45CF, + 0x45D0,0x45D1,0x45D2,0x45D3,0x45D4,0x45D5,0x45D6,0x45D7,0x45D8,0x45D9,0x45DA,0x45DB,0x45DC,0x45DD,0x45DE,0x45DF, + 0x45E0,0x45E1,0x45E2,0x45E3,0x45E4,0x45E5,0x45E6,0x45E7,0x45E8,0x45E9,0x45EA,0x45EB,0x45EC,0x45ED,0x45EE,0x45EF, + 0x45F0,0x45F1,0x45F2,0x45F3,0x45F4,0x45F5,0x45F6,0x45F7,0x45F8,0x45F9,0x45FA,0x45FB,0x45FC,0x45FD,0x45FE,0x45FF, + 0x4600,0x4601,0x4602,0x4603,0x4604,0x4605,0x4606,0x4607,0x4608,0x4609,0x460A,0x460B,0x460C,0x460D,0x460E,0x460F, + 0x4610,0x4611,0x4612,0x4613,0x4614,0x4615,0x4616,0x4617,0x4618,0x4619,0x461A,0x461B,0x461C,0x461D,0x461E,0x461F, + 0x4620,0x4621,0x4622,0x4623,0x4624,0x4625,0x4626,0x4627,0x4628,0x4629,0x462A,0x462B,0x462C,0x462D,0x462E,0x462F, + 0x4630,0x4631,0x4632,0x4633,0x4634,0x4635,0x4636,0x4637,0x4638,0x4639,0x463A,0x463B,0x463C,0x463D,0x463E,0x463F, + 0x4640,0x4641,0x4642,0x4643,0x4644,0x4645,0x4646,0x4647,0x4648,0x4649,0x464A,0x464B,0x464C,0x464D,0x464E,0x464F, + 0x4650,0x4651,0x4652,0x4653,0x4654,0x4655,0x4656,0x4657,0x4658,0x4659,0x465A,0x465B,0x465C,0x465D,0x465E,0x465F, + 0x4660,0x4661,0x4662,0x4663,0x4664,0x4665,0x4666,0x4667,0x4668,0x4669,0x466A,0x466B,0x466C,0x466D,0x466E,0x466F, + 0x4670,0x4671,0x4672,0x4673,0x4674,0x4675,0x4676,0x4677,0x4678,0x4679,0x467A,0x467B,0x467C,0x467D,0x467E,0x467F, + 0x4680,0x4681,0x4682,0x4683,0x4684,0x4685,0x4686,0x4687,0x4688,0x4689,0x468A,0x468B,0x468C,0x468D,0x468E,0x468F, + 0x4690,0x4691,0x4692,0x4693,0x4694,0x4695,0x4696,0x4697,0x4698,0x4699,0x469A,0x469B,0x469C,0x469D,0x469E,0x469F, + 0x46A0,0x46A1,0x46A2,0x46A3,0x46A4,0x46A5,0x46A6,0x46A7,0x46A8,0x46A9,0x46AA,0x46AB,0x46AC,0x46AD,0x46AE,0x46AF, + 0x46B0,0x46B1,0x46B2,0x46B3,0x46B4,0x46B5,0x46B6,0x46B7,0x46B8,0x46B9,0x46BA,0x46BB,0x46BC,0x46BD,0x46BE,0x46BF, + 0x46C0,0x46C1,0x46C2,0x46C3,0x46C4,0x46C5,0x46C6,0x46C7,0x46C8,0x46C9,0x46CA,0x46CB,0x46CC,0x46CD,0x46CE,0x46CF, + 0x46D0,0x46D1,0x46D2,0x46D3,0x46D4,0x46D5,0x46D6,0x46D7,0x46D8,0x46D9,0x46DA,0x46DB,0x46DC,0x46DD,0x46DE,0x46DF, + 0x46E0,0x46E1,0x46E2,0x46E3,0x46E4,0x46E5,0x46E6,0x46E7,0x46E8,0x46E9,0x46EA,0x46EB,0x46EC,0x46ED,0x46EE,0x46EF, + 0x46F0,0x46F1,0x46F2,0x46F3,0x46F4,0x46F5,0x46F6,0x46F7,0x46F8,0x46F9,0x46FA,0x46FB,0x46FC,0x46FD,0x46FE,0x46FF, + 0x4700,0x4701,0x4702,0x4703,0x4704,0x4705,0x4706,0x4707,0x4708,0x4709,0x470A,0x470B,0x470C,0x470D,0x470E,0x470F, + 0x4710,0x4711,0x4712,0x4713,0x4714,0x4715,0x4716,0x4717,0x4718,0x4719,0x471A,0x471B,0x471C,0x471D,0x471E,0x471F, + 0x4720,0x4721,0x4722,0x4723,0x4724,0x4725,0x4726,0x4727,0x4728,0x4729,0x472A,0x472B,0x472C,0x472D,0x472E,0x472F, + 0x4730,0x4731,0x4732,0x4733,0x4734,0x4735,0x4736,0x4737,0x4738,0x4739,0x473A,0x473B,0x473C,0x473D,0x473E,0x473F, + 0x4740,0x4741,0x4742,0x4743,0x4744,0x4745,0x4746,0x4747,0x4748,0x4749,0x474A,0x474B,0x474C,0x474D,0x474E,0x474F, + 0x4750,0x4751,0x4752,0x4753,0x4754,0x4755,0x4756,0x4757,0x4758,0x4759,0x475A,0x475B,0x475C,0x475D,0x475E,0x475F, + 0x4760,0x4761,0x4762,0x4763,0x4764,0x4765,0x4766,0x4767,0x4768,0x4769,0x476A,0x476B,0x476C,0x476D,0x476E,0x476F, + 0x4770,0x4771,0x4772,0x4773,0x4774,0x4775,0x4776,0x4777,0x4778,0x4779,0x477A,0x477B,0x477C,0x477D,0x477E,0x477F, + 0x4780,0x4781,0x4782,0x4783,0x4784,0x4785,0x4786,0x4787,0x4788,0x4789,0x478A,0x478B,0x478C,0x478D,0x478E,0x478F, + 0x4790,0x4791,0x4792,0x4793,0x4794,0x4795,0x4796,0x4797,0x4798,0x4799,0x479A,0x479B,0x479C,0x479D,0x479E,0x479F, + 0x47A0,0x47A1,0x47A2,0x47A3,0x47A4,0x47A5,0x47A6,0x47A7,0x47A8,0x47A9,0x47AA,0x47AB,0x47AC,0x47AD,0x47AE,0x47AF, + 0x47B0,0x47B1,0x47B2,0x47B3,0x47B4,0x47B5,0x47B6,0x47B7,0x47B8,0x47B9,0x47BA,0x47BB,0x47BC,0x47BD,0x47BE,0x47BF, + 0x47C0,0x47C1,0x47C2,0x47C3,0x47C4,0x47C5,0x47C6,0x47C7,0x47C8,0x47C9,0x47CA,0x47CB,0x47CC,0x47CD,0x47CE,0x47CF, + 0x47D0,0x47D1,0x47D2,0x47D3,0x47D4,0x47D5,0x47D6,0x47D7,0x47D8,0x47D9,0x47DA,0x47DB,0x47DC,0x47DD,0x47DE,0x47DF, + 0x47E0,0x47E1,0x47E2,0x47E3,0x47E4,0x47E5,0x47E6,0x47E7,0x47E8,0x47E9,0x47EA,0x47EB,0x47EC,0x47ED,0x47EE,0x47EF, + 0x47F0,0x47F1,0x47F2,0x47F3,0x47F4,0x47F5,0x47F6,0x47F7,0x47F8,0x47F9,0x47FA,0x47FB,0x47FC,0x47FD,0x47FE,0x47FF, + 0x4800,0x4801,0x4802,0x4803,0x4804,0x4805,0x4806,0x4807,0x4808,0x4809,0x480A,0x480B,0x480C,0x480D,0x480E,0x480F, + 0x4810,0x4811,0x4812,0x4813,0x4814,0x4815,0x4816,0x4817,0x4818,0x4819,0x481A,0x481B,0x481C,0x481D,0x481E,0x481F, + 0x4820,0x4821,0x4822,0x4823,0x4824,0x4825,0x4826,0x4827,0x4828,0x4829,0x482A,0x482B,0x482C,0x482D,0x482E,0x482F, + 0x4830,0x4831,0x4832,0x4833,0x4834,0x4835,0x4836,0x4837,0x4838,0x4839,0x483A,0x483B,0x483C,0x483D,0x483E,0x483F, + 0x4840,0x4841,0x4842,0x4843,0x4844,0x4845,0x4846,0x4847,0x4848,0x4849,0x484A,0x484B,0x484C,0x484D,0x484E,0x484F, + 0x4850,0x4851,0x4852,0x4853,0x4854,0x4855,0x4856,0x4857,0x4858,0x4859,0x485A,0x485B,0x485C,0x485D,0x485E,0x485F, + 0x4860,0x4861,0x4862,0x4863,0x4864,0x4865,0x4866,0x4867,0x4868,0x4869,0x486A,0x486B,0x486C,0x486D,0x486E,0x486F, + 0x4870,0x4871,0x4872,0x4873,0x4874,0x4875,0x4876,0x4877,0x4878,0x4879,0x487A,0x487B,0x487C,0x487D,0x487E,0x487F, + 0x4880,0x4881,0x4882,0x4883,0x4884,0x4885,0x4886,0x4887,0x4888,0x4889,0x488A,0x488B,0x488C,0x488D,0x488E,0x488F, + 0x4890,0x4891,0x4892,0x4893,0x4894,0x4895,0x4896,0x4897,0x4898,0x4899,0x489A,0x489B,0x489C,0x489D,0x489E,0x489F, + 0x48A0,0x48A1,0x48A2,0x48A3,0x48A4,0x48A5,0x48A6,0x48A7,0x48A8,0x48A9,0x48AA,0x48AB,0x48AC,0x48AD,0x48AE,0x48AF, + 0x48B0,0x48B1,0x48B2,0x48B3,0x48B4,0x48B5,0x48B6,0x48B7,0x48B8,0x48B9,0x48BA,0x48BB,0x48BC,0x48BD,0x48BE,0x48BF, + 0x48C0,0x48C1,0x48C2,0x48C3,0x48C4,0x48C5,0x48C6,0x48C7,0x48C8,0x48C9,0x48CA,0x48CB,0x48CC,0x48CD,0x48CE,0x48CF, + 0x48D0,0x48D1,0x48D2,0x48D3,0x48D4,0x48D5,0x48D6,0x48D7,0x48D8,0x48D9,0x48DA,0x48DB,0x48DC,0x48DD,0x48DE,0x48DF, + 0x48E0,0x48E1,0x48E2,0x48E3,0x48E4,0x48E5,0x48E6,0x48E7,0x48E8,0x48E9,0x48EA,0x48EB,0x48EC,0x48ED,0x48EE,0x48EF, + 0x48F0,0x48F1,0x48F2,0x48F3,0x48F4,0x48F5,0x48F6,0x48F7,0x48F8,0x48F9,0x48FA,0x48FB,0x48FC,0x48FD,0x48FE,0x48FF, + 0x4900,0x4901,0x4902,0x4903,0x4904,0x4905,0x4906,0x4907,0x4908,0x4909,0x490A,0x490B,0x490C,0x490D,0x490E,0x490F, + 0x4910,0x4911,0x4912,0x4913,0x4914,0x4915,0x4916,0x4917,0x4918,0x4919,0x491A,0x491B,0x491C,0x491D,0x491E,0x491F, + 0x4920,0x4921,0x4922,0x4923,0x4924,0x4925,0x4926,0x4927,0x4928,0x4929,0x492A,0x492B,0x492C,0x492D,0x492E,0x492F, + 0x4930,0x4931,0x4932,0x4933,0x4934,0x4935,0x4936,0x4937,0x4938,0x4939,0x493A,0x493B,0x493C,0x493D,0x493E,0x493F, + 0x4940,0x4941,0x4942,0x4943,0x4944,0x4945,0x4946,0x4947,0x4948,0x4949,0x494A,0x494B,0x494C,0x494D,0x494E,0x494F, + 0x4950,0x4951,0x4952,0x4953,0x4954,0x4955,0x4956,0x4957,0x4958,0x4959,0x495A,0x495B,0x495C,0x495D,0x495E,0x495F, + 0x4960,0x4961,0x4962,0x4963,0x4964,0x4965,0x4966,0x4967,0x4968,0x4969,0x496A,0x496B,0x496C,0x496D,0x496E,0x496F, + 0x4970,0x4971,0x4972,0x4973,0x4974,0x4975,0x4976,0x4977,0x4978,0x4979,0x497A,0x497B,0x497C,0x497D,0x497E,0x497F, + 0x4980,0x4981,0x4982,0x4983,0x4984,0x4985,0x4986,0x4987,0x4988,0x4989,0x498A,0x498B,0x498C,0x498D,0x498E,0x498F, + 0x4990,0x4991,0x4992,0x4993,0x4994,0x4995,0x4996,0x4997,0x4998,0x4999,0x499A,0x499B,0x499C,0x499D,0x499E,0x499F, + 0x49A0,0x49A1,0x49A2,0x49A3,0x49A4,0x49A5,0x49A6,0x49A7,0x49A8,0x49A9,0x49AA,0x49AB,0x49AC,0x49AD,0x49AE,0x49AF, + 0x49B0,0x49B1,0x49B2,0x49B3,0x49B4,0x49B5,0x49B6,0x49B7,0x49B8,0x49B9,0x49BA,0x49BB,0x49BC,0x49BD,0x49BE,0x49BF, + 0x49C0,0x49C1,0x49C2,0x49C3,0x49C4,0x49C5,0x49C6,0x49C7,0x49C8,0x49C9,0x49CA,0x49CB,0x49CC,0x49CD,0x49CE,0x49CF, + 0x49D0,0x49D1,0x49D2,0x49D3,0x49D4,0x49D5,0x49D6,0x49D7,0x49D8,0x49D9,0x49DA,0x49DB,0x49DC,0x49DD,0x49DE,0x49DF, + 0x49E0,0x49E1,0x49E2,0x49E3,0x49E4,0x49E5,0x49E6,0x49E7,0x49E8,0x49E9,0x49EA,0x49EB,0x49EC,0x49ED,0x49EE,0x49EF, + 0x49F0,0x49F1,0x49F2,0x49F3,0x49F4,0x49F5,0x49F6,0x49F7,0x49F8,0x49F9,0x49FA,0x49FB,0x49FC,0x49FD,0x49FE,0x49FF, + 0x4A00,0x4A01,0x4A02,0x4A03,0x4A04,0x4A05,0x4A06,0x4A07,0x4A08,0x4A09,0x4A0A,0x4A0B,0x4A0C,0x4A0D,0x4A0E,0x4A0F, + 0x4A10,0x4A11,0x4A12,0x4A13,0x4A14,0x4A15,0x4A16,0x4A17,0x4A18,0x4A19,0x4A1A,0x4A1B,0x4A1C,0x4A1D,0x4A1E,0x4A1F, + 0x4A20,0x4A21,0x4A22,0x4A23,0x4A24,0x4A25,0x4A26,0x4A27,0x4A28,0x4A29,0x4A2A,0x4A2B,0x4A2C,0x4A2D,0x4A2E,0x4A2F, + 0x4A30,0x4A31,0x4A32,0x4A33,0x4A34,0x4A35,0x4A36,0x4A37,0x4A38,0x4A39,0x4A3A,0x4A3B,0x4A3C,0x4A3D,0x4A3E,0x4A3F, + 0x4A40,0x4A41,0x4A42,0x4A43,0x4A44,0x4A45,0x4A46,0x4A47,0x4A48,0x4A49,0x4A4A,0x4A4B,0x4A4C,0x4A4D,0x4A4E,0x4A4F, + 0x4A50,0x4A51,0x4A52,0x4A53,0x4A54,0x4A55,0x4A56,0x4A57,0x4A58,0x4A59,0x4A5A,0x4A5B,0x4A5C,0x4A5D,0x4A5E,0x4A5F, + 0x4A60,0x4A61,0x4A62,0x4A63,0x4A64,0x4A65,0x4A66,0x4A67,0x4A68,0x4A69,0x4A6A,0x4A6B,0x4A6C,0x4A6D,0x4A6E,0x4A6F, + 0x4A70,0x4A71,0x4A72,0x4A73,0x4A74,0x4A75,0x4A76,0x4A77,0x4A78,0x4A79,0x4A7A,0x4A7B,0x4A7C,0x4A7D,0x4A7E,0x4A7F, + 0x4A80,0x4A81,0x4A82,0x4A83,0x4A84,0x4A85,0x4A86,0x4A87,0x4A88,0x4A89,0x4A8A,0x4A8B,0x4A8C,0x4A8D,0x4A8E,0x4A8F, + 0x4A90,0x4A91,0x4A92,0x4A93,0x4A94,0x4A95,0x4A96,0x4A97,0x4A98,0x4A99,0x4A9A,0x4A9B,0x4A9C,0x4A9D,0x4A9E,0x4A9F, + 0x4AA0,0x4AA1,0x4AA2,0x4AA3,0x4AA4,0x4AA5,0x4AA6,0x4AA7,0x4AA8,0x4AA9,0x4AAA,0x4AAB,0x4AAC,0x4AAD,0x4AAE,0x4AAF, + 0x4AB0,0x4AB1,0x4AB2,0x4AB3,0x4AB4,0x4AB5,0x4AB6,0x4AB7,0x4AB8,0x4AB9,0x4ABA,0x4ABB,0x4ABC,0x4ABD,0x4ABE,0x4ABF, + 0x4AC0,0x4AC1,0x4AC2,0x4AC3,0x4AC4,0x4AC5,0x4AC6,0x4AC7,0x4AC8,0x4AC9,0x4ACA,0x4ACB,0x4ACC,0x4ACD,0x4ACE,0x4ACF, + 0x4AD0,0x4AD1,0x4AD2,0x4AD3,0x4AD4,0x4AD5,0x4AD6,0x4AD7,0x4AD8,0x4AD9,0x4ADA,0x4ADB,0x4ADC,0x4ADD,0x4ADE,0x4ADF, + 0x4AE0,0x4AE1,0x4AE2,0x4AE3,0x4AE4,0x4AE5,0x4AE6,0x4AE7,0x4AE8,0x4AE9,0x4AEA,0x4AEB,0x4AEC,0x4AED,0x4AEE,0x4AEF, + 0x4AF0,0x4AF1,0x4AF2,0x4AF3,0x4AF4,0x4AF5,0x4AF6,0x4AF7,0x4AF8,0x4AF9,0x4AFA,0x4AFB,0x4AFC,0x4AFD,0x4AFE,0x4AFF, + 0x4B00,0x4B01,0x4B02,0x4B03,0x4B04,0x4B05,0x4B06,0x4B07,0x4B08,0x4B09,0x4B0A,0x4B0B,0x4B0C,0x4B0D,0x4B0E,0x4B0F, + 0x4B10,0x4B11,0x4B12,0x4B13,0x4B14,0x4B15,0x4B16,0x4B17,0x4B18,0x4B19,0x4B1A,0x4B1B,0x4B1C,0x4B1D,0x4B1E,0x4B1F, + 0x4B20,0x4B21,0x4B22,0x4B23,0x4B24,0x4B25,0x4B26,0x4B27,0x4B28,0x4B29,0x4B2A,0x4B2B,0x4B2C,0x4B2D,0x4B2E,0x4B2F, + 0x4B30,0x4B31,0x4B32,0x4B33,0x4B34,0x4B35,0x4B36,0x4B37,0x4B38,0x4B39,0x4B3A,0x4B3B,0x4B3C,0x4B3D,0x4B3E,0x4B3F, + 0x4B40,0x4B41,0x4B42,0x4B43,0x4B44,0x4B45,0x4B46,0x4B47,0x4B48,0x4B49,0x4B4A,0x4B4B,0x4B4C,0x4B4D,0x4B4E,0x4B4F, + 0x4B50,0x4B51,0x4B52,0x4B53,0x4B54,0x4B55,0x4B56,0x4B57,0x4B58,0x4B59,0x4B5A,0x4B5B,0x4B5C,0x4B5D,0x4B5E,0x4B5F, + 0x4B60,0x4B61,0x4B62,0x4B63,0x4B64,0x4B65,0x4B66,0x4B67,0x4B68,0x4B69,0x4B6A,0x4B6B,0x4B6C,0x4B6D,0x4B6E,0x4B6F, + 0x4B70,0x4B71,0x4B72,0x4B73,0x4B74,0x4B75,0x4B76,0x4B77,0x4B78,0x4B79,0x4B7A,0x4B7B,0x4B7C,0x4B7D,0x4B7E,0x4B7F, + 0x4B80,0x4B81,0x4B82,0x4B83,0x4B84,0x4B85,0x4B86,0x4B87,0x4B88,0x4B89,0x4B8A,0x4B8B,0x4B8C,0x4B8D,0x4B8E,0x4B8F, + 0x4B90,0x4B91,0x4B92,0x4B93,0x4B94,0x4B95,0x4B96,0x4B97,0x4B98,0x4B99,0x4B9A,0x4B9B,0x4B9C,0x4B9D,0x4B9E,0x4B9F, + 0x4BA0,0x4BA1,0x4BA2,0x4BA3,0x4BA4,0x4BA5,0x4BA6,0x4BA7,0x4BA8,0x4BA9,0x4BAA,0x4BAB,0x4BAC,0x4BAD,0x4BAE,0x4BAF, + 0x4BB0,0x4BB1,0x4BB2,0x4BB3,0x4BB4,0x4BB5,0x4BB6,0x4BB7,0x4BB8,0x4BB9,0x4BBA,0x4BBB,0x4BBC,0x4BBD,0x4BBE,0x4BBF, + 0x4BC0,0x4BC1,0x4BC2,0x4BC3,0x4BC4,0x4BC5,0x4BC6,0x4BC7,0x4BC8,0x4BC9,0x4BCA,0x4BCB,0x4BCC,0x4BCD,0x4BCE,0x4BCF, + 0x4BD0,0x4BD1,0x4BD2,0x4BD3,0x4BD4,0x4BD5,0x4BD6,0x4BD7,0x4BD8,0x4BD9,0x4BDA,0x4BDB,0x4BDC,0x4BDD,0x4BDE,0x4BDF, + 0x4BE0,0x4BE1,0x4BE2,0x4BE3,0x4BE4,0x4BE5,0x4BE6,0x4BE7,0x4BE8,0x4BE9,0x4BEA,0x4BEB,0x4BEC,0x4BED,0x4BEE,0x4BEF, + 0x4BF0,0x4BF1,0x4BF2,0x4BF3,0x4BF4,0x4BF5,0x4BF6,0x4BF7,0x4BF8,0x4BF9,0x4BFA,0x4BFB,0x4BFC,0x4BFD,0x4BFE,0x4BFF, + 0x4C00,0x4C01,0x4C02,0x4C03,0x4C04,0x4C05,0x4C06,0x4C07,0x4C08,0x4C09,0x4C0A,0x4C0B,0x4C0C,0x4C0D,0x4C0E,0x4C0F, + 0x4C10,0x4C11,0x4C12,0x4C13,0x4C14,0x4C15,0x4C16,0x4C17,0x4C18,0x4C19,0x4C1A,0x4C1B,0x4C1C,0x4C1D,0x4C1E,0x4C1F, + 0x4C20,0x4C21,0x4C22,0x4C23,0x4C24,0x4C25,0x4C26,0x4C27,0x4C28,0x4C29,0x4C2A,0x4C2B,0x4C2C,0x4C2D,0x4C2E,0x4C2F, + 0x4C30,0x4C31,0x4C32,0x4C33,0x4C34,0x4C35,0x4C36,0x4C37,0x4C38,0x4C39,0x4C3A,0x4C3B,0x4C3C,0x4C3D,0x4C3E,0x4C3F, + 0x4C40,0x4C41,0x4C42,0x4C43,0x4C44,0x4C45,0x4C46,0x4C47,0x4C48,0x4C49,0x4C4A,0x4C4B,0x4C4C,0x4C4D,0x4C4E,0x4C4F, + 0x4C50,0x4C51,0x4C52,0x4C53,0x4C54,0x4C55,0x4C56,0x4C57,0x4C58,0x4C59,0x4C5A,0x4C5B,0x4C5C,0x4C5D,0x4C5E,0x4C5F, + 0x4C60,0x4C61,0x4C62,0x4C63,0x4C64,0x4C65,0x4C66,0x4C67,0x4C68,0x4C69,0x4C6A,0x4C6B,0x4C6C,0x4C6D,0x4C6E,0x4C6F, + 0x4C70,0x4C71,0x4C72,0x4C73,0x4C74,0x4C75,0x4C76,0x4C77,0x4C78,0x4C79,0x4C7A,0x4C7B,0x4C7C,0x4C7D,0x4C7E,0x4C7F, + 0x4C80,0x4C81,0x4C82,0x4C83,0x4C84,0x4C85,0x4C86,0x4C87,0x4C88,0x4C89,0x4C8A,0x4C8B,0x4C8C,0x4C8D,0x4C8E,0x4C8F, + 0x4C90,0x4C91,0x4C92,0x4C93,0x4C94,0x4C95,0x4C96,0x4C97,0x4C98,0x4C99,0x4C9A,0x4C9B,0x4C9C,0x4C9D,0x4C9E,0x4C9F, + 0x4CA0,0x4CA1,0x4CA2,0x4CA3,0x4CA4,0x4CA5,0x4CA6,0x4CA7,0x4CA8,0x4CA9,0x4CAA,0x4CAB,0x4CAC,0x4CAD,0x4CAE,0x4CAF, + 0x4CB0,0x4CB1,0x4CB2,0x4CB3,0x4CB4,0x4CB5,0x4CB6,0x4CB7,0x4CB8,0x4CB9,0x4CBA,0x4CBB,0x4CBC,0x4CBD,0x4CBE,0x4CBF, + 0x4CC0,0x4CC1,0x4CC2,0x4CC3,0x4CC4,0x4CC5,0x4CC6,0x4CC7,0x4CC8,0x4CC9,0x4CCA,0x4CCB,0x4CCC,0x4CCD,0x4CCE,0x4CCF, + 0x4CD0,0x4CD1,0x4CD2,0x4CD3,0x4CD4,0x4CD5,0x4CD6,0x4CD7,0x4CD8,0x4CD9,0x4CDA,0x4CDB,0x4CDC,0x4CDD,0x4CDE,0x4CDF, + 0x4CE0,0x4CE1,0x4CE2,0x4CE3,0x4CE4,0x4CE5,0x4CE6,0x4CE7,0x4CE8,0x4CE9,0x4CEA,0x4CEB,0x4CEC,0x4CED,0x4CEE,0x4CEF, + 0x4CF0,0x4CF1,0x4CF2,0x4CF3,0x4CF4,0x4CF5,0x4CF6,0x4CF7,0x4CF8,0x4CF9,0x4CFA,0x4CFB,0x4CFC,0x4CFD,0x4CFE,0x4CFF, + 0x4D00,0x4D01,0x4D02,0x4D03,0x4D04,0x4D05,0x4D06,0x4D07,0x4D08,0x4D09,0x4D0A,0x4D0B,0x4D0C,0x4D0D,0x4D0E,0x4D0F, + 0x4D10,0x4D11,0x4D12,0x4D13,0x4D14,0x4D15,0x4D16,0x4D17,0x4D18,0x4D19,0x4D1A,0x4D1B,0x4D1C,0x4D1D,0x4D1E,0x4D1F, + 0x4D20,0x4D21,0x4D22,0x4D23,0x4D24,0x4D25,0x4D26,0x4D27,0x4D28,0x4D29,0x4D2A,0x4D2B,0x4D2C,0x4D2D,0x4D2E,0x4D2F, + 0x4D30,0x4D31,0x4D32,0x4D33,0x4D34,0x4D35,0x4D36,0x4D37,0x4D38,0x4D39,0x4D3A,0x4D3B,0x4D3C,0x4D3D,0x4D3E,0x4D3F, + 0x4D40,0x4D41,0x4D42,0x4D43,0x4D44,0x4D45,0x4D46,0x4D47,0x4D48,0x4D49,0x4D4A,0x4D4B,0x4D4C,0x4D4D,0x4D4E,0x4D4F, + 0x4D50,0x4D51,0x4D52,0x4D53,0x4D54,0x4D55,0x4D56,0x4D57,0x4D58,0x4D59,0x4D5A,0x4D5B,0x4D5C,0x4D5D,0x4D5E,0x4D5F, + 0x4D60,0x4D61,0x4D62,0x4D63,0x4D64,0x4D65,0x4D66,0x4D67,0x4D68,0x4D69,0x4D6A,0x4D6B,0x4D6C,0x4D6D,0x4D6E,0x4D6F, + 0x4D70,0x4D71,0x4D72,0x4D73,0x4D74,0x4D75,0x4D76,0x4D77,0x4D78,0x4D79,0x4D7A,0x4D7B,0x4D7C,0x4D7D,0x4D7E,0x4D7F, + 0x4D80,0x4D81,0x4D82,0x4D83,0x4D84,0x4D85,0x4D86,0x4D87,0x4D88,0x4D89,0x4D8A,0x4D8B,0x4D8C,0x4D8D,0x4D8E,0x4D8F, + 0x4D90,0x4D91,0x4D92,0x4D93,0x4D94,0x4D95,0x4D96,0x4D97,0x4D98,0x4D99,0x4D9A,0x4D9B,0x4D9C,0x4D9D,0x4D9E,0x4D9F, + 0x4DA0,0x4DA1,0x4DA2,0x4DA3,0x4DA4,0x4DA5,0x4DA6,0x4DA7,0x4DA8,0x4DA9,0x4DAA,0x4DAB,0x4DAC,0x4DAD,0x4DAE,0x4DAF, + 0x4DB0,0x4DB1,0x4DB2,0x4DB3,0x4DB4,0x4DB5,0x4DB6,0x4DB7,0x4DB8,0x4DB9,0x4DBA,0x4DBB,0x4DBC,0x4DBD,0x4DBE,0x4DBF, + 0x4DC0,0x4DC1,0x4DC2,0x4DC3,0x4DC4,0x4DC5,0x4DC6,0x4DC7,0x4DC8,0x4DC9,0x4DCA,0x4DCB,0x4DCC,0x4DCD,0x4DCE,0x4DCF, + 0x4DD0,0x4DD1,0x4DD2,0x4DD3,0x4DD4,0x4DD5,0x4DD6,0x4DD7,0x4DD8,0x4DD9,0x4DDA,0x4DDB,0x4DDC,0x4DDD,0x4DDE,0x4DDF, + 0x4DE0,0x4DE1,0x4DE2,0x4DE3,0x4DE4,0x4DE5,0x4DE6,0x4DE7,0x4DE8,0x4DE9,0x4DEA,0x4DEB,0x4DEC,0x4DED,0x4DEE,0x4DEF, + 0x4DF0,0x4DF1,0x4DF2,0x4DF3,0x4DF4,0x4DF5,0x4DF6,0x4DF7,0x4DF8,0x4DF9,0x4DFA,0x4DFB,0x4DFC,0x4DFD,0x4DFE,0x4DFF, + 0x4E00,0x4E01,0x4E02,0x4E03,0x4E04,0x4E05,0x4E06,0x4E07,0x4E08,0x4E09,0x4E0A,0x4E0B,0x4E0C,0x4E0D,0x4E0E,0x4E0F, + 0x4E10,0x4E11,0x4E12,0x4E13,0x4E14,0x4E15,0x4E16,0x4E17,0x4E18,0x4E19,0x4E1A,0x4E1B,0x4E1C,0x4E1D,0x4E1E,0x4E1F, + 0x4E20,0x4E21,0x4E22,0x4E23,0x4E24,0x4E25,0x4E26,0x4E27,0x4E28,0x4E29,0x4E2A,0x4E2B,0x4E2C,0x4E2D,0x4E2E,0x4E2F, + 0x4E30,0x4E31,0x4E32,0x4E33,0x4E34,0x4E35,0x4E36,0x4E37,0x4E38,0x4E39,0x4E3A,0x4E3B,0x4E3C,0x4E3D,0x4E3E,0x4E3F, + 0x4E40,0x4E41,0x4E42,0x4E43,0x4E44,0x4E45,0x4E46,0x4E47,0x4E48,0x4E49,0x4E4A,0x4E4B,0x4E4C,0x4E4D,0x4E4E,0x4E4F, + 0x4E50,0x4E51,0x4E52,0x4E53,0x4E54,0x4E55,0x4E56,0x4E57,0x4E58,0x4E59,0x4E5A,0x4E5B,0x4E5C,0x4E5D,0x4E5E,0x4E5F, + 0x4E60,0x4E61,0x4E62,0x4E63,0x4E64,0x4E65,0x4E66,0x4E67,0x4E68,0x4E69,0x4E6A,0x4E6B,0x4E6C,0x4E6D,0x4E6E,0x4E6F, + 0x4E70,0x4E71,0x4E72,0x4E73,0x4E74,0x4E75,0x4E76,0x4E77,0x4E78,0x4E79,0x4E7A,0x4E7B,0x4E7C,0x4E7D,0x4E7E,0x4E7F, + 0x4E80,0x4E81,0x4E82,0x4E83,0x4E84,0x4E85,0x4E86,0x4E87,0x4E88,0x4E89,0x4E8A,0x4E8B,0x4E8C,0x4E8D,0x4E8E,0x4E8F, + 0x4E90,0x4E91,0x4E92,0x4E93,0x4E94,0x4E95,0x4E96,0x4E97,0x4E98,0x4E99,0x4E9A,0x4E9B,0x4E9C,0x4E9D,0x4E9E,0x4E9F, + 0x4EA0,0x4EA1,0x4EA2,0x4EA3,0x4EA4,0x4EA5,0x4EA6,0x4EA7,0x4EA8,0x4EA9,0x4EAA,0x4EAB,0x4EAC,0x4EAD,0x4EAE,0x4EAF, + 0x4EB0,0x4EB1,0x4EB2,0x4EB3,0x4EB4,0x4EB5,0x4EB6,0x4EB7,0x4EB8,0x4EB9,0x4EBA,0x4EBB,0x4EBC,0x4EBD,0x4EBE,0x4EBF, + 0x4EC0,0x4EC1,0x4EC2,0x4EC3,0x4EC4,0x4EC5,0x4EC6,0x4EC7,0x4EC8,0x4EC9,0x4ECA,0x4ECB,0x4ECC,0x4ECD,0x4ECE,0x4ECF, + 0x4ED0,0x4ED1,0x4ED2,0x4ED3,0x4ED4,0x4ED5,0x4ED6,0x4ED7,0x4ED8,0x4ED9,0x4EDA,0x4EDB,0x4EDC,0x4EDD,0x4EDE,0x4EDF, + 0x4EE0,0x4EE1,0x4EE2,0x4EE3,0x4EE4,0x4EE5,0x4EE6,0x4EE7,0x4EE8,0x4EE9,0x4EEA,0x4EEB,0x4EEC,0x4EED,0x4EEE,0x4EEF, + 0x4EF0,0x4EF1,0x4EF2,0x4EF3,0x4EF4,0x4EF5,0x4EF6,0x4EF7,0x4EF8,0x4EF9,0x4EFA,0x4EFB,0x4EFC,0x4EFD,0x4EFE,0x4EFF, + 0x4F00,0x4F01,0x4F02,0x4F03,0x4F04,0x4F05,0x4F06,0x4F07,0x4F08,0x4F09,0x4F0A,0x4F0B,0x4F0C,0x4F0D,0x4F0E,0x4F0F, + 0x4F10,0x4F11,0x4F12,0x4F13,0x4F14,0x4F15,0x4F16,0x4F17,0x4F18,0x4F19,0x4F1A,0x4F1B,0x4F1C,0x4F1D,0x4F1E,0x4F1F, + 0x4F20,0x4F21,0x4F22,0x4F23,0x4F24,0x4F25,0x4F26,0x4F27,0x4F28,0x4F29,0x4F2A,0x4F2B,0x4F2C,0x4F2D,0x4F2E,0x4F2F, + 0x4F30,0x4F31,0x4F32,0x4F33,0x4F34,0x4F35,0x4F36,0x4F37,0x4F38,0x4F39,0x4F3A,0x4F3B,0x4F3C,0x4F3D,0x4F3E,0x4F3F, + 0x4F40,0x4F41,0x4F42,0x4F43,0x4F44,0x4F45,0x4F46,0x4F47,0x4F48,0x4F49,0x4F4A,0x4F4B,0x4F4C,0x4F4D,0x4F4E,0x4F4F, + 0x4F50,0x4F51,0x4F52,0x4F53,0x4F54,0x4F55,0x4F56,0x4F57,0x4F58,0x4F59,0x4F5A,0x4F5B,0x4F5C,0x4F5D,0x4F5E,0x4F5F, + 0x4F60,0x4F61,0x4F62,0x4F63,0x4F64,0x4F65,0x4F66,0x4F67,0x4F68,0x4F69,0x4F6A,0x4F6B,0x4F6C,0x4F6D,0x4F6E,0x4F6F, + 0x4F70,0x4F71,0x4F72,0x4F73,0x4F74,0x4F75,0x4F76,0x4F77,0x4F78,0x4F79,0x4F7A,0x4F7B,0x4F7C,0x4F7D,0x4F7E,0x4F7F, + 0x4F80,0x4F81,0x4F82,0x4F83,0x4F84,0x4F85,0x4F86,0x4F87,0x4F88,0x4F89,0x4F8A,0x4F8B,0x4F8C,0x4F8D,0x4F8E,0x4F8F, + 0x4F90,0x4F91,0x4F92,0x4F93,0x4F94,0x4F95,0x4F96,0x4F97,0x4F98,0x4F99,0x4F9A,0x4F9B,0x4F9C,0x4F9D,0x4F9E,0x4F9F, + 0x4FA0,0x4FA1,0x4FA2,0x4FA3,0x4FA4,0x4FA5,0x4FA6,0x4FA7,0x4FA8,0x4FA9,0x4FAA,0x4FAB,0x4FAC,0x4FAD,0x4FAE,0x4FAF, + 0x4FB0,0x4FB1,0x4FB2,0x4FB3,0x4FB4,0x4FB5,0x4FB6,0x4FB7,0x4FB8,0x4FB9,0x4FBA,0x4FBB,0x4FBC,0x4FBD,0x4FBE,0x4FBF, + 0x4FC0,0x4FC1,0x4FC2,0x4FC3,0x4FC4,0x4FC5,0x4FC6,0x4FC7,0x4FC8,0x4FC9,0x4FCA,0x4FCB,0x4FCC,0x4FCD,0x4FCE,0x4FCF, + 0x4FD0,0x4FD1,0x4FD2,0x4FD3,0x4FD4,0x4FD5,0x4FD6,0x4FD7,0x4FD8,0x4FD9,0x4FDA,0x4FDB,0x4FDC,0x4FDD,0x4FDE,0x4FDF, + 0x4FE0,0x4FE1,0x4FE2,0x4FE3,0x4FE4,0x4FE5,0x4FE6,0x4FE7,0x4FE8,0x4FE9,0x4FEA,0x4FEB,0x4FEC,0x4FED,0x4FEE,0x4FEF, + 0x4FF0,0x4FF1,0x4FF2,0x4FF3,0x4FF4,0x4FF5,0x4FF6,0x4FF7,0x4FF8,0x4FF9,0x4FFA,0x4FFB,0x4FFC,0x4FFD,0x4FFE,0x4FFF, + 0x5000,0x5001,0x5002,0x5003,0x5004,0x5005,0x5006,0x5007,0x5008,0x5009,0x500A,0x500B,0x500C,0x500D,0x500E,0x500F, + 0x5010,0x5011,0x5012,0x5013,0x5014,0x5015,0x5016,0x5017,0x5018,0x5019,0x501A,0x501B,0x501C,0x501D,0x501E,0x501F, + 0x5020,0x5021,0x5022,0x5023,0x5024,0x5025,0x5026,0x5027,0x5028,0x5029,0x502A,0x502B,0x502C,0x502D,0x502E,0x502F, + 0x5030,0x5031,0x5032,0x5033,0x5034,0x5035,0x5036,0x5037,0x5038,0x5039,0x503A,0x503B,0x503C,0x503D,0x503E,0x503F, + 0x5040,0x5041,0x5042,0x5043,0x5044,0x5045,0x5046,0x5047,0x5048,0x5049,0x504A,0x504B,0x504C,0x504D,0x504E,0x504F, + 0x5050,0x5051,0x5052,0x5053,0x5054,0x5055,0x5056,0x5057,0x5058,0x5059,0x505A,0x505B,0x505C,0x505D,0x505E,0x505F, + 0x5060,0x5061,0x5062,0x5063,0x5064,0x5065,0x5066,0x5067,0x5068,0x5069,0x506A,0x506B,0x506C,0x506D,0x506E,0x506F, + 0x5070,0x5071,0x5072,0x5073,0x5074,0x5075,0x5076,0x5077,0x5078,0x5079,0x507A,0x507B,0x507C,0x507D,0x507E,0x507F, + 0x5080,0x5081,0x5082,0x5083,0x5084,0x5085,0x5086,0x5087,0x5088,0x5089,0x508A,0x508B,0x508C,0x508D,0x508E,0x508F, + 0x5090,0x5091,0x5092,0x5093,0x5094,0x5095,0x5096,0x5097,0x5098,0x5099,0x509A,0x509B,0x509C,0x509D,0x509E,0x509F, + 0x50A0,0x50A1,0x50A2,0x50A3,0x50A4,0x50A5,0x50A6,0x50A7,0x50A8,0x50A9,0x50AA,0x50AB,0x50AC,0x50AD,0x50AE,0x50AF, + 0x50B0,0x50B1,0x50B2,0x50B3,0x50B4,0x50B5,0x50B6,0x50B7,0x50B8,0x50B9,0x50BA,0x50BB,0x50BC,0x50BD,0x50BE,0x50BF, + 0x50C0,0x50C1,0x50C2,0x50C3,0x50C4,0x50C5,0x50C6,0x50C7,0x50C8,0x50C9,0x50CA,0x50CB,0x50CC,0x50CD,0x50CE,0x50CF, + 0x50D0,0x50D1,0x50D2,0x50D3,0x50D4,0x50D5,0x50D6,0x50D7,0x50D8,0x50D9,0x50DA,0x50DB,0x50DC,0x50DD,0x50DE,0x50DF, + 0x50E0,0x50E1,0x50E2,0x50E3,0x50E4,0x50E5,0x50E6,0x50E7,0x50E8,0x50E9,0x50EA,0x50EB,0x50EC,0x50ED,0x50EE,0x50EF, + 0x50F0,0x50F1,0x50F2,0x50F3,0x50F4,0x50F5,0x50F6,0x50F7,0x50F8,0x50F9,0x50FA,0x50FB,0x50FC,0x50FD,0x50FE,0x50FF, + 0x5100,0x5101,0x5102,0x5103,0x5104,0x5105,0x5106,0x5107,0x5108,0x5109,0x510A,0x510B,0x510C,0x510D,0x510E,0x510F, + 0x5110,0x5111,0x5112,0x5113,0x5114,0x5115,0x5116,0x5117,0x5118,0x5119,0x511A,0x511B,0x511C,0x511D,0x511E,0x511F, + 0x5120,0x5121,0x5122,0x5123,0x5124,0x5125,0x5126,0x5127,0x5128,0x5129,0x512A,0x512B,0x512C,0x512D,0x512E,0x512F, + 0x5130,0x5131,0x5132,0x5133,0x5134,0x5135,0x5136,0x5137,0x5138,0x5139,0x513A,0x513B,0x513C,0x513D,0x513E,0x513F, + 0x5140,0x5141,0x5142,0x5143,0x5144,0x5145,0x5146,0x5147,0x5148,0x5149,0x514A,0x514B,0x514C,0x514D,0x514E,0x514F, + 0x5150,0x5151,0x5152,0x5153,0x5154,0x5155,0x5156,0x5157,0x5158,0x5159,0x515A,0x515B,0x515C,0x515D,0x515E,0x515F, + 0x5160,0x5161,0x5162,0x5163,0x5164,0x5165,0x5166,0x5167,0x5168,0x5169,0x516A,0x516B,0x516C,0x516D,0x516E,0x516F, + 0x5170,0x5171,0x5172,0x5173,0x5174,0x5175,0x5176,0x5177,0x5178,0x5179,0x517A,0x517B,0x517C,0x517D,0x517E,0x517F, + 0x5180,0x5181,0x5182,0x5183,0x5184,0x5185,0x5186,0x5187,0x5188,0x5189,0x518A,0x518B,0x518C,0x518D,0x518E,0x518F, + 0x5190,0x5191,0x5192,0x5193,0x5194,0x5195,0x5196,0x5197,0x5198,0x5199,0x519A,0x519B,0x519C,0x519D,0x519E,0x519F, + 0x51A0,0x51A1,0x51A2,0x51A3,0x51A4,0x51A5,0x51A6,0x51A7,0x51A8,0x51A9,0x51AA,0x51AB,0x51AC,0x51AD,0x51AE,0x51AF, + 0x51B0,0x51B1,0x51B2,0x51B3,0x51B4,0x51B5,0x51B6,0x51B7,0x51B8,0x51B9,0x51BA,0x51BB,0x51BC,0x51BD,0x51BE,0x51BF, + 0x51C0,0x51C1,0x51C2,0x51C3,0x51C4,0x51C5,0x51C6,0x51C7,0x51C8,0x51C9,0x51CA,0x51CB,0x51CC,0x51CD,0x51CE,0x51CF, + 0x51D0,0x51D1,0x51D2,0x51D3,0x51D4,0x51D5,0x51D6,0x51D7,0x51D8,0x51D9,0x51DA,0x51DB,0x51DC,0x51DD,0x51DE,0x51DF, + 0x51E0,0x51E1,0x51E2,0x51E3,0x51E4,0x51E5,0x51E6,0x51E7,0x51E8,0x51E9,0x51EA,0x51EB,0x51EC,0x51ED,0x51EE,0x51EF, + 0x51F0,0x51F1,0x51F2,0x51F3,0x51F4,0x51F5,0x51F6,0x51F7,0x51F8,0x51F9,0x51FA,0x51FB,0x51FC,0x51FD,0x51FE,0x51FF, + 0x5200,0x5201,0x5202,0x5203,0x5204,0x5205,0x5206,0x5207,0x5208,0x5209,0x520A,0x520B,0x520C,0x520D,0x520E,0x520F, + 0x5210,0x5211,0x5212,0x5213,0x5214,0x5215,0x5216,0x5217,0x5218,0x5219,0x521A,0x521B,0x521C,0x521D,0x521E,0x521F, + 0x5220,0x5221,0x5222,0x5223,0x5224,0x5225,0x5226,0x5227,0x5228,0x5229,0x522A,0x522B,0x522C,0x522D,0x522E,0x522F, + 0x5230,0x5231,0x5232,0x5233,0x5234,0x5235,0x5236,0x5237,0x5238,0x5239,0x523A,0x523B,0x523C,0x523D,0x523E,0x523F, + 0x5240,0x5241,0x5242,0x5243,0x5244,0x5245,0x5246,0x5247,0x5248,0x5249,0x524A,0x524B,0x524C,0x524D,0x524E,0x524F, + 0x5250,0x5251,0x5252,0x5253,0x5254,0x5255,0x5256,0x5257,0x5258,0x5259,0x525A,0x525B,0x525C,0x525D,0x525E,0x525F, + 0x5260,0x5261,0x5262,0x5263,0x5264,0x5265,0x5266,0x5267,0x5268,0x5269,0x526A,0x526B,0x526C,0x526D,0x526E,0x526F, + 0x5270,0x5271,0x5272,0x5273,0x5274,0x5275,0x5276,0x5277,0x5278,0x5279,0x527A,0x527B,0x527C,0x527D,0x527E,0x527F, + 0x5280,0x5281,0x5282,0x5283,0x5284,0x5285,0x5286,0x5287,0x5288,0x5289,0x528A,0x528B,0x528C,0x528D,0x528E,0x528F, + 0x5290,0x5291,0x5292,0x5293,0x5294,0x5295,0x5296,0x5297,0x5298,0x5299,0x529A,0x529B,0x529C,0x529D,0x529E,0x529F, + 0x52A0,0x52A1,0x52A2,0x52A3,0x52A4,0x52A5,0x52A6,0x52A7,0x52A8,0x52A9,0x52AA,0x52AB,0x52AC,0x52AD,0x52AE,0x52AF, + 0x52B0,0x52B1,0x52B2,0x52B3,0x52B4,0x52B5,0x52B6,0x52B7,0x52B8,0x52B9,0x52BA,0x52BB,0x52BC,0x52BD,0x52BE,0x52BF, + 0x52C0,0x52C1,0x52C2,0x52C3,0x52C4,0x52C5,0x52C6,0x52C7,0x52C8,0x52C9,0x52CA,0x52CB,0x52CC,0x52CD,0x52CE,0x52CF, + 0x52D0,0x52D1,0x52D2,0x52D3,0x52D4,0x52D5,0x52D6,0x52D7,0x52D8,0x52D9,0x52DA,0x52DB,0x52DC,0x52DD,0x52DE,0x52DF, + 0x52E0,0x52E1,0x52E2,0x52E3,0x52E4,0x52E5,0x52E6,0x52E7,0x52E8,0x52E9,0x52EA,0x52EB,0x52EC,0x52ED,0x52EE,0x52EF, + 0x52F0,0x52F1,0x52F2,0x52F3,0x52F4,0x52F5,0x52F6,0x52F7,0x52F8,0x52F9,0x52FA,0x52FB,0x52FC,0x52FD,0x52FE,0x52FF, + 0x5300,0x5301,0x5302,0x5303,0x5304,0x5305,0x5306,0x5307,0x5308,0x5309,0x530A,0x530B,0x530C,0x530D,0x530E,0x530F, + 0x5310,0x5311,0x5312,0x5313,0x5314,0x5315,0x5316,0x5317,0x5318,0x5319,0x531A,0x531B,0x531C,0x531D,0x531E,0x531F, + 0x5320,0x5321,0x5322,0x5323,0x5324,0x5325,0x5326,0x5327,0x5328,0x5329,0x532A,0x532B,0x532C,0x532D,0x532E,0x532F, + 0x5330,0x5331,0x5332,0x5333,0x5334,0x5335,0x5336,0x5337,0x5338,0x5339,0x533A,0x533B,0x533C,0x533D,0x533E,0x533F, + 0x5340,0x5341,0x5342,0x5343,0x5344,0x5345,0x5346,0x5347,0x5348,0x5349,0x534A,0x534B,0x534C,0x534D,0x534E,0x534F, + 0x5350,0x5351,0x5352,0x5353,0x5354,0x5355,0x5356,0x5357,0x5358,0x5359,0x535A,0x535B,0x535C,0x535D,0x535E,0x535F, + 0x5360,0x5361,0x5362,0x5363,0x5364,0x5365,0x5366,0x5367,0x5368,0x5369,0x536A,0x536B,0x536C,0x536D,0x536E,0x536F, + 0x5370,0x5371,0x5372,0x5373,0x5374,0x5375,0x5376,0x5377,0x5378,0x5379,0x537A,0x537B,0x537C,0x537D,0x537E,0x537F, + 0x5380,0x5381,0x5382,0x5383,0x5384,0x5385,0x5386,0x5387,0x5388,0x5389,0x538A,0x538B,0x538C,0x538D,0x538E,0x538F, + 0x5390,0x5391,0x5392,0x5393,0x5394,0x5395,0x5396,0x5397,0x5398,0x5399,0x539A,0x539B,0x539C,0x539D,0x539E,0x539F, + 0x53A0,0x53A1,0x53A2,0x53A3,0x53A4,0x53A5,0x53A6,0x53A7,0x53A8,0x53A9,0x53AA,0x53AB,0x53AC,0x53AD,0x53AE,0x53AF, + 0x53B0,0x53B1,0x53B2,0x53B3,0x53B4,0x53B5,0x53B6,0x53B7,0x53B8,0x53B9,0x53BA,0x53BB,0x53BC,0x53BD,0x53BE,0x53BF, + 0x53C0,0x53C1,0x53C2,0x53C3,0x53C4,0x53C5,0x53C6,0x53C7,0x53C8,0x53C9,0x53CA,0x53CB,0x53CC,0x53CD,0x53CE,0x53CF, + 0x53D0,0x53D1,0x53D2,0x53D3,0x53D4,0x53D5,0x53D6,0x53D7,0x53D8,0x53D9,0x53DA,0x53DB,0x53DC,0x53DD,0x53DE,0x53DF, + 0x53E0,0x53E1,0x53E2,0x53E3,0x53E4,0x53E5,0x53E6,0x53E7,0x53E8,0x53E9,0x53EA,0x53EB,0x53EC,0x53ED,0x53EE,0x53EF, + 0x53F0,0x53F1,0x53F2,0x53F3,0x53F4,0x53F5,0x53F6,0x53F7,0x53F8,0x53F9,0x53FA,0x53FB,0x53FC,0x53FD,0x53FE,0x53FF, + 0x5400,0x5401,0x5402,0x5403,0x5404,0x5405,0x5406,0x5407,0x5408,0x5409,0x540A,0x540B,0x540C,0x540D,0x540E,0x540F, + 0x5410,0x5411,0x5412,0x5413,0x5414,0x5415,0x5416,0x5417,0x5418,0x5419,0x541A,0x541B,0x541C,0x541D,0x541E,0x541F, + 0x5420,0x5421,0x5422,0x5423,0x5424,0x5425,0x5426,0x5427,0x5428,0x5429,0x542A,0x542B,0x542C,0x542D,0x542E,0x542F, + 0x5430,0x5431,0x5432,0x5433,0x5434,0x5435,0x5436,0x5437,0x5438,0x5439,0x543A,0x543B,0x543C,0x543D,0x543E,0x543F, + 0x5440,0x5441,0x5442,0x5443,0x5444,0x5445,0x5446,0x5447,0x5448,0x5449,0x544A,0x544B,0x544C,0x544D,0x544E,0x544F, + 0x5450,0x5451,0x5452,0x5453,0x5454,0x5455,0x5456,0x5457,0x5458,0x5459,0x545A,0x545B,0x545C,0x545D,0x545E,0x545F, + 0x5460,0x5461,0x5462,0x5463,0x5464,0x5465,0x5466,0x5467,0x5468,0x5469,0x546A,0x546B,0x546C,0x546D,0x546E,0x546F, + 0x5470,0x5471,0x5472,0x5473,0x5474,0x5475,0x5476,0x5477,0x5478,0x5479,0x547A,0x547B,0x547C,0x547D,0x547E,0x547F, + 0x5480,0x5481,0x5482,0x5483,0x5484,0x5485,0x5486,0x5487,0x5488,0x5489,0x548A,0x548B,0x548C,0x548D,0x548E,0x548F, + 0x5490,0x5491,0x5492,0x5493,0x5494,0x5495,0x5496,0x5497,0x5498,0x5499,0x549A,0x549B,0x549C,0x549D,0x549E,0x549F, + 0x54A0,0x54A1,0x54A2,0x54A3,0x54A4,0x54A5,0x54A6,0x54A7,0x54A8,0x54A9,0x54AA,0x54AB,0x54AC,0x54AD,0x54AE,0x54AF, + 0x54B0,0x54B1,0x54B2,0x54B3,0x54B4,0x54B5,0x54B6,0x54B7,0x54B8,0x54B9,0x54BA,0x54BB,0x54BC,0x54BD,0x54BE,0x54BF, + 0x54C0,0x54C1,0x54C2,0x54C3,0x54C4,0x54C5,0x54C6,0x54C7,0x54C8,0x54C9,0x54CA,0x54CB,0x54CC,0x54CD,0x54CE,0x54CF, + 0x54D0,0x54D1,0x54D2,0x54D3,0x54D4,0x54D5,0x54D6,0x54D7,0x54D8,0x54D9,0x54DA,0x54DB,0x54DC,0x54DD,0x54DE,0x54DF, + 0x54E0,0x54E1,0x54E2,0x54E3,0x54E4,0x54E5,0x54E6,0x54E7,0x54E8,0x54E9,0x54EA,0x54EB,0x54EC,0x54ED,0x54EE,0x54EF, + 0x54F0,0x54F1,0x54F2,0x54F3,0x54F4,0x54F5,0x54F6,0x54F7,0x54F8,0x54F9,0x54FA,0x54FB,0x54FC,0x54FD,0x54FE,0x54FF, + 0x5500,0x5501,0x5502,0x5503,0x5504,0x5505,0x5506,0x5507,0x5508,0x5509,0x550A,0x550B,0x550C,0x550D,0x550E,0x550F, + 0x5510,0x5511,0x5512,0x5513,0x5514,0x5515,0x5516,0x5517,0x5518,0x5519,0x551A,0x551B,0x551C,0x551D,0x551E,0x551F, + 0x5520,0x5521,0x5522,0x5523,0x5524,0x5525,0x5526,0x5527,0x5528,0x5529,0x552A,0x552B,0x552C,0x552D,0x552E,0x552F, + 0x5530,0x5531,0x5532,0x5533,0x5534,0x5535,0x5536,0x5537,0x5538,0x5539,0x553A,0x553B,0x553C,0x553D,0x553E,0x553F, + 0x5540,0x5541,0x5542,0x5543,0x5544,0x5545,0x5546,0x5547,0x5548,0x5549,0x554A,0x554B,0x554C,0x554D,0x554E,0x554F, + 0x5550,0x5551,0x5552,0x5553,0x5554,0x5555,0x5556,0x5557,0x5558,0x5559,0x555A,0x555B,0x555C,0x555D,0x555E,0x555F, + 0x5560,0x5561,0x5562,0x5563,0x5564,0x5565,0x5566,0x5567,0x5568,0x5569,0x556A,0x556B,0x556C,0x556D,0x556E,0x556F, + 0x5570,0x5571,0x5572,0x5573,0x5574,0x5575,0x5576,0x5577,0x5578,0x5579,0x557A,0x557B,0x557C,0x557D,0x557E,0x557F, + 0x5580,0x5581,0x5582,0x5583,0x5584,0x5585,0x5586,0x5587,0x5588,0x5589,0x558A,0x558B,0x558C,0x558D,0x558E,0x558F, + 0x5590,0x5591,0x5592,0x5593,0x5594,0x5595,0x5596,0x5597,0x5598,0x5599,0x559A,0x559B,0x559C,0x559D,0x559E,0x559F, + 0x55A0,0x55A1,0x55A2,0x55A3,0x55A4,0x55A5,0x55A6,0x55A7,0x55A8,0x55A9,0x55AA,0x55AB,0x55AC,0x55AD,0x55AE,0x55AF, + 0x55B0,0x55B1,0x55B2,0x55B3,0x55B4,0x55B5,0x55B6,0x55B7,0x55B8,0x55B9,0x55BA,0x55BB,0x55BC,0x55BD,0x55BE,0x55BF, + 0x55C0,0x55C1,0x55C2,0x55C3,0x55C4,0x55C5,0x55C6,0x55C7,0x55C8,0x55C9,0x55CA,0x55CB,0x55CC,0x55CD,0x55CE,0x55CF, + 0x55D0,0x55D1,0x55D2,0x55D3,0x55D4,0x55D5,0x55D6,0x55D7,0x55D8,0x55D9,0x55DA,0x55DB,0x55DC,0x55DD,0x55DE,0x55DF, + 0x55E0,0x55E1,0x55E2,0x55E3,0x55E4,0x55E5,0x55E6,0x55E7,0x55E8,0x55E9,0x55EA,0x55EB,0x55EC,0x55ED,0x55EE,0x55EF, + 0x55F0,0x55F1,0x55F2,0x55F3,0x55F4,0x55F5,0x55F6,0x55F7,0x55F8,0x55F9,0x55FA,0x55FB,0x55FC,0x55FD,0x55FE,0x55FF, + 0x5600,0x5601,0x5602,0x5603,0x5604,0x5605,0x5606,0x5607,0x5608,0x5609,0x560A,0x560B,0x560C,0x560D,0x560E,0x560F, + 0x5610,0x5611,0x5612,0x5613,0x5614,0x5615,0x5616,0x5617,0x5618,0x5619,0x561A,0x561B,0x561C,0x561D,0x561E,0x561F, + 0x5620,0x5621,0x5622,0x5623,0x5624,0x5625,0x5626,0x5627,0x5628,0x5629,0x562A,0x562B,0x562C,0x562D,0x562E,0x562F, + 0x5630,0x5631,0x5632,0x5633,0x5634,0x5635,0x5636,0x5637,0x5638,0x5639,0x563A,0x563B,0x563C,0x563D,0x563E,0x563F, + 0x5640,0x5641,0x5642,0x5643,0x5644,0x5645,0x5646,0x5647,0x5648,0x5649,0x564A,0x564B,0x564C,0x564D,0x564E,0x564F, + 0x5650,0x5651,0x5652,0x5653,0x5654,0x5655,0x5656,0x5657,0x5658,0x5659,0x565A,0x565B,0x565C,0x565D,0x565E,0x565F, + 0x5660,0x5661,0x5662,0x5663,0x5664,0x5665,0x5666,0x5667,0x5668,0x5669,0x566A,0x566B,0x566C,0x566D,0x566E,0x566F, + 0x5670,0x5671,0x5672,0x5673,0x5674,0x5675,0x5676,0x5677,0x5678,0x5679,0x567A,0x567B,0x567C,0x567D,0x567E,0x567F, + 0x5680,0x5681,0x5682,0x5683,0x5684,0x5685,0x5686,0x5687,0x5688,0x5689,0x568A,0x568B,0x568C,0x568D,0x568E,0x568F, + 0x5690,0x5691,0x5692,0x5693,0x5694,0x5695,0x5696,0x5697,0x5698,0x5699,0x569A,0x569B,0x569C,0x569D,0x569E,0x569F, + 0x56A0,0x56A1,0x56A2,0x56A3,0x56A4,0x56A5,0x56A6,0x56A7,0x56A8,0x56A9,0x56AA,0x56AB,0x56AC,0x56AD,0x56AE,0x56AF, + 0x56B0,0x56B1,0x56B2,0x56B3,0x56B4,0x56B5,0x56B6,0x56B7,0x56B8,0x56B9,0x56BA,0x56BB,0x56BC,0x56BD,0x56BE,0x56BF, + 0x56C0,0x56C1,0x56C2,0x56C3,0x56C4,0x56C5,0x56C6,0x56C7,0x56C8,0x56C9,0x56CA,0x56CB,0x56CC,0x56CD,0x56CE,0x56CF, + 0x56D0,0x56D1,0x56D2,0x56D3,0x56D4,0x56D5,0x56D6,0x56D7,0x56D8,0x56D9,0x56DA,0x56DB,0x56DC,0x56DD,0x56DE,0x56DF, + 0x56E0,0x56E1,0x56E2,0x56E3,0x56E4,0x56E5,0x56E6,0x56E7,0x56E8,0x56E9,0x56EA,0x56EB,0x56EC,0x56ED,0x56EE,0x56EF, + 0x56F0,0x56F1,0x56F2,0x56F3,0x56F4,0x56F5,0x56F6,0x56F7,0x56F8,0x56F9,0x56FA,0x56FB,0x56FC,0x56FD,0x56FE,0x56FF, + 0x5700,0x5701,0x5702,0x5703,0x5704,0x5705,0x5706,0x5707,0x5708,0x5709,0x570A,0x570B,0x570C,0x570D,0x570E,0x570F, + 0x5710,0x5711,0x5712,0x5713,0x5714,0x5715,0x5716,0x5717,0x5718,0x5719,0x571A,0x571B,0x571C,0x571D,0x571E,0x571F, + 0x5720,0x5721,0x5722,0x5723,0x5724,0x5725,0x5726,0x5727,0x5728,0x5729,0x572A,0x572B,0x572C,0x572D,0x572E,0x572F, + 0x5730,0x5731,0x5732,0x5733,0x5734,0x5735,0x5736,0x5737,0x5738,0x5739,0x573A,0x573B,0x573C,0x573D,0x573E,0x573F, + 0x5740,0x5741,0x5742,0x5743,0x5744,0x5745,0x5746,0x5747,0x5748,0x5749,0x574A,0x574B,0x574C,0x574D,0x574E,0x574F, + 0x5750,0x5751,0x5752,0x5753,0x5754,0x5755,0x5756,0x5757,0x5758,0x5759,0x575A,0x575B,0x575C,0x575D,0x575E,0x575F, + 0x5760,0x5761,0x5762,0x5763,0x5764,0x5765,0x5766,0x5767,0x5768,0x5769,0x576A,0x576B,0x576C,0x576D,0x576E,0x576F, + 0x5770,0x5771,0x5772,0x5773,0x5774,0x5775,0x5776,0x5777,0x5778,0x5779,0x577A,0x577B,0x577C,0x577D,0x577E,0x577F, + 0x5780,0x5781,0x5782,0x5783,0x5784,0x5785,0x5786,0x5787,0x5788,0x5789,0x578A,0x578B,0x578C,0x578D,0x578E,0x578F, + 0x5790,0x5791,0x5792,0x5793,0x5794,0x5795,0x5796,0x5797,0x5798,0x5799,0x579A,0x579B,0x579C,0x579D,0x579E,0x579F, + 0x57A0,0x57A1,0x57A2,0x57A3,0x57A4,0x57A5,0x57A6,0x57A7,0x57A8,0x57A9,0x57AA,0x57AB,0x57AC,0x57AD,0x57AE,0x57AF, + 0x57B0,0x57B1,0x57B2,0x57B3,0x57B4,0x57B5,0x57B6,0x57B7,0x57B8,0x57B9,0x57BA,0x57BB,0x57BC,0x57BD,0x57BE,0x57BF, + 0x57C0,0x57C1,0x57C2,0x57C3,0x57C4,0x57C5,0x57C6,0x57C7,0x57C8,0x57C9,0x57CA,0x57CB,0x57CC,0x57CD,0x57CE,0x57CF, + 0x57D0,0x57D1,0x57D2,0x57D3,0x57D4,0x57D5,0x57D6,0x57D7,0x57D8,0x57D9,0x57DA,0x57DB,0x57DC,0x57DD,0x57DE,0x57DF, + 0x57E0,0x57E1,0x57E2,0x57E3,0x57E4,0x57E5,0x57E6,0x57E7,0x57E8,0x57E9,0x57EA,0x57EB,0x57EC,0x57ED,0x57EE,0x57EF, + 0x57F0,0x57F1,0x57F2,0x57F3,0x57F4,0x57F5,0x57F6,0x57F7,0x57F8,0x57F9,0x57FA,0x57FB,0x57FC,0x57FD,0x57FE,0x57FF, + 0x5800,0x5801,0x5802,0x5803,0x5804,0x5805,0x5806,0x5807,0x5808,0x5809,0x580A,0x580B,0x580C,0x580D,0x580E,0x580F, + 0x5810,0x5811,0x5812,0x5813,0x5814,0x5815,0x5816,0x5817,0x5818,0x5819,0x581A,0x581B,0x581C,0x581D,0x581E,0x581F, + 0x5820,0x5821,0x5822,0x5823,0x5824,0x5825,0x5826,0x5827,0x5828,0x5829,0x582A,0x582B,0x582C,0x582D,0x582E,0x582F, + 0x5830,0x5831,0x5832,0x5833,0x5834,0x5835,0x5836,0x5837,0x5838,0x5839,0x583A,0x583B,0x583C,0x583D,0x583E,0x583F, + 0x5840,0x5841,0x5842,0x5843,0x5844,0x5845,0x5846,0x5847,0x5848,0x5849,0x584A,0x584B,0x584C,0x584D,0x584E,0x584F, + 0x5850,0x5851,0x5852,0x5853,0x5854,0x5855,0x5856,0x5857,0x5858,0x5859,0x585A,0x585B,0x585C,0x585D,0x585E,0x585F, + 0x5860,0x5861,0x5862,0x5863,0x5864,0x5865,0x5866,0x5867,0x5868,0x5869,0x586A,0x586B,0x586C,0x586D,0x586E,0x586F, + 0x5870,0x5871,0x5872,0x5873,0x5874,0x5875,0x5876,0x5877,0x5878,0x5879,0x587A,0x587B,0x587C,0x587D,0x587E,0x587F, + 0x5880,0x5881,0x5882,0x5883,0x5884,0x5885,0x5886,0x5887,0x5888,0x5889,0x588A,0x588B,0x588C,0x588D,0x588E,0x588F, + 0x5890,0x5891,0x5892,0x5893,0x5894,0x5895,0x5896,0x5897,0x5898,0x5899,0x589A,0x589B,0x589C,0x589D,0x589E,0x589F, + 0x58A0,0x58A1,0x58A2,0x58A3,0x58A4,0x58A5,0x58A6,0x58A7,0x58A8,0x58A9,0x58AA,0x58AB,0x58AC,0x58AD,0x58AE,0x58AF, + 0x58B0,0x58B1,0x58B2,0x58B3,0x58B4,0x58B5,0x58B6,0x58B7,0x58B8,0x58B9,0x58BA,0x58BB,0x58BC,0x58BD,0x58BE,0x58BF, + 0x58C0,0x58C1,0x58C2,0x58C3,0x58C4,0x58C5,0x58C6,0x58C7,0x58C8,0x58C9,0x58CA,0x58CB,0x58CC,0x58CD,0x58CE,0x58CF, + 0x58D0,0x58D1,0x58D2,0x58D3,0x58D4,0x58D5,0x58D6,0x58D7,0x58D8,0x58D9,0x58DA,0x58DB,0x58DC,0x58DD,0x58DE,0x58DF, + 0x58E0,0x58E1,0x58E2,0x58E3,0x58E4,0x58E5,0x58E6,0x58E7,0x58E8,0x58E9,0x58EA,0x58EB,0x58EC,0x58ED,0x58EE,0x58EF, + 0x58F0,0x58F1,0x58F2,0x58F3,0x58F4,0x58F5,0x58F6,0x58F7,0x58F8,0x58F9,0x58FA,0x58FB,0x58FC,0x58FD,0x58FE,0x58FF, + 0x5900,0x5901,0x5902,0x5903,0x5904,0x5905,0x5906,0x5907,0x5908,0x5909,0x590A,0x590B,0x590C,0x590D,0x590E,0x590F, + 0x5910,0x5911,0x5912,0x5913,0x5914,0x5915,0x5916,0x5917,0x5918,0x5919,0x591A,0x591B,0x591C,0x591D,0x591E,0x591F, + 0x5920,0x5921,0x5922,0x5923,0x5924,0x5925,0x5926,0x5927,0x5928,0x5929,0x592A,0x592B,0x592C,0x592D,0x592E,0x592F, + 0x5930,0x5931,0x5932,0x5933,0x5934,0x5935,0x5936,0x5937,0x5938,0x5939,0x593A,0x593B,0x593C,0x593D,0x593E,0x593F, + 0x5940,0x5941,0x5942,0x5943,0x5944,0x5945,0x5946,0x5947,0x5948,0x5949,0x594A,0x594B,0x594C,0x594D,0x594E,0x594F, + 0x5950,0x5951,0x5952,0x5953,0x5954,0x5955,0x5956,0x5957,0x5958,0x5959,0x595A,0x595B,0x595C,0x595D,0x595E,0x595F, + 0x5960,0x5961,0x5962,0x5963,0x5964,0x5965,0x5966,0x5967,0x5968,0x5969,0x596A,0x596B,0x596C,0x596D,0x596E,0x596F, + 0x5970,0x5971,0x5972,0x5973,0x5974,0x5975,0x5976,0x5977,0x5978,0x5979,0x597A,0x597B,0x597C,0x597D,0x597E,0x597F, + 0x5980,0x5981,0x5982,0x5983,0x5984,0x5985,0x5986,0x5987,0x5988,0x5989,0x598A,0x598B,0x598C,0x598D,0x598E,0x598F, + 0x5990,0x5991,0x5992,0x5993,0x5994,0x5995,0x5996,0x5997,0x5998,0x5999,0x599A,0x599B,0x599C,0x599D,0x599E,0x599F, + 0x59A0,0x59A1,0x59A2,0x59A3,0x59A4,0x59A5,0x59A6,0x59A7,0x59A8,0x59A9,0x59AA,0x59AB,0x59AC,0x59AD,0x59AE,0x59AF, + 0x59B0,0x59B1,0x59B2,0x59B3,0x59B4,0x59B5,0x59B6,0x59B7,0x59B8,0x59B9,0x59BA,0x59BB,0x59BC,0x59BD,0x59BE,0x59BF, + 0x59C0,0x59C1,0x59C2,0x59C3,0x59C4,0x59C5,0x59C6,0x59C7,0x59C8,0x59C9,0x59CA,0x59CB,0x59CC,0x59CD,0x59CE,0x59CF, + 0x59D0,0x59D1,0x59D2,0x59D3,0x59D4,0x59D5,0x59D6,0x59D7,0x59D8,0x59D9,0x59DA,0x59DB,0x59DC,0x59DD,0x59DE,0x59DF, + 0x59E0,0x59E1,0x59E2,0x59E3,0x59E4,0x59E5,0x59E6,0x59E7,0x59E8,0x59E9,0x59EA,0x59EB,0x59EC,0x59ED,0x59EE,0x59EF, + 0x59F0,0x59F1,0x59F2,0x59F3,0x59F4,0x59F5,0x59F6,0x59F7,0x59F8,0x59F9,0x59FA,0x59FB,0x59FC,0x59FD,0x59FE,0x59FF, + 0x5A00,0x5A01,0x5A02,0x5A03,0x5A04,0x5A05,0x5A06,0x5A07,0x5A08,0x5A09,0x5A0A,0x5A0B,0x5A0C,0x5A0D,0x5A0E,0x5A0F, + 0x5A10,0x5A11,0x5A12,0x5A13,0x5A14,0x5A15,0x5A16,0x5A17,0x5A18,0x5A19,0x5A1A,0x5A1B,0x5A1C,0x5A1D,0x5A1E,0x5A1F, + 0x5A20,0x5A21,0x5A22,0x5A23,0x5A24,0x5A25,0x5A26,0x5A27,0x5A28,0x5A29,0x5A2A,0x5A2B,0x5A2C,0x5A2D,0x5A2E,0x5A2F, + 0x5A30,0x5A31,0x5A32,0x5A33,0x5A34,0x5A35,0x5A36,0x5A37,0x5A38,0x5A39,0x5A3A,0x5A3B,0x5A3C,0x5A3D,0x5A3E,0x5A3F, + 0x5A40,0x5A41,0x5A42,0x5A43,0x5A44,0x5A45,0x5A46,0x5A47,0x5A48,0x5A49,0x5A4A,0x5A4B,0x5A4C,0x5A4D,0x5A4E,0x5A4F, + 0x5A50,0x5A51,0x5A52,0x5A53,0x5A54,0x5A55,0x5A56,0x5A57,0x5A58,0x5A59,0x5A5A,0x5A5B,0x5A5C,0x5A5D,0x5A5E,0x5A5F, + 0x5A60,0x5A61,0x5A62,0x5A63,0x5A64,0x5A65,0x5A66,0x5A67,0x5A68,0x5A69,0x5A6A,0x5A6B,0x5A6C,0x5A6D,0x5A6E,0x5A6F, + 0x5A70,0x5A71,0x5A72,0x5A73,0x5A74,0x5A75,0x5A76,0x5A77,0x5A78,0x5A79,0x5A7A,0x5A7B,0x5A7C,0x5A7D,0x5A7E,0x5A7F, + 0x5A80,0x5A81,0x5A82,0x5A83,0x5A84,0x5A85,0x5A86,0x5A87,0x5A88,0x5A89,0x5A8A,0x5A8B,0x5A8C,0x5A8D,0x5A8E,0x5A8F, + 0x5A90,0x5A91,0x5A92,0x5A93,0x5A94,0x5A95,0x5A96,0x5A97,0x5A98,0x5A99,0x5A9A,0x5A9B,0x5A9C,0x5A9D,0x5A9E,0x5A9F, + 0x5AA0,0x5AA1,0x5AA2,0x5AA3,0x5AA4,0x5AA5,0x5AA6,0x5AA7,0x5AA8,0x5AA9,0x5AAA,0x5AAB,0x5AAC,0x5AAD,0x5AAE,0x5AAF, + 0x5AB0,0x5AB1,0x5AB2,0x5AB3,0x5AB4,0x5AB5,0x5AB6,0x5AB7,0x5AB8,0x5AB9,0x5ABA,0x5ABB,0x5ABC,0x5ABD,0x5ABE,0x5ABF, + 0x5AC0,0x5AC1,0x5AC2,0x5AC3,0x5AC4,0x5AC5,0x5AC6,0x5AC7,0x5AC8,0x5AC9,0x5ACA,0x5ACB,0x5ACC,0x5ACD,0x5ACE,0x5ACF, + 0x5AD0,0x5AD1,0x5AD2,0x5AD3,0x5AD4,0x5AD5,0x5AD6,0x5AD7,0x5AD8,0x5AD9,0x5ADA,0x5ADB,0x5ADC,0x5ADD,0x5ADE,0x5ADF, + 0x5AE0,0x5AE1,0x5AE2,0x5AE3,0x5AE4,0x5AE5,0x5AE6,0x5AE7,0x5AE8,0x5AE9,0x5AEA,0x5AEB,0x5AEC,0x5AED,0x5AEE,0x5AEF, + 0x5AF0,0x5AF1,0x5AF2,0x5AF3,0x5AF4,0x5AF5,0x5AF6,0x5AF7,0x5AF8,0x5AF9,0x5AFA,0x5AFB,0x5AFC,0x5AFD,0x5AFE,0x5AFF, + 0x5B00,0x5B01,0x5B02,0x5B03,0x5B04,0x5B05,0x5B06,0x5B07,0x5B08,0x5B09,0x5B0A,0x5B0B,0x5B0C,0x5B0D,0x5B0E,0x5B0F, + 0x5B10,0x5B11,0x5B12,0x5B13,0x5B14,0x5B15,0x5B16,0x5B17,0x5B18,0x5B19,0x5B1A,0x5B1B,0x5B1C,0x5B1D,0x5B1E,0x5B1F, + 0x5B20,0x5B21,0x5B22,0x5B23,0x5B24,0x5B25,0x5B26,0x5B27,0x5B28,0x5B29,0x5B2A,0x5B2B,0x5B2C,0x5B2D,0x5B2E,0x5B2F, + 0x5B30,0x5B31,0x5B32,0x5B33,0x5B34,0x5B35,0x5B36,0x5B37,0x5B38,0x5B39,0x5B3A,0x5B3B,0x5B3C,0x5B3D,0x5B3E,0x5B3F, + 0x5B40,0x5B41,0x5B42,0x5B43,0x5B44,0x5B45,0x5B46,0x5B47,0x5B48,0x5B49,0x5B4A,0x5B4B,0x5B4C,0x5B4D,0x5B4E,0x5B4F, + 0x5B50,0x5B51,0x5B52,0x5B53,0x5B54,0x5B55,0x5B56,0x5B57,0x5B58,0x5B59,0x5B5A,0x5B5B,0x5B5C,0x5B5D,0x5B5E,0x5B5F, + 0x5B60,0x5B61,0x5B62,0x5B63,0x5B64,0x5B65,0x5B66,0x5B67,0x5B68,0x5B69,0x5B6A,0x5B6B,0x5B6C,0x5B6D,0x5B6E,0x5B6F, + 0x5B70,0x5B71,0x5B72,0x5B73,0x5B74,0x5B75,0x5B76,0x5B77,0x5B78,0x5B79,0x5B7A,0x5B7B,0x5B7C,0x5B7D,0x5B7E,0x5B7F, + 0x5B80,0x5B81,0x5B82,0x5B83,0x5B84,0x5B85,0x5B86,0x5B87,0x5B88,0x5B89,0x5B8A,0x5B8B,0x5B8C,0x5B8D,0x5B8E,0x5B8F, + 0x5B90,0x5B91,0x5B92,0x5B93,0x5B94,0x5B95,0x5B96,0x5B97,0x5B98,0x5B99,0x5B9A,0x5B9B,0x5B9C,0x5B9D,0x5B9E,0x5B9F, + 0x5BA0,0x5BA1,0x5BA2,0x5BA3,0x5BA4,0x5BA5,0x5BA6,0x5BA7,0x5BA8,0x5BA9,0x5BAA,0x5BAB,0x5BAC,0x5BAD,0x5BAE,0x5BAF, + 0x5BB0,0x5BB1,0x5BB2,0x5BB3,0x5BB4,0x5BB5,0x5BB6,0x5BB7,0x5BB8,0x5BB9,0x5BBA,0x5BBB,0x5BBC,0x5BBD,0x5BBE,0x5BBF, + 0x5BC0,0x5BC1,0x5BC2,0x5BC3,0x5BC4,0x5BC5,0x5BC6,0x5BC7,0x5BC8,0x5BC9,0x5BCA,0x5BCB,0x5BCC,0x5BCD,0x5BCE,0x5BCF, + 0x5BD0,0x5BD1,0x5BD2,0x5BD3,0x5BD4,0x5BD5,0x5BD6,0x5BD7,0x5BD8,0x5BD9,0x5BDA,0x5BDB,0x5BDC,0x5BDD,0x5BDE,0x5BDF, + 0x5BE0,0x5BE1,0x5BE2,0x5BE3,0x5BE4,0x5BE5,0x5BE6,0x5BE7,0x5BE8,0x5BE9,0x5BEA,0x5BEB,0x5BEC,0x5BED,0x5BEE,0x5BEF, + 0x5BF0,0x5BF1,0x5BF2,0x5BF3,0x5BF4,0x5BF5,0x5BF6,0x5BF7,0x5BF8,0x5BF9,0x5BFA,0x5BFB,0x5BFC,0x5BFD,0x5BFE,0x5BFF, + 0x5C00,0x5C01,0x5C02,0x5C03,0x5C04,0x5C05,0x5C06,0x5C07,0x5C08,0x5C09,0x5C0A,0x5C0B,0x5C0C,0x5C0D,0x5C0E,0x5C0F, + 0x5C10,0x5C11,0x5C12,0x5C13,0x5C14,0x5C15,0x5C16,0x5C17,0x5C18,0x5C19,0x5C1A,0x5C1B,0x5C1C,0x5C1D,0x5C1E,0x5C1F, + 0x5C20,0x5C21,0x5C22,0x5C23,0x5C24,0x5C25,0x5C26,0x5C27,0x5C28,0x5C29,0x5C2A,0x5C2B,0x5C2C,0x5C2D,0x5C2E,0x5C2F, + 0x5C30,0x5C31,0x5C32,0x5C33,0x5C34,0x5C35,0x5C36,0x5C37,0x5C38,0x5C39,0x5C3A,0x5C3B,0x5C3C,0x5C3D,0x5C3E,0x5C3F, + 0x5C40,0x5C41,0x5C42,0x5C43,0x5C44,0x5C45,0x5C46,0x5C47,0x5C48,0x5C49,0x5C4A,0x5C4B,0x5C4C,0x5C4D,0x5C4E,0x5C4F, + 0x5C50,0x5C51,0x5C52,0x5C53,0x5C54,0x5C55,0x5C56,0x5C57,0x5C58,0x5C59,0x5C5A,0x5C5B,0x5C5C,0x5C5D,0x5C5E,0x5C5F, + 0x5C60,0x5C61,0x5C62,0x5C63,0x5C64,0x5C65,0x5C66,0x5C67,0x5C68,0x5C69,0x5C6A,0x5C6B,0x5C6C,0x5C6D,0x5C6E,0x5C6F, + 0x5C70,0x5C71,0x5C72,0x5C73,0x5C74,0x5C75,0x5C76,0x5C77,0x5C78,0x5C79,0x5C7A,0x5C7B,0x5C7C,0x5C7D,0x5C7E,0x5C7F, + 0x5C80,0x5C81,0x5C82,0x5C83,0x5C84,0x5C85,0x5C86,0x5C87,0x5C88,0x5C89,0x5C8A,0x5C8B,0x5C8C,0x5C8D,0x5C8E,0x5C8F, + 0x5C90,0x5C91,0x5C92,0x5C93,0x5C94,0x5C95,0x5C96,0x5C97,0x5C98,0x5C99,0x5C9A,0x5C9B,0x5C9C,0x5C9D,0x5C9E,0x5C9F, + 0x5CA0,0x5CA1,0x5CA2,0x5CA3,0x5CA4,0x5CA5,0x5CA6,0x5CA7,0x5CA8,0x5CA9,0x5CAA,0x5CAB,0x5CAC,0x5CAD,0x5CAE,0x5CAF, + 0x5CB0,0x5CB1,0x5CB2,0x5CB3,0x5CB4,0x5CB5,0x5CB6,0x5CB7,0x5CB8,0x5CB9,0x5CBA,0x5CBB,0x5CBC,0x5CBD,0x5CBE,0x5CBF, + 0x5CC0,0x5CC1,0x5CC2,0x5CC3,0x5CC4,0x5CC5,0x5CC6,0x5CC7,0x5CC8,0x5CC9,0x5CCA,0x5CCB,0x5CCC,0x5CCD,0x5CCE,0x5CCF, + 0x5CD0,0x5CD1,0x5CD2,0x5CD3,0x5CD4,0x5CD5,0x5CD6,0x5CD7,0x5CD8,0x5CD9,0x5CDA,0x5CDB,0x5CDC,0x5CDD,0x5CDE,0x5CDF, + 0x5CE0,0x5CE1,0x5CE2,0x5CE3,0x5CE4,0x5CE5,0x5CE6,0x5CE7,0x5CE8,0x5CE9,0x5CEA,0x5CEB,0x5CEC,0x5CED,0x5CEE,0x5CEF, + 0x5CF0,0x5CF1,0x5CF2,0x5CF3,0x5CF4,0x5CF5,0x5CF6,0x5CF7,0x5CF8,0x5CF9,0x5CFA,0x5CFB,0x5CFC,0x5CFD,0x5CFE,0x5CFF, + 0x5D00,0x5D01,0x5D02,0x5D03,0x5D04,0x5D05,0x5D06,0x5D07,0x5D08,0x5D09,0x5D0A,0x5D0B,0x5D0C,0x5D0D,0x5D0E,0x5D0F, + 0x5D10,0x5D11,0x5D12,0x5D13,0x5D14,0x5D15,0x5D16,0x5D17,0x5D18,0x5D19,0x5D1A,0x5D1B,0x5D1C,0x5D1D,0x5D1E,0x5D1F, + 0x5D20,0x5D21,0x5D22,0x5D23,0x5D24,0x5D25,0x5D26,0x5D27,0x5D28,0x5D29,0x5D2A,0x5D2B,0x5D2C,0x5D2D,0x5D2E,0x5D2F, + 0x5D30,0x5D31,0x5D32,0x5D33,0x5D34,0x5D35,0x5D36,0x5D37,0x5D38,0x5D39,0x5D3A,0x5D3B,0x5D3C,0x5D3D,0x5D3E,0x5D3F, + 0x5D40,0x5D41,0x5D42,0x5D43,0x5D44,0x5D45,0x5D46,0x5D47,0x5D48,0x5D49,0x5D4A,0x5D4B,0x5D4C,0x5D4D,0x5D4E,0x5D4F, + 0x5D50,0x5D51,0x5D52,0x5D53,0x5D54,0x5D55,0x5D56,0x5D57,0x5D58,0x5D59,0x5D5A,0x5D5B,0x5D5C,0x5D5D,0x5D5E,0x5D5F, + 0x5D60,0x5D61,0x5D62,0x5D63,0x5D64,0x5D65,0x5D66,0x5D67,0x5D68,0x5D69,0x5D6A,0x5D6B,0x5D6C,0x5D6D,0x5D6E,0x5D6F, + 0x5D70,0x5D71,0x5D72,0x5D73,0x5D74,0x5D75,0x5D76,0x5D77,0x5D78,0x5D79,0x5D7A,0x5D7B,0x5D7C,0x5D7D,0x5D7E,0x5D7F, + 0x5D80,0x5D81,0x5D82,0x5D83,0x5D84,0x5D85,0x5D86,0x5D87,0x5D88,0x5D89,0x5D8A,0x5D8B,0x5D8C,0x5D8D,0x5D8E,0x5D8F, + 0x5D90,0x5D91,0x5D92,0x5D93,0x5D94,0x5D95,0x5D96,0x5D97,0x5D98,0x5D99,0x5D9A,0x5D9B,0x5D9C,0x5D9D,0x5D9E,0x5D9F, + 0x5DA0,0x5DA1,0x5DA2,0x5DA3,0x5DA4,0x5DA5,0x5DA6,0x5DA7,0x5DA8,0x5DA9,0x5DAA,0x5DAB,0x5DAC,0x5DAD,0x5DAE,0x5DAF, + 0x5DB0,0x5DB1,0x5DB2,0x5DB3,0x5DB4,0x5DB5,0x5DB6,0x5DB7,0x5DB8,0x5DB9,0x5DBA,0x5DBB,0x5DBC,0x5DBD,0x5DBE,0x5DBF, + 0x5DC0,0x5DC1,0x5DC2,0x5DC3,0x5DC4,0x5DC5,0x5DC6,0x5DC7,0x5DC8,0x5DC9,0x5DCA,0x5DCB,0x5DCC,0x5DCD,0x5DCE,0x5DCF, + 0x5DD0,0x5DD1,0x5DD2,0x5DD3,0x5DD4,0x5DD5,0x5DD6,0x5DD7,0x5DD8,0x5DD9,0x5DDA,0x5DDB,0x5DDC,0x5DDD,0x5DDE,0x5DDF, + 0x5DE0,0x5DE1,0x5DE2,0x5DE3,0x5DE4,0x5DE5,0x5DE6,0x5DE7,0x5DE8,0x5DE9,0x5DEA,0x5DEB,0x5DEC,0x5DED,0x5DEE,0x5DEF, + 0x5DF0,0x5DF1,0x5DF2,0x5DF3,0x5DF4,0x5DF5,0x5DF6,0x5DF7,0x5DF8,0x5DF9,0x5DFA,0x5DFB,0x5DFC,0x5DFD,0x5DFE,0x5DFF, + 0x5E00,0x5E01,0x5E02,0x5E03,0x5E04,0x5E05,0x5E06,0x5E07,0x5E08,0x5E09,0x5E0A,0x5E0B,0x5E0C,0x5E0D,0x5E0E,0x5E0F, + 0x5E10,0x5E11,0x5E12,0x5E13,0x5E14,0x5E15,0x5E16,0x5E17,0x5E18,0x5E19,0x5E1A,0x5E1B,0x5E1C,0x5E1D,0x5E1E,0x5E1F, + 0x5E20,0x5E21,0x5E22,0x5E23,0x5E24,0x5E25,0x5E26,0x5E27,0x5E28,0x5E29,0x5E2A,0x5E2B,0x5E2C,0x5E2D,0x5E2E,0x5E2F, + 0x5E30,0x5E31,0x5E32,0x5E33,0x5E34,0x5E35,0x5E36,0x5E37,0x5E38,0x5E39,0x5E3A,0x5E3B,0x5E3C,0x5E3D,0x5E3E,0x5E3F, + 0x5E40,0x5E41,0x5E42,0x5E43,0x5E44,0x5E45,0x5E46,0x5E47,0x5E48,0x5E49,0x5E4A,0x5E4B,0x5E4C,0x5E4D,0x5E4E,0x5E4F, + 0x5E50,0x5E51,0x5E52,0x5E53,0x5E54,0x5E55,0x5E56,0x5E57,0x5E58,0x5E59,0x5E5A,0x5E5B,0x5E5C,0x5E5D,0x5E5E,0x5E5F, + 0x5E60,0x5E61,0x5E62,0x5E63,0x5E64,0x5E65,0x5E66,0x5E67,0x5E68,0x5E69,0x5E6A,0x5E6B,0x5E6C,0x5E6D,0x5E6E,0x5E6F, + 0x5E70,0x5E71,0x5E72,0x5E73,0x5E74,0x5E75,0x5E76,0x5E77,0x5E78,0x5E79,0x5E7A,0x5E7B,0x5E7C,0x5E7D,0x5E7E,0x5E7F, + 0x5E80,0x5E81,0x5E82,0x5E83,0x5E84,0x5E85,0x5E86,0x5E87,0x5E88,0x5E89,0x5E8A,0x5E8B,0x5E8C,0x5E8D,0x5E8E,0x5E8F, + 0x5E90,0x5E91,0x5E92,0x5E93,0x5E94,0x5E95,0x5E96,0x5E97,0x5E98,0x5E99,0x5E9A,0x5E9B,0x5E9C,0x5E9D,0x5E9E,0x5E9F, + 0x5EA0,0x5EA1,0x5EA2,0x5EA3,0x5EA4,0x5EA5,0x5EA6,0x5EA7,0x5EA8,0x5EA9,0x5EAA,0x5EAB,0x5EAC,0x5EAD,0x5EAE,0x5EAF, + 0x5EB0,0x5EB1,0x5EB2,0x5EB3,0x5EB4,0x5EB5,0x5EB6,0x5EB7,0x5EB8,0x5EB9,0x5EBA,0x5EBB,0x5EBC,0x5EBD,0x5EBE,0x5EBF, + 0x5EC0,0x5EC1,0x5EC2,0x5EC3,0x5EC4,0x5EC5,0x5EC6,0x5EC7,0x5EC8,0x5EC9,0x5ECA,0x5ECB,0x5ECC,0x5ECD,0x5ECE,0x5ECF, + 0x5ED0,0x5ED1,0x5ED2,0x5ED3,0x5ED4,0x5ED5,0x5ED6,0x5ED7,0x5ED8,0x5ED9,0x5EDA,0x5EDB,0x5EDC,0x5EDD,0x5EDE,0x5EDF, + 0x5EE0,0x5EE1,0x5EE2,0x5EE3,0x5EE4,0x5EE5,0x5EE6,0x5EE7,0x5EE8,0x5EE9,0x5EEA,0x5EEB,0x5EEC,0x5EED,0x5EEE,0x5EEF, + 0x5EF0,0x5EF1,0x5EF2,0x5EF3,0x5EF4,0x5EF5,0x5EF6,0x5EF7,0x5EF8,0x5EF9,0x5EFA,0x5EFB,0x5EFC,0x5EFD,0x5EFE,0x5EFF, + 0x5F00,0x5F01,0x5F02,0x5F03,0x5F04,0x5F05,0x5F06,0x5F07,0x5F08,0x5F09,0x5F0A,0x5F0B,0x5F0C,0x5F0D,0x5F0E,0x5F0F, + 0x5F10,0x5F11,0x5F12,0x5F13,0x5F14,0x5F15,0x5F16,0x5F17,0x5F18,0x5F19,0x5F1A,0x5F1B,0x5F1C,0x5F1D,0x5F1E,0x5F1F, + 0x5F20,0x5F21,0x5F22,0x5F23,0x5F24,0x5F25,0x5F26,0x5F27,0x5F28,0x5F29,0x5F2A,0x5F2B,0x5F2C,0x5F2D,0x5F2E,0x5F2F, + 0x5F30,0x5F31,0x5F32,0x5F33,0x5F34,0x5F35,0x5F36,0x5F37,0x5F38,0x5F39,0x5F3A,0x5F3B,0x5F3C,0x5F3D,0x5F3E,0x5F3F, + 0x5F40,0x5F41,0x5F42,0x5F43,0x5F44,0x5F45,0x5F46,0x5F47,0x5F48,0x5F49,0x5F4A,0x5F4B,0x5F4C,0x5F4D,0x5F4E,0x5F4F, + 0x5F50,0x5F51,0x5F52,0x5F53,0x5F54,0x5F55,0x5F56,0x5F57,0x5F58,0x5F59,0x5F5A,0x5F5B,0x5F5C,0x5F5D,0x5F5E,0x5F5F, + 0x5F60,0x5F61,0x5F62,0x5F63,0x5F64,0x5F65,0x5F66,0x5F67,0x5F68,0x5F69,0x5F6A,0x5F6B,0x5F6C,0x5F6D,0x5F6E,0x5F6F, + 0x5F70,0x5F71,0x5F72,0x5F73,0x5F74,0x5F75,0x5F76,0x5F77,0x5F78,0x5F79,0x5F7A,0x5F7B,0x5F7C,0x5F7D,0x5F7E,0x5F7F, + 0x5F80,0x5F81,0x5F82,0x5F83,0x5F84,0x5F85,0x5F86,0x5F87,0x5F88,0x5F89,0x5F8A,0x5F8B,0x5F8C,0x5F8D,0x5F8E,0x5F8F, + 0x5F90,0x5F91,0x5F92,0x5F93,0x5F94,0x5F95,0x5F96,0x5F97,0x5F98,0x5F99,0x5F9A,0x5F9B,0x5F9C,0x5F9D,0x5F9E,0x5F9F, + 0x5FA0,0x5FA1,0x5FA2,0x5FA3,0x5FA4,0x5FA5,0x5FA6,0x5FA7,0x5FA8,0x5FA9,0x5FAA,0x5FAB,0x5FAC,0x5FAD,0x5FAE,0x5FAF, + 0x5FB0,0x5FB1,0x5FB2,0x5FB3,0x5FB4,0x5FB5,0x5FB6,0x5FB7,0x5FB8,0x5FB9,0x5FBA,0x5FBB,0x5FBC,0x5FBD,0x5FBE,0x5FBF, + 0x5FC0,0x5FC1,0x5FC2,0x5FC3,0x5FC4,0x5FC5,0x5FC6,0x5FC7,0x5FC8,0x5FC9,0x5FCA,0x5FCB,0x5FCC,0x5FCD,0x5FCE,0x5FCF, + 0x5FD0,0x5FD1,0x5FD2,0x5FD3,0x5FD4,0x5FD5,0x5FD6,0x5FD7,0x5FD8,0x5FD9,0x5FDA,0x5FDB,0x5FDC,0x5FDD,0x5FDE,0x5FDF, + 0x5FE0,0x5FE1,0x5FE2,0x5FE3,0x5FE4,0x5FE5,0x5FE6,0x5FE7,0x5FE8,0x5FE9,0x5FEA,0x5FEB,0x5FEC,0x5FED,0x5FEE,0x5FEF, + 0x5FF0,0x5FF1,0x5FF2,0x5FF3,0x5FF4,0x5FF5,0x5FF6,0x5FF7,0x5FF8,0x5FF9,0x5FFA,0x5FFB,0x5FFC,0x5FFD,0x5FFE,0x5FFF, + 0x6000,0x6001,0x6002,0x6003,0x6004,0x6005,0x6006,0x6007,0x6008,0x6009,0x600A,0x600B,0x600C,0x600D,0x600E,0x600F, + 0x6010,0x6011,0x6012,0x6013,0x6014,0x6015,0x6016,0x6017,0x6018,0x6019,0x601A,0x601B,0x601C,0x601D,0x601E,0x601F, + 0x6020,0x6021,0x6022,0x6023,0x6024,0x6025,0x6026,0x6027,0x6028,0x6029,0x602A,0x602B,0x602C,0x602D,0x602E,0x602F, + 0x6030,0x6031,0x6032,0x6033,0x6034,0x6035,0x6036,0x6037,0x6038,0x6039,0x603A,0x603B,0x603C,0x603D,0x603E,0x603F, + 0x6040,0x6041,0x6042,0x6043,0x6044,0x6045,0x6046,0x6047,0x6048,0x6049,0x604A,0x604B,0x604C,0x604D,0x604E,0x604F, + 0x6050,0x6051,0x6052,0x6053,0x6054,0x6055,0x6056,0x6057,0x6058,0x6059,0x605A,0x605B,0x605C,0x605D,0x605E,0x605F, + 0x6060,0x6061,0x6062,0x6063,0x6064,0x6065,0x6066,0x6067,0x6068,0x6069,0x606A,0x606B,0x606C,0x606D,0x606E,0x606F, + 0x6070,0x6071,0x6072,0x6073,0x6074,0x6075,0x6076,0x6077,0x6078,0x6079,0x607A,0x607B,0x607C,0x607D,0x607E,0x607F, + 0x6080,0x6081,0x6082,0x6083,0x6084,0x6085,0x6086,0x6087,0x6088,0x6089,0x608A,0x608B,0x608C,0x608D,0x608E,0x608F, + 0x6090,0x6091,0x6092,0x6093,0x6094,0x6095,0x6096,0x6097,0x6098,0x6099,0x609A,0x609B,0x609C,0x609D,0x609E,0x609F, + 0x60A0,0x60A1,0x60A2,0x60A3,0x60A4,0x60A5,0x60A6,0x60A7,0x60A8,0x60A9,0x60AA,0x60AB,0x60AC,0x60AD,0x60AE,0x60AF, + 0x60B0,0x60B1,0x60B2,0x60B3,0x60B4,0x60B5,0x60B6,0x60B7,0x60B8,0x60B9,0x60BA,0x60BB,0x60BC,0x60BD,0x60BE,0x60BF, + 0x60C0,0x60C1,0x60C2,0x60C3,0x60C4,0x60C5,0x60C6,0x60C7,0x60C8,0x60C9,0x60CA,0x60CB,0x60CC,0x60CD,0x60CE,0x60CF, + 0x60D0,0x60D1,0x60D2,0x60D3,0x60D4,0x60D5,0x60D6,0x60D7,0x60D8,0x60D9,0x60DA,0x60DB,0x60DC,0x60DD,0x60DE,0x60DF, + 0x60E0,0x60E1,0x60E2,0x60E3,0x60E4,0x60E5,0x60E6,0x60E7,0x60E8,0x60E9,0x60EA,0x60EB,0x60EC,0x60ED,0x60EE,0x60EF, + 0x60F0,0x60F1,0x60F2,0x60F3,0x60F4,0x60F5,0x60F6,0x60F7,0x60F8,0x60F9,0x60FA,0x60FB,0x60FC,0x60FD,0x60FE,0x60FF, + 0x6100,0x6101,0x6102,0x6103,0x6104,0x6105,0x6106,0x6107,0x6108,0x6109,0x610A,0x610B,0x610C,0x610D,0x610E,0x610F, + 0x6110,0x6111,0x6112,0x6113,0x6114,0x6115,0x6116,0x6117,0x6118,0x6119,0x611A,0x611B,0x611C,0x611D,0x611E,0x611F, + 0x6120,0x6121,0x6122,0x6123,0x6124,0x6125,0x6126,0x6127,0x6128,0x6129,0x612A,0x612B,0x612C,0x612D,0x612E,0x612F, + 0x6130,0x6131,0x6132,0x6133,0x6134,0x6135,0x6136,0x6137,0x6138,0x6139,0x613A,0x613B,0x613C,0x613D,0x613E,0x613F, + 0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146,0x6147,0x6148,0x6149,0x614A,0x614B,0x614C,0x614D,0x614E,0x614F, + 0x6150,0x6151,0x6152,0x6153,0x6154,0x6155,0x6156,0x6157,0x6158,0x6159,0x615A,0x615B,0x615C,0x615D,0x615E,0x615F, + 0x6160,0x6161,0x6162,0x6163,0x6164,0x6165,0x6166,0x6167,0x6168,0x6169,0x616A,0x616B,0x616C,0x616D,0x616E,0x616F, + 0x6170,0x6171,0x6172,0x6173,0x6174,0x6175,0x6176,0x6177,0x6178,0x6179,0x617A,0x617B,0x617C,0x617D,0x617E,0x617F, + 0x6180,0x6181,0x6182,0x6183,0x6184,0x6185,0x6186,0x6187,0x6188,0x6189,0x618A,0x618B,0x618C,0x618D,0x618E,0x618F, + 0x6190,0x6191,0x6192,0x6193,0x6194,0x6195,0x6196,0x6197,0x6198,0x6199,0x619A,0x619B,0x619C,0x619D,0x619E,0x619F, + 0x61A0,0x61A1,0x61A2,0x61A3,0x61A4,0x61A5,0x61A6,0x61A7,0x61A8,0x61A9,0x61AA,0x61AB,0x61AC,0x61AD,0x61AE,0x61AF, + 0x61B0,0x61B1,0x61B2,0x61B3,0x61B4,0x61B5,0x61B6,0x61B7,0x61B8,0x61B9,0x61BA,0x61BB,0x61BC,0x61BD,0x61BE,0x61BF, + 0x61C0,0x61C1,0x61C2,0x61C3,0x61C4,0x61C5,0x61C6,0x61C7,0x61C8,0x61C9,0x61CA,0x61CB,0x61CC,0x61CD,0x61CE,0x61CF, + 0x61D0,0x61D1,0x61D2,0x61D3,0x61D4,0x61D5,0x61D6,0x61D7,0x61D8,0x61D9,0x61DA,0x61DB,0x61DC,0x61DD,0x61DE,0x61DF, + 0x61E0,0x61E1,0x61E2,0x61E3,0x61E4,0x61E5,0x61E6,0x61E7,0x61E8,0x61E9,0x61EA,0x61EB,0x61EC,0x61ED,0x61EE,0x61EF, + 0x61F0,0x61F1,0x61F2,0x61F3,0x61F4,0x61F5,0x61F6,0x61F7,0x61F8,0x61F9,0x61FA,0x61FB,0x61FC,0x61FD,0x61FE,0x61FF, + 0x6200,0x6201,0x6202,0x6203,0x6204,0x6205,0x6206,0x6207,0x6208,0x6209,0x620A,0x620B,0x620C,0x620D,0x620E,0x620F, + 0x6210,0x6211,0x6212,0x6213,0x6214,0x6215,0x6216,0x6217,0x6218,0x6219,0x621A,0x621B,0x621C,0x621D,0x621E,0x621F, + 0x6220,0x6221,0x6222,0x6223,0x6224,0x6225,0x6226,0x6227,0x6228,0x6229,0x622A,0x622B,0x622C,0x622D,0x622E,0x622F, + 0x6230,0x6231,0x6232,0x6233,0x6234,0x6235,0x6236,0x6237,0x6238,0x6239,0x623A,0x623B,0x623C,0x623D,0x623E,0x623F, + 0x6240,0x6241,0x6242,0x6243,0x6244,0x6245,0x6246,0x6247,0x6248,0x6249,0x624A,0x624B,0x624C,0x624D,0x624E,0x624F, + 0x6250,0x6251,0x6252,0x6253,0x6254,0x6255,0x6256,0x6257,0x6258,0x6259,0x625A,0x625B,0x625C,0x625D,0x625E,0x625F, + 0x6260,0x6261,0x6262,0x6263,0x6264,0x6265,0x6266,0x6267,0x6268,0x6269,0x626A,0x626B,0x626C,0x626D,0x626E,0x626F, + 0x6270,0x6271,0x6272,0x6273,0x6274,0x6275,0x6276,0x6277,0x6278,0x6279,0x627A,0x627B,0x627C,0x627D,0x627E,0x627F, + 0x6280,0x6281,0x6282,0x6283,0x6284,0x6285,0x6286,0x6287,0x6288,0x6289,0x628A,0x628B,0x628C,0x628D,0x628E,0x628F, + 0x6290,0x6291,0x6292,0x6293,0x6294,0x6295,0x6296,0x6297,0x6298,0x6299,0x629A,0x629B,0x629C,0x629D,0x629E,0x629F, + 0x62A0,0x62A1,0x62A2,0x62A3,0x62A4,0x62A5,0x62A6,0x62A7,0x62A8,0x62A9,0x62AA,0x62AB,0x62AC,0x62AD,0x62AE,0x62AF, + 0x62B0,0x62B1,0x62B2,0x62B3,0x62B4,0x62B5,0x62B6,0x62B7,0x62B8,0x62B9,0x62BA,0x62BB,0x62BC,0x62BD,0x62BE,0x62BF, + 0x62C0,0x62C1,0x62C2,0x62C3,0x62C4,0x62C5,0x62C6,0x62C7,0x62C8,0x62C9,0x62CA,0x62CB,0x62CC,0x62CD,0x62CE,0x62CF, + 0x62D0,0x62D1,0x62D2,0x62D3,0x62D4,0x62D5,0x62D6,0x62D7,0x62D8,0x62D9,0x62DA,0x62DB,0x62DC,0x62DD,0x62DE,0x62DF, + 0x62E0,0x62E1,0x62E2,0x62E3,0x62E4,0x62E5,0x62E6,0x62E7,0x62E8,0x62E9,0x62EA,0x62EB,0x62EC,0x62ED,0x62EE,0x62EF, + 0x62F0,0x62F1,0x62F2,0x62F3,0x62F4,0x62F5,0x62F6,0x62F7,0x62F8,0x62F9,0x62FA,0x62FB,0x62FC,0x62FD,0x62FE,0x62FF, + 0x6300,0x6301,0x6302,0x6303,0x6304,0x6305,0x6306,0x6307,0x6308,0x6309,0x630A,0x630B,0x630C,0x630D,0x630E,0x630F, + 0x6310,0x6311,0x6312,0x6313,0x6314,0x6315,0x6316,0x6317,0x6318,0x6319,0x631A,0x631B,0x631C,0x631D,0x631E,0x631F, + 0x6320,0x6321,0x6322,0x6323,0x6324,0x6325,0x6326,0x6327,0x6328,0x6329,0x632A,0x632B,0x632C,0x632D,0x632E,0x632F, + 0x6330,0x6331,0x6332,0x6333,0x6334,0x6335,0x6336,0x6337,0x6338,0x6339,0x633A,0x633B,0x633C,0x633D,0x633E,0x633F, + 0x6340,0x6341,0x6342,0x6343,0x6344,0x6345,0x6346,0x6347,0x6348,0x6349,0x634A,0x634B,0x634C,0x634D,0x634E,0x634F, + 0x6350,0x6351,0x6352,0x6353,0x6354,0x6355,0x6356,0x6357,0x6358,0x6359,0x635A,0x635B,0x635C,0x635D,0x635E,0x635F, + 0x6360,0x6361,0x6362,0x6363,0x6364,0x6365,0x6366,0x6367,0x6368,0x6369,0x636A,0x636B,0x636C,0x636D,0x636E,0x636F, + 0x6370,0x6371,0x6372,0x6373,0x6374,0x6375,0x6376,0x6377,0x6378,0x6379,0x637A,0x637B,0x637C,0x637D,0x637E,0x637F, + 0x6380,0x6381,0x6382,0x6383,0x6384,0x6385,0x6386,0x6387,0x6388,0x6389,0x638A,0x638B,0x638C,0x638D,0x638E,0x638F, + 0x6390,0x6391,0x6392,0x6393,0x6394,0x6395,0x6396,0x6397,0x6398,0x6399,0x639A,0x639B,0x639C,0x639D,0x639E,0x639F, + 0x63A0,0x63A1,0x63A2,0x63A3,0x63A4,0x63A5,0x63A6,0x63A7,0x63A8,0x63A9,0x63AA,0x63AB,0x63AC,0x63AD,0x63AE,0x63AF, + 0x63B0,0x63B1,0x63B2,0x63B3,0x63B4,0x63B5,0x63B6,0x63B7,0x63B8,0x63B9,0x63BA,0x63BB,0x63BC,0x63BD,0x63BE,0x63BF, + 0x63C0,0x63C1,0x63C2,0x63C3,0x63C4,0x63C5,0x63C6,0x63C7,0x63C8,0x63C9,0x63CA,0x63CB,0x63CC,0x63CD,0x63CE,0x63CF, + 0x63D0,0x63D1,0x63D2,0x63D3,0x63D4,0x63D5,0x63D6,0x63D7,0x63D8,0x63D9,0x63DA,0x63DB,0x63DC,0x63DD,0x63DE,0x63DF, + 0x63E0,0x63E1,0x63E2,0x63E3,0x63E4,0x63E5,0x63E6,0x63E7,0x63E8,0x63E9,0x63EA,0x63EB,0x63EC,0x63ED,0x63EE,0x63EF, + 0x63F0,0x63F1,0x63F2,0x63F3,0x63F4,0x63F5,0x63F6,0x63F7,0x63F8,0x63F9,0x63FA,0x63FB,0x63FC,0x63FD,0x63FE,0x63FF, + 0x6400,0x6401,0x6402,0x6403,0x6404,0x6405,0x6406,0x6407,0x6408,0x6409,0x640A,0x640B,0x640C,0x640D,0x640E,0x640F, + 0x6410,0x6411,0x6412,0x6413,0x6414,0x6415,0x6416,0x6417,0x6418,0x6419,0x641A,0x641B,0x641C,0x641D,0x641E,0x641F, + 0x6420,0x6421,0x6422,0x6423,0x6424,0x6425,0x6426,0x6427,0x6428,0x6429,0x642A,0x642B,0x642C,0x642D,0x642E,0x642F, + 0x6430,0x6431,0x6432,0x6433,0x6434,0x6435,0x6436,0x6437,0x6438,0x6439,0x643A,0x643B,0x643C,0x643D,0x643E,0x643F, + 0x6440,0x6441,0x6442,0x6443,0x6444,0x6445,0x6446,0x6447,0x6448,0x6449,0x644A,0x644B,0x644C,0x644D,0x644E,0x644F, + 0x6450,0x6451,0x6452,0x6453,0x6454,0x6455,0x6456,0x6457,0x6458,0x6459,0x645A,0x645B,0x645C,0x645D,0x645E,0x645F, + 0x6460,0x6461,0x6462,0x6463,0x6464,0x6465,0x6466,0x6467,0x6468,0x6469,0x646A,0x646B,0x646C,0x646D,0x646E,0x646F, + 0x6470,0x6471,0x6472,0x6473,0x6474,0x6475,0x6476,0x6477,0x6478,0x6479,0x647A,0x647B,0x647C,0x647D,0x647E,0x647F, + 0x6480,0x6481,0x6482,0x6483,0x6484,0x6485,0x6486,0x6487,0x6488,0x6489,0x648A,0x648B,0x648C,0x648D,0x648E,0x648F, + 0x6490,0x6491,0x6492,0x6493,0x6494,0x6495,0x6496,0x6497,0x6498,0x6499,0x649A,0x649B,0x649C,0x649D,0x649E,0x649F, + 0x64A0,0x64A1,0x64A2,0x64A3,0x64A4,0x64A5,0x64A6,0x64A7,0x64A8,0x64A9,0x64AA,0x64AB,0x64AC,0x64AD,0x64AE,0x64AF, + 0x64B0,0x64B1,0x64B2,0x64B3,0x64B4,0x64B5,0x64B6,0x64B7,0x64B8,0x64B9,0x64BA,0x64BB,0x64BC,0x64BD,0x64BE,0x64BF, + 0x64C0,0x64C1,0x64C2,0x64C3,0x64C4,0x64C5,0x64C6,0x64C7,0x64C8,0x64C9,0x64CA,0x64CB,0x64CC,0x64CD,0x64CE,0x64CF, + 0x64D0,0x64D1,0x64D2,0x64D3,0x64D4,0x64D5,0x64D6,0x64D7,0x64D8,0x64D9,0x64DA,0x64DB,0x64DC,0x64DD,0x64DE,0x64DF, + 0x64E0,0x64E1,0x64E2,0x64E3,0x64E4,0x64E5,0x64E6,0x64E7,0x64E8,0x64E9,0x64EA,0x64EB,0x64EC,0x64ED,0x64EE,0x64EF, + 0x64F0,0x64F1,0x64F2,0x64F3,0x64F4,0x64F5,0x64F6,0x64F7,0x64F8,0x64F9,0x64FA,0x64FB,0x64FC,0x64FD,0x64FE,0x64FF, + 0x6500,0x6501,0x6502,0x6503,0x6504,0x6505,0x6506,0x6507,0x6508,0x6509,0x650A,0x650B,0x650C,0x650D,0x650E,0x650F, + 0x6510,0x6511,0x6512,0x6513,0x6514,0x6515,0x6516,0x6517,0x6518,0x6519,0x651A,0x651B,0x651C,0x651D,0x651E,0x651F, + 0x6520,0x6521,0x6522,0x6523,0x6524,0x6525,0x6526,0x6527,0x6528,0x6529,0x652A,0x652B,0x652C,0x652D,0x652E,0x652F, + 0x6530,0x6531,0x6532,0x6533,0x6534,0x6535,0x6536,0x6537,0x6538,0x6539,0x653A,0x653B,0x653C,0x653D,0x653E,0x653F, + 0x6540,0x6541,0x6542,0x6543,0x6544,0x6545,0x6546,0x6547,0x6548,0x6549,0x654A,0x654B,0x654C,0x654D,0x654E,0x654F, + 0x6550,0x6551,0x6552,0x6553,0x6554,0x6555,0x6556,0x6557,0x6558,0x6559,0x655A,0x655B,0x655C,0x655D,0x655E,0x655F, + 0x6560,0x6561,0x6562,0x6563,0x6564,0x6565,0x6566,0x6567,0x6568,0x6569,0x656A,0x656B,0x656C,0x656D,0x656E,0x656F, + 0x6570,0x6571,0x6572,0x6573,0x6574,0x6575,0x6576,0x6577,0x6578,0x6579,0x657A,0x657B,0x657C,0x657D,0x657E,0x657F, + 0x6580,0x6581,0x6582,0x6583,0x6584,0x6585,0x6586,0x6587,0x6588,0x6589,0x658A,0x658B,0x658C,0x658D,0x658E,0x658F, + 0x6590,0x6591,0x6592,0x6593,0x6594,0x6595,0x6596,0x6597,0x6598,0x6599,0x659A,0x659B,0x659C,0x659D,0x659E,0x659F, + 0x65A0,0x65A1,0x65A2,0x65A3,0x65A4,0x65A5,0x65A6,0x65A7,0x65A8,0x65A9,0x65AA,0x65AB,0x65AC,0x65AD,0x65AE,0x65AF, + 0x65B0,0x65B1,0x65B2,0x65B3,0x65B4,0x65B5,0x65B6,0x65B7,0x65B8,0x65B9,0x65BA,0x65BB,0x65BC,0x65BD,0x65BE,0x65BF, + 0x65C0,0x65C1,0x65C2,0x65C3,0x65C4,0x65C5,0x65C6,0x65C7,0x65C8,0x65C9,0x65CA,0x65CB,0x65CC,0x65CD,0x65CE,0x65CF, + 0x65D0,0x65D1,0x65D2,0x65D3,0x65D4,0x65D5,0x65D6,0x65D7,0x65D8,0x65D9,0x65DA,0x65DB,0x65DC,0x65DD,0x65DE,0x65DF, + 0x65E0,0x65E1,0x65E2,0x65E3,0x65E4,0x65E5,0x65E6,0x65E7,0x65E8,0x65E9,0x65EA,0x65EB,0x65EC,0x65ED,0x65EE,0x65EF, + 0x65F0,0x65F1,0x65F2,0x65F3,0x65F4,0x65F5,0x65F6,0x65F7,0x65F8,0x65F9,0x65FA,0x65FB,0x65FC,0x65FD,0x65FE,0x65FF, + 0x6600,0x6601,0x6602,0x6603,0x6604,0x6605,0x6606,0x6607,0x6608,0x6609,0x660A,0x660B,0x660C,0x660D,0x660E,0x660F, + 0x6610,0x6611,0x6612,0x6613,0x6614,0x6615,0x6616,0x6617,0x6618,0x6619,0x661A,0x661B,0x661C,0x661D,0x661E,0x661F, + 0x6620,0x6621,0x6622,0x6623,0x6624,0x6625,0x6626,0x6627,0x6628,0x6629,0x662A,0x662B,0x662C,0x662D,0x662E,0x662F, + 0x6630,0x6631,0x6632,0x6633,0x6634,0x6635,0x6636,0x6637,0x6638,0x6639,0x663A,0x663B,0x663C,0x663D,0x663E,0x663F, + 0x6640,0x6641,0x6642,0x6643,0x6644,0x6645,0x6646,0x6647,0x6648,0x6649,0x664A,0x664B,0x664C,0x664D,0x664E,0x664F, + 0x6650,0x6651,0x6652,0x6653,0x6654,0x6655,0x6656,0x6657,0x6658,0x6659,0x665A,0x665B,0x665C,0x665D,0x665E,0x665F, + 0x6660,0x6661,0x6662,0x6663,0x6664,0x6665,0x6666,0x6667,0x6668,0x6669,0x666A,0x666B,0x666C,0x666D,0x666E,0x666F, + 0x6670,0x6671,0x6672,0x6673,0x6674,0x6675,0x6676,0x6677,0x6678,0x6679,0x667A,0x667B,0x667C,0x667D,0x667E,0x667F, + 0x6680,0x6681,0x6682,0x6683,0x6684,0x6685,0x6686,0x6687,0x6688,0x6689,0x668A,0x668B,0x668C,0x668D,0x668E,0x668F, + 0x6690,0x6691,0x6692,0x6693,0x6694,0x6695,0x6696,0x6697,0x6698,0x6699,0x669A,0x669B,0x669C,0x669D,0x669E,0x669F, + 0x66A0,0x66A1,0x66A2,0x66A3,0x66A4,0x66A5,0x66A6,0x66A7,0x66A8,0x66A9,0x66AA,0x66AB,0x66AC,0x66AD,0x66AE,0x66AF, + 0x66B0,0x66B1,0x66B2,0x66B3,0x66B4,0x66B5,0x66B6,0x66B7,0x66B8,0x66B9,0x66BA,0x66BB,0x66BC,0x66BD,0x66BE,0x66BF, + 0x66C0,0x66C1,0x66C2,0x66C3,0x66C4,0x66C5,0x66C6,0x66C7,0x66C8,0x66C9,0x66CA,0x66CB,0x66CC,0x66CD,0x66CE,0x66CF, + 0x66D0,0x66D1,0x66D2,0x66D3,0x66D4,0x66D5,0x66D6,0x66D7,0x66D8,0x66D9,0x66DA,0x66DB,0x66DC,0x66DD,0x66DE,0x66DF, + 0x66E0,0x66E1,0x66E2,0x66E3,0x66E4,0x66E5,0x66E6,0x66E7,0x66E8,0x66E9,0x66EA,0x66EB,0x66EC,0x66ED,0x66EE,0x66EF, + 0x66F0,0x66F1,0x66F2,0x66F3,0x66F4,0x66F5,0x66F6,0x66F7,0x66F8,0x66F9,0x66FA,0x66FB,0x66FC,0x66FD,0x66FE,0x66FF, + 0x6700,0x6701,0x6702,0x6703,0x6704,0x6705,0x6706,0x6707,0x6708,0x6709,0x670A,0x670B,0x670C,0x670D,0x670E,0x670F, + 0x6710,0x6711,0x6712,0x6713,0x6714,0x6715,0x6716,0x6717,0x6718,0x6719,0x671A,0x671B,0x671C,0x671D,0x671E,0x671F, + 0x6720,0x6721,0x6722,0x6723,0x6724,0x6725,0x6726,0x6727,0x6728,0x6729,0x672A,0x672B,0x672C,0x672D,0x672E,0x672F, + 0x6730,0x6731,0x6732,0x6733,0x6734,0x6735,0x6736,0x6737,0x6738,0x6739,0x673A,0x673B,0x673C,0x673D,0x673E,0x673F, + 0x6740,0x6741,0x6742,0x6743,0x6744,0x6745,0x6746,0x6747,0x6748,0x6749,0x674A,0x674B,0x674C,0x674D,0x674E,0x674F, + 0x6750,0x6751,0x6752,0x6753,0x6754,0x6755,0x6756,0x6757,0x6758,0x6759,0x675A,0x675B,0x675C,0x675D,0x675E,0x675F, + 0x6760,0x6761,0x6762,0x6763,0x6764,0x6765,0x6766,0x6767,0x6768,0x6769,0x676A,0x676B,0x676C,0x676D,0x676E,0x676F, + 0x6770,0x6771,0x6772,0x6773,0x6774,0x6775,0x6776,0x6777,0x6778,0x6779,0x677A,0x677B,0x677C,0x677D,0x677E,0x677F, + 0x6780,0x6781,0x6782,0x6783,0x6784,0x6785,0x6786,0x6787,0x6788,0x6789,0x678A,0x678B,0x678C,0x678D,0x678E,0x678F, + 0x6790,0x6791,0x6792,0x6793,0x6794,0x6795,0x6796,0x6797,0x6798,0x6799,0x679A,0x679B,0x679C,0x679D,0x679E,0x679F, + 0x67A0,0x67A1,0x67A2,0x67A3,0x67A4,0x67A5,0x67A6,0x67A7,0x67A8,0x67A9,0x67AA,0x67AB,0x67AC,0x67AD,0x67AE,0x67AF, + 0x67B0,0x67B1,0x67B2,0x67B3,0x67B4,0x67B5,0x67B6,0x67B7,0x67B8,0x67B9,0x67BA,0x67BB,0x67BC,0x67BD,0x67BE,0x67BF, + 0x67C0,0x67C1,0x67C2,0x67C3,0x67C4,0x67C5,0x67C6,0x67C7,0x67C8,0x67C9,0x67CA,0x67CB,0x67CC,0x67CD,0x67CE,0x67CF, + 0x67D0,0x67D1,0x67D2,0x67D3,0x67D4,0x67D5,0x67D6,0x67D7,0x67D8,0x67D9,0x67DA,0x67DB,0x67DC,0x67DD,0x67DE,0x67DF, + 0x67E0,0x67E1,0x67E2,0x67E3,0x67E4,0x67E5,0x67E6,0x67E7,0x67E8,0x67E9,0x67EA,0x67EB,0x67EC,0x67ED,0x67EE,0x67EF, + 0x67F0,0x67F1,0x67F2,0x67F3,0x67F4,0x67F5,0x67F6,0x67F7,0x67F8,0x67F9,0x67FA,0x67FB,0x67FC,0x67FD,0x67FE,0x67FF, + 0x6800,0x6801,0x6802,0x6803,0x6804,0x6805,0x6806,0x6807,0x6808,0x6809,0x680A,0x680B,0x680C,0x680D,0x680E,0x680F, + 0x6810,0x6811,0x6812,0x6813,0x6814,0x6815,0x6816,0x6817,0x6818,0x6819,0x681A,0x681B,0x681C,0x681D,0x681E,0x681F, + 0x6820,0x6821,0x6822,0x6823,0x6824,0x6825,0x6826,0x6827,0x6828,0x6829,0x682A,0x682B,0x682C,0x682D,0x682E,0x682F, + 0x6830,0x6831,0x6832,0x6833,0x6834,0x6835,0x6836,0x6837,0x6838,0x6839,0x683A,0x683B,0x683C,0x683D,0x683E,0x683F, + 0x6840,0x6841,0x6842,0x6843,0x6844,0x6845,0x6846,0x6847,0x6848,0x6849,0x684A,0x684B,0x684C,0x684D,0x684E,0x684F, + 0x6850,0x6851,0x6852,0x6853,0x6854,0x6855,0x6856,0x6857,0x6858,0x6859,0x685A,0x685B,0x685C,0x685D,0x685E,0x685F, + 0x6860,0x6861,0x6862,0x6863,0x6864,0x6865,0x6866,0x6867,0x6868,0x6869,0x686A,0x686B,0x686C,0x686D,0x686E,0x686F, + 0x6870,0x6871,0x6872,0x6873,0x6874,0x6875,0x6876,0x6877,0x6878,0x6879,0x687A,0x687B,0x687C,0x687D,0x687E,0x687F, + 0x6880,0x6881,0x6882,0x6883,0x6884,0x6885,0x6886,0x6887,0x6888,0x6889,0x688A,0x688B,0x688C,0x688D,0x688E,0x688F, + 0x6890,0x6891,0x6892,0x6893,0x6894,0x6895,0x6896,0x6897,0x6898,0x6899,0x689A,0x689B,0x689C,0x689D,0x689E,0x689F, + 0x68A0,0x68A1,0x68A2,0x68A3,0x68A4,0x68A5,0x68A6,0x68A7,0x68A8,0x68A9,0x68AA,0x68AB,0x68AC,0x68AD,0x68AE,0x68AF, + 0x68B0,0x68B1,0x68B2,0x68B3,0x68B4,0x68B5,0x68B6,0x68B7,0x68B8,0x68B9,0x68BA,0x68BB,0x68BC,0x68BD,0x68BE,0x68BF, + 0x68C0,0x68C1,0x68C2,0x68C3,0x68C4,0x68C5,0x68C6,0x68C7,0x68C8,0x68C9,0x68CA,0x68CB,0x68CC,0x68CD,0x68CE,0x68CF, + 0x68D0,0x68D1,0x68D2,0x68D3,0x68D4,0x68D5,0x68D6,0x68D7,0x68D8,0x68D9,0x68DA,0x68DB,0x68DC,0x68DD,0x68DE,0x68DF, + 0x68E0,0x68E1,0x68E2,0x68E3,0x68E4,0x68E5,0x68E6,0x68E7,0x68E8,0x68E9,0x68EA,0x68EB,0x68EC,0x68ED,0x68EE,0x68EF, + 0x68F0,0x68F1,0x68F2,0x68F3,0x68F4,0x68F5,0x68F6,0x68F7,0x68F8,0x68F9,0x68FA,0x68FB,0x68FC,0x68FD,0x68FE,0x68FF, + 0x6900,0x6901,0x6902,0x6903,0x6904,0x6905,0x6906,0x6907,0x6908,0x6909,0x690A,0x690B,0x690C,0x690D,0x690E,0x690F, + 0x6910,0x6911,0x6912,0x6913,0x6914,0x6915,0x6916,0x6917,0x6918,0x6919,0x691A,0x691B,0x691C,0x691D,0x691E,0x691F, + 0x6920,0x6921,0x6922,0x6923,0x6924,0x6925,0x6926,0x6927,0x6928,0x6929,0x692A,0x692B,0x692C,0x692D,0x692E,0x692F, + 0x6930,0x6931,0x6932,0x6933,0x6934,0x6935,0x6936,0x6937,0x6938,0x6939,0x693A,0x693B,0x693C,0x693D,0x693E,0x693F, + 0x6940,0x6941,0x6942,0x6943,0x6944,0x6945,0x6946,0x6947,0x6948,0x6949,0x694A,0x694B,0x694C,0x694D,0x694E,0x694F, + 0x6950,0x6951,0x6952,0x6953,0x6954,0x6955,0x6956,0x6957,0x6958,0x6959,0x695A,0x695B,0x695C,0x695D,0x695E,0x695F, + 0x6960,0x6961,0x6962,0x6963,0x6964,0x6965,0x6966,0x6967,0x6968,0x6969,0x696A,0x696B,0x696C,0x696D,0x696E,0x696F, + 0x6970,0x6971,0x6972,0x6973,0x6974,0x6975,0x6976,0x6977,0x6978,0x6979,0x697A,0x697B,0x697C,0x697D,0x697E,0x697F, + 0x6980,0x6981,0x6982,0x6983,0x6984,0x6985,0x6986,0x6987,0x6988,0x6989,0x698A,0x698B,0x698C,0x698D,0x698E,0x698F, + 0x6990,0x6991,0x6992,0x6993,0x6994,0x6995,0x6996,0x6997,0x6998,0x6999,0x699A,0x699B,0x699C,0x699D,0x699E,0x699F, + 0x69A0,0x69A1,0x69A2,0x69A3,0x69A4,0x69A5,0x69A6,0x69A7,0x69A8,0x69A9,0x69AA,0x69AB,0x69AC,0x69AD,0x69AE,0x69AF, + 0x69B0,0x69B1,0x69B2,0x69B3,0x69B4,0x69B5,0x69B6,0x69B7,0x69B8,0x69B9,0x69BA,0x69BB,0x69BC,0x69BD,0x69BE,0x69BF, + 0x69C0,0x69C1,0x69C2,0x69C3,0x69C4,0x69C5,0x69C6,0x69C7,0x69C8,0x69C9,0x69CA,0x69CB,0x69CC,0x69CD,0x69CE,0x69CF, + 0x69D0,0x69D1,0x69D2,0x69D3,0x69D4,0x69D5,0x69D6,0x69D7,0x69D8,0x69D9,0x69DA,0x69DB,0x69DC,0x69DD,0x69DE,0x69DF, + 0x69E0,0x69E1,0x69E2,0x69E3,0x69E4,0x69E5,0x69E6,0x69E7,0x69E8,0x69E9,0x69EA,0x69EB,0x69EC,0x69ED,0x69EE,0x69EF, + 0x69F0,0x69F1,0x69F2,0x69F3,0x69F4,0x69F5,0x69F6,0x69F7,0x69F8,0x69F9,0x69FA,0x69FB,0x69FC,0x69FD,0x69FE,0x69FF, + 0x6A00,0x6A01,0x6A02,0x6A03,0x6A04,0x6A05,0x6A06,0x6A07,0x6A08,0x6A09,0x6A0A,0x6A0B,0x6A0C,0x6A0D,0x6A0E,0x6A0F, + 0x6A10,0x6A11,0x6A12,0x6A13,0x6A14,0x6A15,0x6A16,0x6A17,0x6A18,0x6A19,0x6A1A,0x6A1B,0x6A1C,0x6A1D,0x6A1E,0x6A1F, + 0x6A20,0x6A21,0x6A22,0x6A23,0x6A24,0x6A25,0x6A26,0x6A27,0x6A28,0x6A29,0x6A2A,0x6A2B,0x6A2C,0x6A2D,0x6A2E,0x6A2F, + 0x6A30,0x6A31,0x6A32,0x6A33,0x6A34,0x6A35,0x6A36,0x6A37,0x6A38,0x6A39,0x6A3A,0x6A3B,0x6A3C,0x6A3D,0x6A3E,0x6A3F, + 0x6A40,0x6A41,0x6A42,0x6A43,0x6A44,0x6A45,0x6A46,0x6A47,0x6A48,0x6A49,0x6A4A,0x6A4B,0x6A4C,0x6A4D,0x6A4E,0x6A4F, + 0x6A50,0x6A51,0x6A52,0x6A53,0x6A54,0x6A55,0x6A56,0x6A57,0x6A58,0x6A59,0x6A5A,0x6A5B,0x6A5C,0x6A5D,0x6A5E,0x6A5F, + 0x6A60,0x6A61,0x6A62,0x6A63,0x6A64,0x6A65,0x6A66,0x6A67,0x6A68,0x6A69,0x6A6A,0x6A6B,0x6A6C,0x6A6D,0x6A6E,0x6A6F, + 0x6A70,0x6A71,0x6A72,0x6A73,0x6A74,0x6A75,0x6A76,0x6A77,0x6A78,0x6A79,0x6A7A,0x6A7B,0x6A7C,0x6A7D,0x6A7E,0x6A7F, + 0x6A80,0x6A81,0x6A82,0x6A83,0x6A84,0x6A85,0x6A86,0x6A87,0x6A88,0x6A89,0x6A8A,0x6A8B,0x6A8C,0x6A8D,0x6A8E,0x6A8F, + 0x6A90,0x6A91,0x6A92,0x6A93,0x6A94,0x6A95,0x6A96,0x6A97,0x6A98,0x6A99,0x6A9A,0x6A9B,0x6A9C,0x6A9D,0x6A9E,0x6A9F, + 0x6AA0,0x6AA1,0x6AA2,0x6AA3,0x6AA4,0x6AA5,0x6AA6,0x6AA7,0x6AA8,0x6AA9,0x6AAA,0x6AAB,0x6AAC,0x6AAD,0x6AAE,0x6AAF, + 0x6AB0,0x6AB1,0x6AB2,0x6AB3,0x6AB4,0x6AB5,0x6AB6,0x6AB7,0x6AB8,0x6AB9,0x6ABA,0x6ABB,0x6ABC,0x6ABD,0x6ABE,0x6ABF, + 0x6AC0,0x6AC1,0x6AC2,0x6AC3,0x6AC4,0x6AC5,0x6AC6,0x6AC7,0x6AC8,0x6AC9,0x6ACA,0x6ACB,0x6ACC,0x6ACD,0x6ACE,0x6ACF, + 0x6AD0,0x6AD1,0x6AD2,0x6AD3,0x6AD4,0x6AD5,0x6AD6,0x6AD7,0x6AD8,0x6AD9,0x6ADA,0x6ADB,0x6ADC,0x6ADD,0x6ADE,0x6ADF, + 0x6AE0,0x6AE1,0x6AE2,0x6AE3,0x6AE4,0x6AE5,0x6AE6,0x6AE7,0x6AE8,0x6AE9,0x6AEA,0x6AEB,0x6AEC,0x6AED,0x6AEE,0x6AEF, + 0x6AF0,0x6AF1,0x6AF2,0x6AF3,0x6AF4,0x6AF5,0x6AF6,0x6AF7,0x6AF8,0x6AF9,0x6AFA,0x6AFB,0x6AFC,0x6AFD,0x6AFE,0x6AFF, + 0x6B00,0x6B01,0x6B02,0x6B03,0x6B04,0x6B05,0x6B06,0x6B07,0x6B08,0x6B09,0x6B0A,0x6B0B,0x6B0C,0x6B0D,0x6B0E,0x6B0F, + 0x6B10,0x6B11,0x6B12,0x6B13,0x6B14,0x6B15,0x6B16,0x6B17,0x6B18,0x6B19,0x6B1A,0x6B1B,0x6B1C,0x6B1D,0x6B1E,0x6B1F, + 0x6B20,0x6B21,0x6B22,0x6B23,0x6B24,0x6B25,0x6B26,0x6B27,0x6B28,0x6B29,0x6B2A,0x6B2B,0x6B2C,0x6B2D,0x6B2E,0x6B2F, + 0x6B30,0x6B31,0x6B32,0x6B33,0x6B34,0x6B35,0x6B36,0x6B37,0x6B38,0x6B39,0x6B3A,0x6B3B,0x6B3C,0x6B3D,0x6B3E,0x6B3F, + 0x6B40,0x6B41,0x6B42,0x6B43,0x6B44,0x6B45,0x6B46,0x6B47,0x6B48,0x6B49,0x6B4A,0x6B4B,0x6B4C,0x6B4D,0x6B4E,0x6B4F, + 0x6B50,0x6B51,0x6B52,0x6B53,0x6B54,0x6B55,0x6B56,0x6B57,0x6B58,0x6B59,0x6B5A,0x6B5B,0x6B5C,0x6B5D,0x6B5E,0x6B5F, + 0x6B60,0x6B61,0x6B62,0x6B63,0x6B64,0x6B65,0x6B66,0x6B67,0x6B68,0x6B69,0x6B6A,0x6B6B,0x6B6C,0x6B6D,0x6B6E,0x6B6F, + 0x6B70,0x6B71,0x6B72,0x6B73,0x6B74,0x6B75,0x6B76,0x6B77,0x6B78,0x6B79,0x6B7A,0x6B7B,0x6B7C,0x6B7D,0x6B7E,0x6B7F, + 0x6B80,0x6B81,0x6B82,0x6B83,0x6B84,0x6B85,0x6B86,0x6B87,0x6B88,0x6B89,0x6B8A,0x6B8B,0x6B8C,0x6B8D,0x6B8E,0x6B8F, + 0x6B90,0x6B91,0x6B92,0x6B93,0x6B94,0x6B95,0x6B96,0x6B97,0x6B98,0x6B99,0x6B9A,0x6B9B,0x6B9C,0x6B9D,0x6B9E,0x6B9F, + 0x6BA0,0x6BA1,0x6BA2,0x6BA3,0x6BA4,0x6BA5,0x6BA6,0x6BA7,0x6BA8,0x6BA9,0x6BAA,0x6BAB,0x6BAC,0x6BAD,0x6BAE,0x6BAF, + 0x6BB0,0x6BB1,0x6BB2,0x6BB3,0x6BB4,0x6BB5,0x6BB6,0x6BB7,0x6BB8,0x6BB9,0x6BBA,0x6BBB,0x6BBC,0x6BBD,0x6BBE,0x6BBF, + 0x6BC0,0x6BC1,0x6BC2,0x6BC3,0x6BC4,0x6BC5,0x6BC6,0x6BC7,0x6BC8,0x6BC9,0x6BCA,0x6BCB,0x6BCC,0x6BCD,0x6BCE,0x6BCF, + 0x6BD0,0x6BD1,0x6BD2,0x6BD3,0x6BD4,0x6BD5,0x6BD6,0x6BD7,0x6BD8,0x6BD9,0x6BDA,0x6BDB,0x6BDC,0x6BDD,0x6BDE,0x6BDF, + 0x6BE0,0x6BE1,0x6BE2,0x6BE3,0x6BE4,0x6BE5,0x6BE6,0x6BE7,0x6BE8,0x6BE9,0x6BEA,0x6BEB,0x6BEC,0x6BED,0x6BEE,0x6BEF, + 0x6BF0,0x6BF1,0x6BF2,0x6BF3,0x6BF4,0x6BF5,0x6BF6,0x6BF7,0x6BF8,0x6BF9,0x6BFA,0x6BFB,0x6BFC,0x6BFD,0x6BFE,0x6BFF, + 0x6C00,0x6C01,0x6C02,0x6C03,0x6C04,0x6C05,0x6C06,0x6C07,0x6C08,0x6C09,0x6C0A,0x6C0B,0x6C0C,0x6C0D,0x6C0E,0x6C0F, + 0x6C10,0x6C11,0x6C12,0x6C13,0x6C14,0x6C15,0x6C16,0x6C17,0x6C18,0x6C19,0x6C1A,0x6C1B,0x6C1C,0x6C1D,0x6C1E,0x6C1F, + 0x6C20,0x6C21,0x6C22,0x6C23,0x6C24,0x6C25,0x6C26,0x6C27,0x6C28,0x6C29,0x6C2A,0x6C2B,0x6C2C,0x6C2D,0x6C2E,0x6C2F, + 0x6C30,0x6C31,0x6C32,0x6C33,0x6C34,0x6C35,0x6C36,0x6C37,0x6C38,0x6C39,0x6C3A,0x6C3B,0x6C3C,0x6C3D,0x6C3E,0x6C3F, + 0x6C40,0x6C41,0x6C42,0x6C43,0x6C44,0x6C45,0x6C46,0x6C47,0x6C48,0x6C49,0x6C4A,0x6C4B,0x6C4C,0x6C4D,0x6C4E,0x6C4F, + 0x6C50,0x6C51,0x6C52,0x6C53,0x6C54,0x6C55,0x6C56,0x6C57,0x6C58,0x6C59,0x6C5A,0x6C5B,0x6C5C,0x6C5D,0x6C5E,0x6C5F, + 0x6C60,0x6C61,0x6C62,0x6C63,0x6C64,0x6C65,0x6C66,0x6C67,0x6C68,0x6C69,0x6C6A,0x6C6B,0x6C6C,0x6C6D,0x6C6E,0x6C6F, + 0x6C70,0x6C71,0x6C72,0x6C73,0x6C74,0x6C75,0x6C76,0x6C77,0x6C78,0x6C79,0x6C7A,0x6C7B,0x6C7C,0x6C7D,0x6C7E,0x6C7F, + 0x6C80,0x6C81,0x6C82,0x6C83,0x6C84,0x6C85,0x6C86,0x6C87,0x6C88,0x6C89,0x6C8A,0x6C8B,0x6C8C,0x6C8D,0x6C8E,0x6C8F, + 0x6C90,0x6C91,0x6C92,0x6C93,0x6C94,0x6C95,0x6C96,0x6C97,0x6C98,0x6C99,0x6C9A,0x6C9B,0x6C9C,0x6C9D,0x6C9E,0x6C9F, + 0x6CA0,0x6CA1,0x6CA2,0x6CA3,0x6CA4,0x6CA5,0x6CA6,0x6CA7,0x6CA8,0x6CA9,0x6CAA,0x6CAB,0x6CAC,0x6CAD,0x6CAE,0x6CAF, + 0x6CB0,0x6CB1,0x6CB2,0x6CB3,0x6CB4,0x6CB5,0x6CB6,0x6CB7,0x6CB8,0x6CB9,0x6CBA,0x6CBB,0x6CBC,0x6CBD,0x6CBE,0x6CBF, + 0x6CC0,0x6CC1,0x6CC2,0x6CC3,0x6CC4,0x6CC5,0x6CC6,0x6CC7,0x6CC8,0x6CC9,0x6CCA,0x6CCB,0x6CCC,0x6CCD,0x6CCE,0x6CCF, + 0x6CD0,0x6CD1,0x6CD2,0x6CD3,0x6CD4,0x6CD5,0x6CD6,0x6CD7,0x6CD8,0x6CD9,0x6CDA,0x6CDB,0x6CDC,0x6CDD,0x6CDE,0x6CDF, + 0x6CE0,0x6CE1,0x6CE2,0x6CE3,0x6CE4,0x6CE5,0x6CE6,0x6CE7,0x6CE8,0x6CE9,0x6CEA,0x6CEB,0x6CEC,0x6CED,0x6CEE,0x6CEF, + 0x6CF0,0x6CF1,0x6CF2,0x6CF3,0x6CF4,0x6CF5,0x6CF6,0x6CF7,0x6CF8,0x6CF9,0x6CFA,0x6CFB,0x6CFC,0x6CFD,0x6CFE,0x6CFF, + 0x6D00,0x6D01,0x6D02,0x6D03,0x6D04,0x6D05,0x6D06,0x6D07,0x6D08,0x6D09,0x6D0A,0x6D0B,0x6D0C,0x6D0D,0x6D0E,0x6D0F, + 0x6D10,0x6D11,0x6D12,0x6D13,0x6D14,0x6D15,0x6D16,0x6D17,0x6D18,0x6D19,0x6D1A,0x6D1B,0x6D1C,0x6D1D,0x6D1E,0x6D1F, + 0x6D20,0x6D21,0x6D22,0x6D23,0x6D24,0x6D25,0x6D26,0x6D27,0x6D28,0x6D29,0x6D2A,0x6D2B,0x6D2C,0x6D2D,0x6D2E,0x6D2F, + 0x6D30,0x6D31,0x6D32,0x6D33,0x6D34,0x6D35,0x6D36,0x6D37,0x6D38,0x6D39,0x6D3A,0x6D3B,0x6D3C,0x6D3D,0x6D3E,0x6D3F, + 0x6D40,0x6D41,0x6D42,0x6D43,0x6D44,0x6D45,0x6D46,0x6D47,0x6D48,0x6D49,0x6D4A,0x6D4B,0x6D4C,0x6D4D,0x6D4E,0x6D4F, + 0x6D50,0x6D51,0x6D52,0x6D53,0x6D54,0x6D55,0x6D56,0x6D57,0x6D58,0x6D59,0x6D5A,0x6D5B,0x6D5C,0x6D5D,0x6D5E,0x6D5F, + 0x6D60,0x6D61,0x6D62,0x6D63,0x6D64,0x6D65,0x6D66,0x6D67,0x6D68,0x6D69,0x6D6A,0x6D6B,0x6D6C,0x6D6D,0x6D6E,0x6D6F, + 0x6D70,0x6D71,0x6D72,0x6D73,0x6D74,0x6D75,0x6D76,0x6D77,0x6D78,0x6D79,0x6D7A,0x6D7B,0x6D7C,0x6D7D,0x6D7E,0x6D7F, + 0x6D80,0x6D81,0x6D82,0x6D83,0x6D84,0x6D85,0x6D86,0x6D87,0x6D88,0x6D89,0x6D8A,0x6D8B,0x6D8C,0x6D8D,0x6D8E,0x6D8F, + 0x6D90,0x6D91,0x6D92,0x6D93,0x6D94,0x6D95,0x6D96,0x6D97,0x6D98,0x6D99,0x6D9A,0x6D9B,0x6D9C,0x6D9D,0x6D9E,0x6D9F, + 0x6DA0,0x6DA1,0x6DA2,0x6DA3,0x6DA4,0x6DA5,0x6DA6,0x6DA7,0x6DA8,0x6DA9,0x6DAA,0x6DAB,0x6DAC,0x6DAD,0x6DAE,0x6DAF, + 0x6DB0,0x6DB1,0x6DB2,0x6DB3,0x6DB4,0x6DB5,0x6DB6,0x6DB7,0x6DB8,0x6DB9,0x6DBA,0x6DBB,0x6DBC,0x6DBD,0x6DBE,0x6DBF, + 0x6DC0,0x6DC1,0x6DC2,0x6DC3,0x6DC4,0x6DC5,0x6DC6,0x6DC7,0x6DC8,0x6DC9,0x6DCA,0x6DCB,0x6DCC,0x6DCD,0x6DCE,0x6DCF, + 0x6DD0,0x6DD1,0x6DD2,0x6DD3,0x6DD4,0x6DD5,0x6DD6,0x6DD7,0x6DD8,0x6DD9,0x6DDA,0x6DDB,0x6DDC,0x6DDD,0x6DDE,0x6DDF, + 0x6DE0,0x6DE1,0x6DE2,0x6DE3,0x6DE4,0x6DE5,0x6DE6,0x6DE7,0x6DE8,0x6DE9,0x6DEA,0x6DEB,0x6DEC,0x6DED,0x6DEE,0x6DEF, + 0x6DF0,0x6DF1,0x6DF2,0x6DF3,0x6DF4,0x6DF5,0x6DF6,0x6DF7,0x6DF8,0x6DF9,0x6DFA,0x6DFB,0x6DFC,0x6DFD,0x6DFE,0x6DFF, + 0x6E00,0x6E01,0x6E02,0x6E03,0x6E04,0x6E05,0x6E06,0x6E07,0x6E08,0x6E09,0x6E0A,0x6E0B,0x6E0C,0x6E0D,0x6E0E,0x6E0F, + 0x6E10,0x6E11,0x6E12,0x6E13,0x6E14,0x6E15,0x6E16,0x6E17,0x6E18,0x6E19,0x6E1A,0x6E1B,0x6E1C,0x6E1D,0x6E1E,0x6E1F, + 0x6E20,0x6E21,0x6E22,0x6E23,0x6E24,0x6E25,0x6E26,0x6E27,0x6E28,0x6E29,0x6E2A,0x6E2B,0x6E2C,0x6E2D,0x6E2E,0x6E2F, + 0x6E30,0x6E31,0x6E32,0x6E33,0x6E34,0x6E35,0x6E36,0x6E37,0x6E38,0x6E39,0x6E3A,0x6E3B,0x6E3C,0x6E3D,0x6E3E,0x6E3F, + 0x6E40,0x6E41,0x6E42,0x6E43,0x6E44,0x6E45,0x6E46,0x6E47,0x6E48,0x6E49,0x6E4A,0x6E4B,0x6E4C,0x6E4D,0x6E4E,0x6E4F, + 0x6E50,0x6E51,0x6E52,0x6E53,0x6E54,0x6E55,0x6E56,0x6E57,0x6E58,0x6E59,0x6E5A,0x6E5B,0x6E5C,0x6E5D,0x6E5E,0x6E5F, + 0x6E60,0x6E61,0x6E62,0x6E63,0x6E64,0x6E65,0x6E66,0x6E67,0x6E68,0x6E69,0x6E6A,0x6E6B,0x6E6C,0x6E6D,0x6E6E,0x6E6F, + 0x6E70,0x6E71,0x6E72,0x6E73,0x6E74,0x6E75,0x6E76,0x6E77,0x6E78,0x6E79,0x6E7A,0x6E7B,0x6E7C,0x6E7D,0x6E7E,0x6E7F, + 0x6E80,0x6E81,0x6E82,0x6E83,0x6E84,0x6E85,0x6E86,0x6E87,0x6E88,0x6E89,0x6E8A,0x6E8B,0x6E8C,0x6E8D,0x6E8E,0x6E8F, + 0x6E90,0x6E91,0x6E92,0x6E93,0x6E94,0x6E95,0x6E96,0x6E97,0x6E98,0x6E99,0x6E9A,0x6E9B,0x6E9C,0x6E9D,0x6E9E,0x6E9F, + 0x6EA0,0x6EA1,0x6EA2,0x6EA3,0x6EA4,0x6EA5,0x6EA6,0x6EA7,0x6EA8,0x6EA9,0x6EAA,0x6EAB,0x6EAC,0x6EAD,0x6EAE,0x6EAF, + 0x6EB0,0x6EB1,0x6EB2,0x6EB3,0x6EB4,0x6EB5,0x6EB6,0x6EB7,0x6EB8,0x6EB9,0x6EBA,0x6EBB,0x6EBC,0x6EBD,0x6EBE,0x6EBF, + 0x6EC0,0x6EC1,0x6EC2,0x6EC3,0x6EC4,0x6EC5,0x6EC6,0x6EC7,0x6EC8,0x6EC9,0x6ECA,0x6ECB,0x6ECC,0x6ECD,0x6ECE,0x6ECF, + 0x6ED0,0x6ED1,0x6ED2,0x6ED3,0x6ED4,0x6ED5,0x6ED6,0x6ED7,0x6ED8,0x6ED9,0x6EDA,0x6EDB,0x6EDC,0x6EDD,0x6EDE,0x6EDF, + 0x6EE0,0x6EE1,0x6EE2,0x6EE3,0x6EE4,0x6EE5,0x6EE6,0x6EE7,0x6EE8,0x6EE9,0x6EEA,0x6EEB,0x6EEC,0x6EED,0x6EEE,0x6EEF, + 0x6EF0,0x6EF1,0x6EF2,0x6EF3,0x6EF4,0x6EF5,0x6EF6,0x6EF7,0x6EF8,0x6EF9,0x6EFA,0x6EFB,0x6EFC,0x6EFD,0x6EFE,0x6EFF, + 0x6F00,0x6F01,0x6F02,0x6F03,0x6F04,0x6F05,0x6F06,0x6F07,0x6F08,0x6F09,0x6F0A,0x6F0B,0x6F0C,0x6F0D,0x6F0E,0x6F0F, + 0x6F10,0x6F11,0x6F12,0x6F13,0x6F14,0x6F15,0x6F16,0x6F17,0x6F18,0x6F19,0x6F1A,0x6F1B,0x6F1C,0x6F1D,0x6F1E,0x6F1F, + 0x6F20,0x6F21,0x6F22,0x6F23,0x6F24,0x6F25,0x6F26,0x6F27,0x6F28,0x6F29,0x6F2A,0x6F2B,0x6F2C,0x6F2D,0x6F2E,0x6F2F, + 0x6F30,0x6F31,0x6F32,0x6F33,0x6F34,0x6F35,0x6F36,0x6F37,0x6F38,0x6F39,0x6F3A,0x6F3B,0x6F3C,0x6F3D,0x6F3E,0x6F3F, + 0x6F40,0x6F41,0x6F42,0x6F43,0x6F44,0x6F45,0x6F46,0x6F47,0x6F48,0x6F49,0x6F4A,0x6F4B,0x6F4C,0x6F4D,0x6F4E,0x6F4F, + 0x6F50,0x6F51,0x6F52,0x6F53,0x6F54,0x6F55,0x6F56,0x6F57,0x6F58,0x6F59,0x6F5A,0x6F5B,0x6F5C,0x6F5D,0x6F5E,0x6F5F, + 0x6F60,0x6F61,0x6F62,0x6F63,0x6F64,0x6F65,0x6F66,0x6F67,0x6F68,0x6F69,0x6F6A,0x6F6B,0x6F6C,0x6F6D,0x6F6E,0x6F6F, + 0x6F70,0x6F71,0x6F72,0x6F73,0x6F74,0x6F75,0x6F76,0x6F77,0x6F78,0x6F79,0x6F7A,0x6F7B,0x6F7C,0x6F7D,0x6F7E,0x6F7F, + 0x6F80,0x6F81,0x6F82,0x6F83,0x6F84,0x6F85,0x6F86,0x6F87,0x6F88,0x6F89,0x6F8A,0x6F8B,0x6F8C,0x6F8D,0x6F8E,0x6F8F, + 0x6F90,0x6F91,0x6F92,0x6F93,0x6F94,0x6F95,0x6F96,0x6F97,0x6F98,0x6F99,0x6F9A,0x6F9B,0x6F9C,0x6F9D,0x6F9E,0x6F9F, + 0x6FA0,0x6FA1,0x6FA2,0x6FA3,0x6FA4,0x6FA5,0x6FA6,0x6FA7,0x6FA8,0x6FA9,0x6FAA,0x6FAB,0x6FAC,0x6FAD,0x6FAE,0x6FAF, + 0x6FB0,0x6FB1,0x6FB2,0x6FB3,0x6FB4,0x6FB5,0x6FB6,0x6FB7,0x6FB8,0x6FB9,0x6FBA,0x6FBB,0x6FBC,0x6FBD,0x6FBE,0x6FBF, + 0x6FC0,0x6FC1,0x6FC2,0x6FC3,0x6FC4,0x6FC5,0x6FC6,0x6FC7,0x6FC8,0x6FC9,0x6FCA,0x6FCB,0x6FCC,0x6FCD,0x6FCE,0x6FCF, + 0x6FD0,0x6FD1,0x6FD2,0x6FD3,0x6FD4,0x6FD5,0x6FD6,0x6FD7,0x6FD8,0x6FD9,0x6FDA,0x6FDB,0x6FDC,0x6FDD,0x6FDE,0x6FDF, + 0x6FE0,0x6FE1,0x6FE2,0x6FE3,0x6FE4,0x6FE5,0x6FE6,0x6FE7,0x6FE8,0x6FE9,0x6FEA,0x6FEB,0x6FEC,0x6FED,0x6FEE,0x6FEF, + 0x6FF0,0x6FF1,0x6FF2,0x6FF3,0x6FF4,0x6FF5,0x6FF6,0x6FF7,0x6FF8,0x6FF9,0x6FFA,0x6FFB,0x6FFC,0x6FFD,0x6FFE,0x6FFF, + 0x7000,0x7001,0x7002,0x7003,0x7004,0x7005,0x7006,0x7007,0x7008,0x7009,0x700A,0x700B,0x700C,0x700D,0x700E,0x700F, + 0x7010,0x7011,0x7012,0x7013,0x7014,0x7015,0x7016,0x7017,0x7018,0x7019,0x701A,0x701B,0x701C,0x701D,0x701E,0x701F, + 0x7020,0x7021,0x7022,0x7023,0x7024,0x7025,0x7026,0x7027,0x7028,0x7029,0x702A,0x702B,0x702C,0x702D,0x702E,0x702F, + 0x7030,0x7031,0x7032,0x7033,0x7034,0x7035,0x7036,0x7037,0x7038,0x7039,0x703A,0x703B,0x703C,0x703D,0x703E,0x703F, + 0x7040,0x7041,0x7042,0x7043,0x7044,0x7045,0x7046,0x7047,0x7048,0x7049,0x704A,0x704B,0x704C,0x704D,0x704E,0x704F, + 0x7050,0x7051,0x7052,0x7053,0x7054,0x7055,0x7056,0x7057,0x7058,0x7059,0x705A,0x705B,0x705C,0x705D,0x705E,0x705F, + 0x7060,0x7061,0x7062,0x7063,0x7064,0x7065,0x7066,0x7067,0x7068,0x7069,0x706A,0x706B,0x706C,0x706D,0x706E,0x706F, + 0x7070,0x7071,0x7072,0x7073,0x7074,0x7075,0x7076,0x7077,0x7078,0x7079,0x707A,0x707B,0x707C,0x707D,0x707E,0x707F, + 0x7080,0x7081,0x7082,0x7083,0x7084,0x7085,0x7086,0x7087,0x7088,0x7089,0x708A,0x708B,0x708C,0x708D,0x708E,0x708F, + 0x7090,0x7091,0x7092,0x7093,0x7094,0x7095,0x7096,0x7097,0x7098,0x7099,0x709A,0x709B,0x709C,0x709D,0x709E,0x709F, + 0x70A0,0x70A1,0x70A2,0x70A3,0x70A4,0x70A5,0x70A6,0x70A7,0x70A8,0x70A9,0x70AA,0x70AB,0x70AC,0x70AD,0x70AE,0x70AF, + 0x70B0,0x70B1,0x70B2,0x70B3,0x70B4,0x70B5,0x70B6,0x70B7,0x70B8,0x70B9,0x70BA,0x70BB,0x70BC,0x70BD,0x70BE,0x70BF, + 0x70C0,0x70C1,0x70C2,0x70C3,0x70C4,0x70C5,0x70C6,0x70C7,0x70C8,0x70C9,0x70CA,0x70CB,0x70CC,0x70CD,0x70CE,0x70CF, + 0x70D0,0x70D1,0x70D2,0x70D3,0x70D4,0x70D5,0x70D6,0x70D7,0x70D8,0x70D9,0x70DA,0x70DB,0x70DC,0x70DD,0x70DE,0x70DF, + 0x70E0,0x70E1,0x70E2,0x70E3,0x70E4,0x70E5,0x70E6,0x70E7,0x70E8,0x70E9,0x70EA,0x70EB,0x70EC,0x70ED,0x70EE,0x70EF, + 0x70F0,0x70F1,0x70F2,0x70F3,0x70F4,0x70F5,0x70F6,0x70F7,0x70F8,0x70F9,0x70FA,0x70FB,0x70FC,0x70FD,0x70FE,0x70FF, + 0x7100,0x7101,0x7102,0x7103,0x7104,0x7105,0x7106,0x7107,0x7108,0x7109,0x710A,0x710B,0x710C,0x710D,0x710E,0x710F, + 0x7110,0x7111,0x7112,0x7113,0x7114,0x7115,0x7116,0x7117,0x7118,0x7119,0x711A,0x711B,0x711C,0x711D,0x711E,0x711F, + 0x7120,0x7121,0x7122,0x7123,0x7124,0x7125,0x7126,0x7127,0x7128,0x7129,0x712A,0x712B,0x712C,0x712D,0x712E,0x712F, + 0x7130,0x7131,0x7132,0x7133,0x7134,0x7135,0x7136,0x7137,0x7138,0x7139,0x713A,0x713B,0x713C,0x713D,0x713E,0x713F, + 0x7140,0x7141,0x7142,0x7143,0x7144,0x7145,0x7146,0x7147,0x7148,0x7149,0x714A,0x714B,0x714C,0x714D,0x714E,0x714F, + 0x7150,0x7151,0x7152,0x7153,0x7154,0x7155,0x7156,0x7157,0x7158,0x7159,0x715A,0x715B,0x715C,0x715D,0x715E,0x715F, + 0x7160,0x7161,0x7162,0x7163,0x7164,0x7165,0x7166,0x7167,0x7168,0x7169,0x716A,0x716B,0x716C,0x716D,0x716E,0x716F, + 0x7170,0x7171,0x7172,0x7173,0x7174,0x7175,0x7176,0x7177,0x7178,0x7179,0x717A,0x717B,0x717C,0x717D,0x717E,0x717F, + 0x7180,0x7181,0x7182,0x7183,0x7184,0x7185,0x7186,0x7187,0x7188,0x7189,0x718A,0x718B,0x718C,0x718D,0x718E,0x718F, + 0x7190,0x7191,0x7192,0x7193,0x7194,0x7195,0x7196,0x7197,0x7198,0x7199,0x719A,0x719B,0x719C,0x719D,0x719E,0x719F, + 0x71A0,0x71A1,0x71A2,0x71A3,0x71A4,0x71A5,0x71A6,0x71A7,0x71A8,0x71A9,0x71AA,0x71AB,0x71AC,0x71AD,0x71AE,0x71AF, + 0x71B0,0x71B1,0x71B2,0x71B3,0x71B4,0x71B5,0x71B6,0x71B7,0x71B8,0x71B9,0x71BA,0x71BB,0x71BC,0x71BD,0x71BE,0x71BF, + 0x71C0,0x71C1,0x71C2,0x71C3,0x71C4,0x71C5,0x71C6,0x71C7,0x71C8,0x71C9,0x71CA,0x71CB,0x71CC,0x71CD,0x71CE,0x71CF, + 0x71D0,0x71D1,0x71D2,0x71D3,0x71D4,0x71D5,0x71D6,0x71D7,0x71D8,0x71D9,0x71DA,0x71DB,0x71DC,0x71DD,0x71DE,0x71DF, + 0x71E0,0x71E1,0x71E2,0x71E3,0x71E4,0x71E5,0x71E6,0x71E7,0x71E8,0x71E9,0x71EA,0x71EB,0x71EC,0x71ED,0x71EE,0x71EF, + 0x71F0,0x71F1,0x71F2,0x71F3,0x71F4,0x71F5,0x71F6,0x71F7,0x71F8,0x71F9,0x71FA,0x71FB,0x71FC,0x71FD,0x71FE,0x71FF, + 0x7200,0x7201,0x7202,0x7203,0x7204,0x7205,0x7206,0x7207,0x7208,0x7209,0x720A,0x720B,0x720C,0x720D,0x720E,0x720F, + 0x7210,0x7211,0x7212,0x7213,0x7214,0x7215,0x7216,0x7217,0x7218,0x7219,0x721A,0x721B,0x721C,0x721D,0x721E,0x721F, + 0x7220,0x7221,0x7222,0x7223,0x7224,0x7225,0x7226,0x7227,0x7228,0x7229,0x722A,0x722B,0x722C,0x722D,0x722E,0x722F, + 0x7230,0x7231,0x7232,0x7233,0x7234,0x7235,0x7236,0x7237,0x7238,0x7239,0x723A,0x723B,0x723C,0x723D,0x723E,0x723F, + 0x7240,0x7241,0x7242,0x7243,0x7244,0x7245,0x7246,0x7247,0x7248,0x7249,0x724A,0x724B,0x724C,0x724D,0x724E,0x724F, + 0x7250,0x7251,0x7252,0x7253,0x7254,0x7255,0x7256,0x7257,0x7258,0x7259,0x725A,0x725B,0x725C,0x725D,0x725E,0x725F, + 0x7260,0x7261,0x7262,0x7263,0x7264,0x7265,0x7266,0x7267,0x7268,0x7269,0x726A,0x726B,0x726C,0x726D,0x726E,0x726F, + 0x7270,0x7271,0x7272,0x7273,0x7274,0x7275,0x7276,0x7277,0x7278,0x7279,0x727A,0x727B,0x727C,0x727D,0x727E,0x727F, + 0x7280,0x7281,0x7282,0x7283,0x7284,0x7285,0x7286,0x7287,0x7288,0x7289,0x728A,0x728B,0x728C,0x728D,0x728E,0x728F, + 0x7290,0x7291,0x7292,0x7293,0x7294,0x7295,0x7296,0x7297,0x7298,0x7299,0x729A,0x729B,0x729C,0x729D,0x729E,0x729F, + 0x72A0,0x72A1,0x72A2,0x72A3,0x72A4,0x72A5,0x72A6,0x72A7,0x72A8,0x72A9,0x72AA,0x72AB,0x72AC,0x72AD,0x72AE,0x72AF, + 0x72B0,0x72B1,0x72B2,0x72B3,0x72B4,0x72B5,0x72B6,0x72B7,0x72B8,0x72B9,0x72BA,0x72BB,0x72BC,0x72BD,0x72BE,0x72BF, + 0x72C0,0x72C1,0x72C2,0x72C3,0x72C4,0x72C5,0x72C6,0x72C7,0x72C8,0x72C9,0x72CA,0x72CB,0x72CC,0x72CD,0x72CE,0x72CF, + 0x72D0,0x72D1,0x72D2,0x72D3,0x72D4,0x72D5,0x72D6,0x72D7,0x72D8,0x72D9,0x72DA,0x72DB,0x72DC,0x72DD,0x72DE,0x72DF, + 0x72E0,0x72E1,0x72E2,0x72E3,0x72E4,0x72E5,0x72E6,0x72E7,0x72E8,0x72E9,0x72EA,0x72EB,0x72EC,0x72ED,0x72EE,0x72EF, + 0x72F0,0x72F1,0x72F2,0x72F3,0x72F4,0x72F5,0x72F6,0x72F7,0x72F8,0x72F9,0x72FA,0x72FB,0x72FC,0x72FD,0x72FE,0x72FF, + 0x7300,0x7301,0x7302,0x7303,0x7304,0x7305,0x7306,0x7307,0x7308,0x7309,0x730A,0x730B,0x730C,0x730D,0x730E,0x730F, + 0x7310,0x7311,0x7312,0x7313,0x7314,0x7315,0x7316,0x7317,0x7318,0x7319,0x731A,0x731B,0x731C,0x731D,0x731E,0x731F, + 0x7320,0x7321,0x7322,0x7323,0x7324,0x7325,0x7326,0x7327,0x7328,0x7329,0x732A,0x732B,0x732C,0x732D,0x732E,0x732F, + 0x7330,0x7331,0x7332,0x7333,0x7334,0x7335,0x7336,0x7337,0x7338,0x7339,0x733A,0x733B,0x733C,0x733D,0x733E,0x733F, + 0x7340,0x7341,0x7342,0x7343,0x7344,0x7345,0x7346,0x7347,0x7348,0x7349,0x734A,0x734B,0x734C,0x734D,0x734E,0x734F, + 0x7350,0x7351,0x7352,0x7353,0x7354,0x7355,0x7356,0x7357,0x7358,0x7359,0x735A,0x735B,0x735C,0x735D,0x735E,0x735F, + 0x7360,0x7361,0x7362,0x7363,0x7364,0x7365,0x7366,0x7367,0x7368,0x7369,0x736A,0x736B,0x736C,0x736D,0x736E,0x736F, + 0x7370,0x7371,0x7372,0x7373,0x7374,0x7375,0x7376,0x7377,0x7378,0x7379,0x737A,0x737B,0x737C,0x737D,0x737E,0x737F, + 0x7380,0x7381,0x7382,0x7383,0x7384,0x7385,0x7386,0x7387,0x7388,0x7389,0x738A,0x738B,0x738C,0x738D,0x738E,0x738F, + 0x7390,0x7391,0x7392,0x7393,0x7394,0x7395,0x7396,0x7397,0x7398,0x7399,0x739A,0x739B,0x739C,0x739D,0x739E,0x739F, + 0x73A0,0x73A1,0x73A2,0x73A3,0x73A4,0x73A5,0x73A6,0x73A7,0x73A8,0x73A9,0x73AA,0x73AB,0x73AC,0x73AD,0x73AE,0x73AF, + 0x73B0,0x73B1,0x73B2,0x73B3,0x73B4,0x73B5,0x73B6,0x73B7,0x73B8,0x73B9,0x73BA,0x73BB,0x73BC,0x73BD,0x73BE,0x73BF, + 0x73C0,0x73C1,0x73C2,0x73C3,0x73C4,0x73C5,0x73C6,0x73C7,0x73C8,0x73C9,0x73CA,0x73CB,0x73CC,0x73CD,0x73CE,0x73CF, + 0x73D0,0x73D1,0x73D2,0x73D3,0x73D4,0x73D5,0x73D6,0x73D7,0x73D8,0x73D9,0x73DA,0x73DB,0x73DC,0x73DD,0x73DE,0x73DF, + 0x73E0,0x73E1,0x73E2,0x73E3,0x73E4,0x73E5,0x73E6,0x73E7,0x73E8,0x73E9,0x73EA,0x73EB,0x73EC,0x73ED,0x73EE,0x73EF, + 0x73F0,0x73F1,0x73F2,0x73F3,0x73F4,0x73F5,0x73F6,0x73F7,0x73F8,0x73F9,0x73FA,0x73FB,0x73FC,0x73FD,0x73FE,0x73FF, + 0x7400,0x7401,0x7402,0x7403,0x7404,0x7405,0x7406,0x7407,0x7408,0x7409,0x740A,0x740B,0x740C,0x740D,0x740E,0x740F, + 0x7410,0x7411,0x7412,0x7413,0x7414,0x7415,0x7416,0x7417,0x7418,0x7419,0x741A,0x741B,0x741C,0x741D,0x741E,0x741F, + 0x7420,0x7421,0x7422,0x7423,0x7424,0x7425,0x7426,0x7427,0x7428,0x7429,0x742A,0x742B,0x742C,0x742D,0x742E,0x742F, + 0x7430,0x7431,0x7432,0x7433,0x7434,0x7435,0x7436,0x7437,0x7438,0x7439,0x743A,0x743B,0x743C,0x743D,0x743E,0x743F, + 0x7440,0x7441,0x7442,0x7443,0x7444,0x7445,0x7446,0x7447,0x7448,0x7449,0x744A,0x744B,0x744C,0x744D,0x744E,0x744F, + 0x7450,0x7451,0x7452,0x7453,0x7454,0x7455,0x7456,0x7457,0x7458,0x7459,0x745A,0x745B,0x745C,0x745D,0x745E,0x745F, + 0x7460,0x7461,0x7462,0x7463,0x7464,0x7465,0x7466,0x7467,0x7468,0x7469,0x746A,0x746B,0x746C,0x746D,0x746E,0x746F, + 0x7470,0x7471,0x7472,0x7473,0x7474,0x7475,0x7476,0x7477,0x7478,0x7479,0x747A,0x747B,0x747C,0x747D,0x747E,0x747F, + 0x7480,0x7481,0x7482,0x7483,0x7484,0x7485,0x7486,0x7487,0x7488,0x7489,0x748A,0x748B,0x748C,0x748D,0x748E,0x748F, + 0x7490,0x7491,0x7492,0x7493,0x7494,0x7495,0x7496,0x7497,0x7498,0x7499,0x749A,0x749B,0x749C,0x749D,0x749E,0x749F, + 0x74A0,0x74A1,0x74A2,0x74A3,0x74A4,0x74A5,0x74A6,0x74A7,0x74A8,0x74A9,0x74AA,0x74AB,0x74AC,0x74AD,0x74AE,0x74AF, + 0x74B0,0x74B1,0x74B2,0x74B3,0x74B4,0x74B5,0x74B6,0x74B7,0x74B8,0x74B9,0x74BA,0x74BB,0x74BC,0x74BD,0x74BE,0x74BF, + 0x74C0,0x74C1,0x74C2,0x74C3,0x74C4,0x74C5,0x74C6,0x74C7,0x74C8,0x74C9,0x74CA,0x74CB,0x74CC,0x74CD,0x74CE,0x74CF, + 0x74D0,0x74D1,0x74D2,0x74D3,0x74D4,0x74D5,0x74D6,0x74D7,0x74D8,0x74D9,0x74DA,0x74DB,0x74DC,0x74DD,0x74DE,0x74DF, + 0x74E0,0x74E1,0x74E2,0x74E3,0x74E4,0x74E5,0x74E6,0x74E7,0x74E8,0x74E9,0x74EA,0x74EB,0x74EC,0x74ED,0x74EE,0x74EF, + 0x74F0,0x74F1,0x74F2,0x74F3,0x74F4,0x74F5,0x74F6,0x74F7,0x74F8,0x74F9,0x74FA,0x74FB,0x74FC,0x74FD,0x74FE,0x74FF, + 0x7500,0x7501,0x7502,0x7503,0x7504,0x7505,0x7506,0x7507,0x7508,0x7509,0x750A,0x750B,0x750C,0x750D,0x750E,0x750F, + 0x7510,0x7511,0x7512,0x7513,0x7514,0x7515,0x7516,0x7517,0x7518,0x7519,0x751A,0x751B,0x751C,0x751D,0x751E,0x751F, + 0x7520,0x7521,0x7522,0x7523,0x7524,0x7525,0x7526,0x7527,0x7528,0x7529,0x752A,0x752B,0x752C,0x752D,0x752E,0x752F, + 0x7530,0x7531,0x7532,0x7533,0x7534,0x7535,0x7536,0x7537,0x7538,0x7539,0x753A,0x753B,0x753C,0x753D,0x753E,0x753F, + 0x7540,0x7541,0x7542,0x7543,0x7544,0x7545,0x7546,0x7547,0x7548,0x7549,0x754A,0x754B,0x754C,0x754D,0x754E,0x754F, + 0x7550,0x7551,0x7552,0x7553,0x7554,0x7555,0x7556,0x7557,0x7558,0x7559,0x755A,0x755B,0x755C,0x755D,0x755E,0x755F, + 0x7560,0x7561,0x7562,0x7563,0x7564,0x7565,0x7566,0x7567,0x7568,0x7569,0x756A,0x756B,0x756C,0x756D,0x756E,0x756F, + 0x7570,0x7571,0x7572,0x7573,0x7574,0x7575,0x7576,0x7577,0x7578,0x7579,0x757A,0x757B,0x757C,0x757D,0x757E,0x757F, + 0x7580,0x7581,0x7582,0x7583,0x7584,0x7585,0x7586,0x7587,0x7588,0x7589,0x758A,0x758B,0x758C,0x758D,0x758E,0x758F, + 0x7590,0x7591,0x7592,0x7593,0x7594,0x7595,0x7596,0x7597,0x7598,0x7599,0x759A,0x759B,0x759C,0x759D,0x759E,0x759F, + 0x75A0,0x75A1,0x75A2,0x75A3,0x75A4,0x75A5,0x75A6,0x75A7,0x75A8,0x75A9,0x75AA,0x75AB,0x75AC,0x75AD,0x75AE,0x75AF, + 0x75B0,0x75B1,0x75B2,0x75B3,0x75B4,0x75B5,0x75B6,0x75B7,0x75B8,0x75B9,0x75BA,0x75BB,0x75BC,0x75BD,0x75BE,0x75BF, + 0x75C0,0x75C1,0x75C2,0x75C3,0x75C4,0x75C5,0x75C6,0x75C7,0x75C8,0x75C9,0x75CA,0x75CB,0x75CC,0x75CD,0x75CE,0x75CF, + 0x75D0,0x75D1,0x75D2,0x75D3,0x75D4,0x75D5,0x75D6,0x75D7,0x75D8,0x75D9,0x75DA,0x75DB,0x75DC,0x75DD,0x75DE,0x75DF, + 0x75E0,0x75E1,0x75E2,0x75E3,0x75E4,0x75E5,0x75E6,0x75E7,0x75E8,0x75E9,0x75EA,0x75EB,0x75EC,0x75ED,0x75EE,0x75EF, + 0x75F0,0x75F1,0x75F2,0x75F3,0x75F4,0x75F5,0x75F6,0x75F7,0x75F8,0x75F9,0x75FA,0x75FB,0x75FC,0x75FD,0x75FE,0x75FF, + 0x7600,0x7601,0x7602,0x7603,0x7604,0x7605,0x7606,0x7607,0x7608,0x7609,0x760A,0x760B,0x760C,0x760D,0x760E,0x760F, + 0x7610,0x7611,0x7612,0x7613,0x7614,0x7615,0x7616,0x7617,0x7618,0x7619,0x761A,0x761B,0x761C,0x761D,0x761E,0x761F, + 0x7620,0x7621,0x7622,0x7623,0x7624,0x7625,0x7626,0x7627,0x7628,0x7629,0x762A,0x762B,0x762C,0x762D,0x762E,0x762F, + 0x7630,0x7631,0x7632,0x7633,0x7634,0x7635,0x7636,0x7637,0x7638,0x7639,0x763A,0x763B,0x763C,0x763D,0x763E,0x763F, + 0x7640,0x7641,0x7642,0x7643,0x7644,0x7645,0x7646,0x7647,0x7648,0x7649,0x764A,0x764B,0x764C,0x764D,0x764E,0x764F, + 0x7650,0x7651,0x7652,0x7653,0x7654,0x7655,0x7656,0x7657,0x7658,0x7659,0x765A,0x765B,0x765C,0x765D,0x765E,0x765F, + 0x7660,0x7661,0x7662,0x7663,0x7664,0x7665,0x7666,0x7667,0x7668,0x7669,0x766A,0x766B,0x766C,0x766D,0x766E,0x766F, + 0x7670,0x7671,0x7672,0x7673,0x7674,0x7675,0x7676,0x7677,0x7678,0x7679,0x767A,0x767B,0x767C,0x767D,0x767E,0x767F, + 0x7680,0x7681,0x7682,0x7683,0x7684,0x7685,0x7686,0x7687,0x7688,0x7689,0x768A,0x768B,0x768C,0x768D,0x768E,0x768F, + 0x7690,0x7691,0x7692,0x7693,0x7694,0x7695,0x7696,0x7697,0x7698,0x7699,0x769A,0x769B,0x769C,0x769D,0x769E,0x769F, + 0x76A0,0x76A1,0x76A2,0x76A3,0x76A4,0x76A5,0x76A6,0x76A7,0x76A8,0x76A9,0x76AA,0x76AB,0x76AC,0x76AD,0x76AE,0x76AF, + 0x76B0,0x76B1,0x76B2,0x76B3,0x76B4,0x76B5,0x76B6,0x76B7,0x76B8,0x76B9,0x76BA,0x76BB,0x76BC,0x76BD,0x76BE,0x76BF, + 0x76C0,0x76C1,0x76C2,0x76C3,0x76C4,0x76C5,0x76C6,0x76C7,0x76C8,0x76C9,0x76CA,0x76CB,0x76CC,0x76CD,0x76CE,0x76CF, + 0x76D0,0x76D1,0x76D2,0x76D3,0x76D4,0x76D5,0x76D6,0x76D7,0x76D8,0x76D9,0x76DA,0x76DB,0x76DC,0x76DD,0x76DE,0x76DF, + 0x76E0,0x76E1,0x76E2,0x76E3,0x76E4,0x76E5,0x76E6,0x76E7,0x76E8,0x76E9,0x76EA,0x76EB,0x76EC,0x76ED,0x76EE,0x76EF, + 0x76F0,0x76F1,0x76F2,0x76F3,0x76F4,0x76F5,0x76F6,0x76F7,0x76F8,0x76F9,0x76FA,0x76FB,0x76FC,0x76FD,0x76FE,0x76FF, + 0x7700,0x7701,0x7702,0x7703,0x7704,0x7705,0x7706,0x7707,0x7708,0x7709,0x770A,0x770B,0x770C,0x770D,0x770E,0x770F, + 0x7710,0x7711,0x7712,0x7713,0x7714,0x7715,0x7716,0x7717,0x7718,0x7719,0x771A,0x771B,0x771C,0x771D,0x771E,0x771F, + 0x7720,0x7721,0x7722,0x7723,0x7724,0x7725,0x7726,0x7727,0x7728,0x7729,0x772A,0x772B,0x772C,0x772D,0x772E,0x772F, + 0x7730,0x7731,0x7732,0x7733,0x7734,0x7735,0x7736,0x7737,0x7738,0x7739,0x773A,0x773B,0x773C,0x773D,0x773E,0x773F, + 0x7740,0x7741,0x7742,0x7743,0x7744,0x7745,0x7746,0x7747,0x7748,0x7749,0x774A,0x774B,0x774C,0x774D,0x774E,0x774F, + 0x7750,0x7751,0x7752,0x7753,0x7754,0x7755,0x7756,0x7757,0x7758,0x7759,0x775A,0x775B,0x775C,0x775D,0x775E,0x775F, + 0x7760,0x7761,0x7762,0x7763,0x7764,0x7765,0x7766,0x7767,0x7768,0x7769,0x776A,0x776B,0x776C,0x776D,0x776E,0x776F, + 0x7770,0x7771,0x7772,0x7773,0x7774,0x7775,0x7776,0x7777,0x7778,0x7779,0x777A,0x777B,0x777C,0x777D,0x777E,0x777F, + 0x7780,0x7781,0x7782,0x7783,0x7784,0x7785,0x7786,0x7787,0x7788,0x7789,0x778A,0x778B,0x778C,0x778D,0x778E,0x778F, + 0x7790,0x7791,0x7792,0x7793,0x7794,0x7795,0x7796,0x7797,0x7798,0x7799,0x779A,0x779B,0x779C,0x779D,0x779E,0x779F, + 0x77A0,0x77A1,0x77A2,0x77A3,0x77A4,0x77A5,0x77A6,0x77A7,0x77A8,0x77A9,0x77AA,0x77AB,0x77AC,0x77AD,0x77AE,0x77AF, + 0x77B0,0x77B1,0x77B2,0x77B3,0x77B4,0x77B5,0x77B6,0x77B7,0x77B8,0x77B9,0x77BA,0x77BB,0x77BC,0x77BD,0x77BE,0x77BF, + 0x77C0,0x77C1,0x77C2,0x77C3,0x77C4,0x77C5,0x77C6,0x77C7,0x77C8,0x77C9,0x77CA,0x77CB,0x77CC,0x77CD,0x77CE,0x77CF, + 0x77D0,0x77D1,0x77D2,0x77D3,0x77D4,0x77D5,0x77D6,0x77D7,0x77D8,0x77D9,0x77DA,0x77DB,0x77DC,0x77DD,0x77DE,0x77DF, + 0x77E0,0x77E1,0x77E2,0x77E3,0x77E4,0x77E5,0x77E6,0x77E7,0x77E8,0x77E9,0x77EA,0x77EB,0x77EC,0x77ED,0x77EE,0x77EF, + 0x77F0,0x77F1,0x77F2,0x77F3,0x77F4,0x77F5,0x77F6,0x77F7,0x77F8,0x77F9,0x77FA,0x77FB,0x77FC,0x77FD,0x77FE,0x77FF, + 0x7800,0x7801,0x7802,0x7803,0x7804,0x7805,0x7806,0x7807,0x7808,0x7809,0x780A,0x780B,0x780C,0x780D,0x780E,0x780F, + 0x7810,0x7811,0x7812,0x7813,0x7814,0x7815,0x7816,0x7817,0x7818,0x7819,0x781A,0x781B,0x781C,0x781D,0x781E,0x781F, + 0x7820,0x7821,0x7822,0x7823,0x7824,0x7825,0x7826,0x7827,0x7828,0x7829,0x782A,0x782B,0x782C,0x782D,0x782E,0x782F, + 0x7830,0x7831,0x7832,0x7833,0x7834,0x7835,0x7836,0x7837,0x7838,0x7839,0x783A,0x783B,0x783C,0x783D,0x783E,0x783F, + 0x7840,0x7841,0x7842,0x7843,0x7844,0x7845,0x7846,0x7847,0x7848,0x7849,0x784A,0x784B,0x784C,0x784D,0x784E,0x784F, + 0x7850,0x7851,0x7852,0x7853,0x7854,0x7855,0x7856,0x7857,0x7858,0x7859,0x785A,0x785B,0x785C,0x785D,0x785E,0x785F, + 0x7860,0x7861,0x7862,0x7863,0x7864,0x7865,0x7866,0x7867,0x7868,0x7869,0x786A,0x786B,0x786C,0x786D,0x786E,0x786F, + 0x7870,0x7871,0x7872,0x7873,0x7874,0x7875,0x7876,0x7877,0x7878,0x7879,0x787A,0x787B,0x787C,0x787D,0x787E,0x787F, + 0x7880,0x7881,0x7882,0x7883,0x7884,0x7885,0x7886,0x7887,0x7888,0x7889,0x788A,0x788B,0x788C,0x788D,0x788E,0x788F, + 0x7890,0x7891,0x7892,0x7893,0x7894,0x7895,0x7896,0x7897,0x7898,0x7899,0x789A,0x789B,0x789C,0x789D,0x789E,0x789F, + 0x78A0,0x78A1,0x78A2,0x78A3,0x78A4,0x78A5,0x78A6,0x78A7,0x78A8,0x78A9,0x78AA,0x78AB,0x78AC,0x78AD,0x78AE,0x78AF, + 0x78B0,0x78B1,0x78B2,0x78B3,0x78B4,0x78B5,0x78B6,0x78B7,0x78B8,0x78B9,0x78BA,0x78BB,0x78BC,0x78BD,0x78BE,0x78BF, + 0x78C0,0x78C1,0x78C2,0x78C3,0x78C4,0x78C5,0x78C6,0x78C7,0x78C8,0x78C9,0x78CA,0x78CB,0x78CC,0x78CD,0x78CE,0x78CF, + 0x78D0,0x78D1,0x78D2,0x78D3,0x78D4,0x78D5,0x78D6,0x78D7,0x78D8,0x78D9,0x78DA,0x78DB,0x78DC,0x78DD,0x78DE,0x78DF, + 0x78E0,0x78E1,0x78E2,0x78E3,0x78E4,0x78E5,0x78E6,0x78E7,0x78E8,0x78E9,0x78EA,0x78EB,0x78EC,0x78ED,0x78EE,0x78EF, + 0x78F0,0x78F1,0x78F2,0x78F3,0x78F4,0x78F5,0x78F6,0x78F7,0x78F8,0x78F9,0x78FA,0x78FB,0x78FC,0x78FD,0x78FE,0x78FF, + 0x7900,0x7901,0x7902,0x7903,0x7904,0x7905,0x7906,0x7907,0x7908,0x7909,0x790A,0x790B,0x790C,0x790D,0x790E,0x790F, + 0x7910,0x7911,0x7912,0x7913,0x7914,0x7915,0x7916,0x7917,0x7918,0x7919,0x791A,0x791B,0x791C,0x791D,0x791E,0x791F, + 0x7920,0x7921,0x7922,0x7923,0x7924,0x7925,0x7926,0x7927,0x7928,0x7929,0x792A,0x792B,0x792C,0x792D,0x792E,0x792F, + 0x7930,0x7931,0x7932,0x7933,0x7934,0x7935,0x7936,0x7937,0x7938,0x7939,0x793A,0x793B,0x793C,0x793D,0x793E,0x793F, + 0x7940,0x7941,0x7942,0x7943,0x7944,0x7945,0x7946,0x7947,0x7948,0x7949,0x794A,0x794B,0x794C,0x794D,0x794E,0x794F, + 0x7950,0x7951,0x7952,0x7953,0x7954,0x7955,0x7956,0x7957,0x7958,0x7959,0x795A,0x795B,0x795C,0x795D,0x795E,0x795F, + 0x7960,0x7961,0x7962,0x7963,0x7964,0x7965,0x7966,0x7967,0x7968,0x7969,0x796A,0x796B,0x796C,0x796D,0x796E,0x796F, + 0x7970,0x7971,0x7972,0x7973,0x7974,0x7975,0x7976,0x7977,0x7978,0x7979,0x797A,0x797B,0x797C,0x797D,0x797E,0x797F, + 0x7980,0x7981,0x7982,0x7983,0x7984,0x7985,0x7986,0x7987,0x7988,0x7989,0x798A,0x798B,0x798C,0x798D,0x798E,0x798F, + 0x7990,0x7991,0x7992,0x7993,0x7994,0x7995,0x7996,0x7997,0x7998,0x7999,0x799A,0x799B,0x799C,0x799D,0x799E,0x799F, + 0x79A0,0x79A1,0x79A2,0x79A3,0x79A4,0x79A5,0x79A6,0x79A7,0x79A8,0x79A9,0x79AA,0x79AB,0x79AC,0x79AD,0x79AE,0x79AF, + 0x79B0,0x79B1,0x79B2,0x79B3,0x79B4,0x79B5,0x79B6,0x79B7,0x79B8,0x79B9,0x79BA,0x79BB,0x79BC,0x79BD,0x79BE,0x79BF, + 0x79C0,0x79C1,0x79C2,0x79C3,0x79C4,0x79C5,0x79C6,0x79C7,0x79C8,0x79C9,0x79CA,0x79CB,0x79CC,0x79CD,0x79CE,0x79CF, + 0x79D0,0x79D1,0x79D2,0x79D3,0x79D4,0x79D5,0x79D6,0x79D7,0x79D8,0x79D9,0x79DA,0x79DB,0x79DC,0x79DD,0x79DE,0x79DF, + 0x79E0,0x79E1,0x79E2,0x79E3,0x79E4,0x79E5,0x79E6,0x79E7,0x79E8,0x79E9,0x79EA,0x79EB,0x79EC,0x79ED,0x79EE,0x79EF, + 0x79F0,0x79F1,0x79F2,0x79F3,0x79F4,0x79F5,0x79F6,0x79F7,0x79F8,0x79F9,0x79FA,0x79FB,0x79FC,0x79FD,0x79FE,0x79FF, + 0x7A00,0x7A01,0x7A02,0x7A03,0x7A04,0x7A05,0x7A06,0x7A07,0x7A08,0x7A09,0x7A0A,0x7A0B,0x7A0C,0x7A0D,0x7A0E,0x7A0F, + 0x7A10,0x7A11,0x7A12,0x7A13,0x7A14,0x7A15,0x7A16,0x7A17,0x7A18,0x7A19,0x7A1A,0x7A1B,0x7A1C,0x7A1D,0x7A1E,0x7A1F, + 0x7A20,0x7A21,0x7A22,0x7A23,0x7A24,0x7A25,0x7A26,0x7A27,0x7A28,0x7A29,0x7A2A,0x7A2B,0x7A2C,0x7A2D,0x7A2E,0x7A2F, + 0x7A30,0x7A31,0x7A32,0x7A33,0x7A34,0x7A35,0x7A36,0x7A37,0x7A38,0x7A39,0x7A3A,0x7A3B,0x7A3C,0x7A3D,0x7A3E,0x7A3F, + 0x7A40,0x7A41,0x7A42,0x7A43,0x7A44,0x7A45,0x7A46,0x7A47,0x7A48,0x7A49,0x7A4A,0x7A4B,0x7A4C,0x7A4D,0x7A4E,0x7A4F, + 0x7A50,0x7A51,0x7A52,0x7A53,0x7A54,0x7A55,0x7A56,0x7A57,0x7A58,0x7A59,0x7A5A,0x7A5B,0x7A5C,0x7A5D,0x7A5E,0x7A5F, + 0x7A60,0x7A61,0x7A62,0x7A63,0x7A64,0x7A65,0x7A66,0x7A67,0x7A68,0x7A69,0x7A6A,0x7A6B,0x7A6C,0x7A6D,0x7A6E,0x7A6F, + 0x7A70,0x7A71,0x7A72,0x7A73,0x7A74,0x7A75,0x7A76,0x7A77,0x7A78,0x7A79,0x7A7A,0x7A7B,0x7A7C,0x7A7D,0x7A7E,0x7A7F, + 0x7A80,0x7A81,0x7A82,0x7A83,0x7A84,0x7A85,0x7A86,0x7A87,0x7A88,0x7A89,0x7A8A,0x7A8B,0x7A8C,0x7A8D,0x7A8E,0x7A8F, + 0x7A90,0x7A91,0x7A92,0x7A93,0x7A94,0x7A95,0x7A96,0x7A97,0x7A98,0x7A99,0x7A9A,0x7A9B,0x7A9C,0x7A9D,0x7A9E,0x7A9F, + 0x7AA0,0x7AA1,0x7AA2,0x7AA3,0x7AA4,0x7AA5,0x7AA6,0x7AA7,0x7AA8,0x7AA9,0x7AAA,0x7AAB,0x7AAC,0x7AAD,0x7AAE,0x7AAF, + 0x7AB0,0x7AB1,0x7AB2,0x7AB3,0x7AB4,0x7AB5,0x7AB6,0x7AB7,0x7AB8,0x7AB9,0x7ABA,0x7ABB,0x7ABC,0x7ABD,0x7ABE,0x7ABF, + 0x7AC0,0x7AC1,0x7AC2,0x7AC3,0x7AC4,0x7AC5,0x7AC6,0x7AC7,0x7AC8,0x7AC9,0x7ACA,0x7ACB,0x7ACC,0x7ACD,0x7ACE,0x7ACF, + 0x7AD0,0x7AD1,0x7AD2,0x7AD3,0x7AD4,0x7AD5,0x7AD6,0x7AD7,0x7AD8,0x7AD9,0x7ADA,0x7ADB,0x7ADC,0x7ADD,0x7ADE,0x7ADF, + 0x7AE0,0x7AE1,0x7AE2,0x7AE3,0x7AE4,0x7AE5,0x7AE6,0x7AE7,0x7AE8,0x7AE9,0x7AEA,0x7AEB,0x7AEC,0x7AED,0x7AEE,0x7AEF, + 0x7AF0,0x7AF1,0x7AF2,0x7AF3,0x7AF4,0x7AF5,0x7AF6,0x7AF7,0x7AF8,0x7AF9,0x7AFA,0x7AFB,0x7AFC,0x7AFD,0x7AFE,0x7AFF, + 0x7B00,0x7B01,0x7B02,0x7B03,0x7B04,0x7B05,0x7B06,0x7B07,0x7B08,0x7B09,0x7B0A,0x7B0B,0x7B0C,0x7B0D,0x7B0E,0x7B0F, + 0x7B10,0x7B11,0x7B12,0x7B13,0x7B14,0x7B15,0x7B16,0x7B17,0x7B18,0x7B19,0x7B1A,0x7B1B,0x7B1C,0x7B1D,0x7B1E,0x7B1F, + 0x7B20,0x7B21,0x7B22,0x7B23,0x7B24,0x7B25,0x7B26,0x7B27,0x7B28,0x7B29,0x7B2A,0x7B2B,0x7B2C,0x7B2D,0x7B2E,0x7B2F, + 0x7B30,0x7B31,0x7B32,0x7B33,0x7B34,0x7B35,0x7B36,0x7B37,0x7B38,0x7B39,0x7B3A,0x7B3B,0x7B3C,0x7B3D,0x7B3E,0x7B3F, + 0x7B40,0x7B41,0x7B42,0x7B43,0x7B44,0x7B45,0x7B46,0x7B47,0x7B48,0x7B49,0x7B4A,0x7B4B,0x7B4C,0x7B4D,0x7B4E,0x7B4F, + 0x7B50,0x7B51,0x7B52,0x7B53,0x7B54,0x7B55,0x7B56,0x7B57,0x7B58,0x7B59,0x7B5A,0x7B5B,0x7B5C,0x7B5D,0x7B5E,0x7B5F, + 0x7B60,0x7B61,0x7B62,0x7B63,0x7B64,0x7B65,0x7B66,0x7B67,0x7B68,0x7B69,0x7B6A,0x7B6B,0x7B6C,0x7B6D,0x7B6E,0x7B6F, + 0x7B70,0x7B71,0x7B72,0x7B73,0x7B74,0x7B75,0x7B76,0x7B77,0x7B78,0x7B79,0x7B7A,0x7B7B,0x7B7C,0x7B7D,0x7B7E,0x7B7F, + 0x7B80,0x7B81,0x7B82,0x7B83,0x7B84,0x7B85,0x7B86,0x7B87,0x7B88,0x7B89,0x7B8A,0x7B8B,0x7B8C,0x7B8D,0x7B8E,0x7B8F, + 0x7B90,0x7B91,0x7B92,0x7B93,0x7B94,0x7B95,0x7B96,0x7B97,0x7B98,0x7B99,0x7B9A,0x7B9B,0x7B9C,0x7B9D,0x7B9E,0x7B9F, + 0x7BA0,0x7BA1,0x7BA2,0x7BA3,0x7BA4,0x7BA5,0x7BA6,0x7BA7,0x7BA8,0x7BA9,0x7BAA,0x7BAB,0x7BAC,0x7BAD,0x7BAE,0x7BAF, + 0x7BB0,0x7BB1,0x7BB2,0x7BB3,0x7BB4,0x7BB5,0x7BB6,0x7BB7,0x7BB8,0x7BB9,0x7BBA,0x7BBB,0x7BBC,0x7BBD,0x7BBE,0x7BBF, + 0x7BC0,0x7BC1,0x7BC2,0x7BC3,0x7BC4,0x7BC5,0x7BC6,0x7BC7,0x7BC8,0x7BC9,0x7BCA,0x7BCB,0x7BCC,0x7BCD,0x7BCE,0x7BCF, + 0x7BD0,0x7BD1,0x7BD2,0x7BD3,0x7BD4,0x7BD5,0x7BD6,0x7BD7,0x7BD8,0x7BD9,0x7BDA,0x7BDB,0x7BDC,0x7BDD,0x7BDE,0x7BDF, + 0x7BE0,0x7BE1,0x7BE2,0x7BE3,0x7BE4,0x7BE5,0x7BE6,0x7BE7,0x7BE8,0x7BE9,0x7BEA,0x7BEB,0x7BEC,0x7BED,0x7BEE,0x7BEF, + 0x7BF0,0x7BF1,0x7BF2,0x7BF3,0x7BF4,0x7BF5,0x7BF6,0x7BF7,0x7BF8,0x7BF9,0x7BFA,0x7BFB,0x7BFC,0x7BFD,0x7BFE,0x7BFF, + 0x7C00,0x7C01,0x7C02,0x7C03,0x7C04,0x7C05,0x7C06,0x7C07,0x7C08,0x7C09,0x7C0A,0x7C0B,0x7C0C,0x7C0D,0x7C0E,0x7C0F, + 0x7C10,0x7C11,0x7C12,0x7C13,0x7C14,0x7C15,0x7C16,0x7C17,0x7C18,0x7C19,0x7C1A,0x7C1B,0x7C1C,0x7C1D,0x7C1E,0x7C1F, + 0x7C20,0x7C21,0x7C22,0x7C23,0x7C24,0x7C25,0x7C26,0x7C27,0x7C28,0x7C29,0x7C2A,0x7C2B,0x7C2C,0x7C2D,0x7C2E,0x7C2F, + 0x7C30,0x7C31,0x7C32,0x7C33,0x7C34,0x7C35,0x7C36,0x7C37,0x7C38,0x7C39,0x7C3A,0x7C3B,0x7C3C,0x7C3D,0x7C3E,0x7C3F, + 0x7C40,0x7C41,0x7C42,0x7C43,0x7C44,0x7C45,0x7C46,0x7C47,0x7C48,0x7C49,0x7C4A,0x7C4B,0x7C4C,0x7C4D,0x7C4E,0x7C4F, + 0x7C50,0x7C51,0x7C52,0x7C53,0x7C54,0x7C55,0x7C56,0x7C57,0x7C58,0x7C59,0x7C5A,0x7C5B,0x7C5C,0x7C5D,0x7C5E,0x7C5F, + 0x7C60,0x7C61,0x7C62,0x7C63,0x7C64,0x7C65,0x7C66,0x7C67,0x7C68,0x7C69,0x7C6A,0x7C6B,0x7C6C,0x7C6D,0x7C6E,0x7C6F, + 0x7C70,0x7C71,0x7C72,0x7C73,0x7C74,0x7C75,0x7C76,0x7C77,0x7C78,0x7C79,0x7C7A,0x7C7B,0x7C7C,0x7C7D,0x7C7E,0x7C7F, + 0x7C80,0x7C81,0x7C82,0x7C83,0x7C84,0x7C85,0x7C86,0x7C87,0x7C88,0x7C89,0x7C8A,0x7C8B,0x7C8C,0x7C8D,0x7C8E,0x7C8F, + 0x7C90,0x7C91,0x7C92,0x7C93,0x7C94,0x7C95,0x7C96,0x7C97,0x7C98,0x7C99,0x7C9A,0x7C9B,0x7C9C,0x7C9D,0x7C9E,0x7C9F, + 0x7CA0,0x7CA1,0x7CA2,0x7CA3,0x7CA4,0x7CA5,0x7CA6,0x7CA7,0x7CA8,0x7CA9,0x7CAA,0x7CAB,0x7CAC,0x7CAD,0x7CAE,0x7CAF, + 0x7CB0,0x7CB1,0x7CB2,0x7CB3,0x7CB4,0x7CB5,0x7CB6,0x7CB7,0x7CB8,0x7CB9,0x7CBA,0x7CBB,0x7CBC,0x7CBD,0x7CBE,0x7CBF, + 0x7CC0,0x7CC1,0x7CC2,0x7CC3,0x7CC4,0x7CC5,0x7CC6,0x7CC7,0x7CC8,0x7CC9,0x7CCA,0x7CCB,0x7CCC,0x7CCD,0x7CCE,0x7CCF, + 0x7CD0,0x7CD1,0x7CD2,0x7CD3,0x7CD4,0x7CD5,0x7CD6,0x7CD7,0x7CD8,0x7CD9,0x7CDA,0x7CDB,0x7CDC,0x7CDD,0x7CDE,0x7CDF, + 0x7CE0,0x7CE1,0x7CE2,0x7CE3,0x7CE4,0x7CE5,0x7CE6,0x7CE7,0x7CE8,0x7CE9,0x7CEA,0x7CEB,0x7CEC,0x7CED,0x7CEE,0x7CEF, + 0x7CF0,0x7CF1,0x7CF2,0x7CF3,0x7CF4,0x7CF5,0x7CF6,0x7CF7,0x7CF8,0x7CF9,0x7CFA,0x7CFB,0x7CFC,0x7CFD,0x7CFE,0x7CFF, + 0x7D00,0x7D01,0x7D02,0x7D03,0x7D04,0x7D05,0x7D06,0x7D07,0x7D08,0x7D09,0x7D0A,0x7D0B,0x7D0C,0x7D0D,0x7D0E,0x7D0F, + 0x7D10,0x7D11,0x7D12,0x7D13,0x7D14,0x7D15,0x7D16,0x7D17,0x7D18,0x7D19,0x7D1A,0x7D1B,0x7D1C,0x7D1D,0x7D1E,0x7D1F, + 0x7D20,0x7D21,0x7D22,0x7D23,0x7D24,0x7D25,0x7D26,0x7D27,0x7D28,0x7D29,0x7D2A,0x7D2B,0x7D2C,0x7D2D,0x7D2E,0x7D2F, + 0x7D30,0x7D31,0x7D32,0x7D33,0x7D34,0x7D35,0x7D36,0x7D37,0x7D38,0x7D39,0x7D3A,0x7D3B,0x7D3C,0x7D3D,0x7D3E,0x7D3F, + 0x7D40,0x7D41,0x7D42,0x7D43,0x7D44,0x7D45,0x7D46,0x7D47,0x7D48,0x7D49,0x7D4A,0x7D4B,0x7D4C,0x7D4D,0x7D4E,0x7D4F, + 0x7D50,0x7D51,0x7D52,0x7D53,0x7D54,0x7D55,0x7D56,0x7D57,0x7D58,0x7D59,0x7D5A,0x7D5B,0x7D5C,0x7D5D,0x7D5E,0x7D5F, + 0x7D60,0x7D61,0x7D62,0x7D63,0x7D64,0x7D65,0x7D66,0x7D67,0x7D68,0x7D69,0x7D6A,0x7D6B,0x7D6C,0x7D6D,0x7D6E,0x7D6F, + 0x7D70,0x7D71,0x7D72,0x7D73,0x7D74,0x7D75,0x7D76,0x7D77,0x7D78,0x7D79,0x7D7A,0x7D7B,0x7D7C,0x7D7D,0x7D7E,0x7D7F, + 0x7D80,0x7D81,0x7D82,0x7D83,0x7D84,0x7D85,0x7D86,0x7D87,0x7D88,0x7D89,0x7D8A,0x7D8B,0x7D8C,0x7D8D,0x7D8E,0x7D8F, + 0x7D90,0x7D91,0x7D92,0x7D93,0x7D94,0x7D95,0x7D96,0x7D97,0x7D98,0x7D99,0x7D9A,0x7D9B,0x7D9C,0x7D9D,0x7D9E,0x7D9F, + 0x7DA0,0x7DA1,0x7DA2,0x7DA3,0x7DA4,0x7DA5,0x7DA6,0x7DA7,0x7DA8,0x7DA9,0x7DAA,0x7DAB,0x7DAC,0x7DAD,0x7DAE,0x7DAF, + 0x7DB0,0x7DB1,0x7DB2,0x7DB3,0x7DB4,0x7DB5,0x7DB6,0x7DB7,0x7DB8,0x7DB9,0x7DBA,0x7DBB,0x7DBC,0x7DBD,0x7DBE,0x7DBF, + 0x7DC0,0x7DC1,0x7DC2,0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DC7,0x7DC8,0x7DC9,0x7DCA,0x7DCB,0x7DCC,0x7DCD,0x7DCE,0x7DCF, + 0x7DD0,0x7DD1,0x7DD2,0x7DD3,0x7DD4,0x7DD5,0x7DD6,0x7DD7,0x7DD8,0x7DD9,0x7DDA,0x7DDB,0x7DDC,0x7DDD,0x7DDE,0x7DDF, + 0x7DE0,0x7DE1,0x7DE2,0x7DE3,0x7DE4,0x7DE5,0x7DE6,0x7DE7,0x7DE8,0x7DE9,0x7DEA,0x7DEB,0x7DEC,0x7DED,0x7DEE,0x7DEF, + 0x7DF0,0x7DF1,0x7DF2,0x7DF3,0x7DF4,0x7DF5,0x7DF6,0x7DF7,0x7DF8,0x7DF9,0x7DFA,0x7DFB,0x7DFC,0x7DFD,0x7DFE,0x7DFF, + 0x7E00,0x7E01,0x7E02,0x7E03,0x7E04,0x7E05,0x7E06,0x7E07,0x7E08,0x7E09,0x7E0A,0x7E0B,0x7E0C,0x7E0D,0x7E0E,0x7E0F, + 0x7E10,0x7E11,0x7E12,0x7E13,0x7E14,0x7E15,0x7E16,0x7E17,0x7E18,0x7E19,0x7E1A,0x7E1B,0x7E1C,0x7E1D,0x7E1E,0x7E1F, + 0x7E20,0x7E21,0x7E22,0x7E23,0x7E24,0x7E25,0x7E26,0x7E27,0x7E28,0x7E29,0x7E2A,0x7E2B,0x7E2C,0x7E2D,0x7E2E,0x7E2F, + 0x7E30,0x7E31,0x7E32,0x7E33,0x7E34,0x7E35,0x7E36,0x7E37,0x7E38,0x7E39,0x7E3A,0x7E3B,0x7E3C,0x7E3D,0x7E3E,0x7E3F, + 0x7E40,0x7E41,0x7E42,0x7E43,0x7E44,0x7E45,0x7E46,0x7E47,0x7E48,0x7E49,0x7E4A,0x7E4B,0x7E4C,0x7E4D,0x7E4E,0x7E4F, + 0x7E50,0x7E51,0x7E52,0x7E53,0x7E54,0x7E55,0x7E56,0x7E57,0x7E58,0x7E59,0x7E5A,0x7E5B,0x7E5C,0x7E5D,0x7E5E,0x7E5F, + 0x7E60,0x7E61,0x7E62,0x7E63,0x7E64,0x7E65,0x7E66,0x7E67,0x7E68,0x7E69,0x7E6A,0x7E6B,0x7E6C,0x7E6D,0x7E6E,0x7E6F, + 0x7E70,0x7E71,0x7E72,0x7E73,0x7E74,0x7E75,0x7E76,0x7E77,0x7E78,0x7E79,0x7E7A,0x7E7B,0x7E7C,0x7E7D,0x7E7E,0x7E7F, + 0x7E80,0x7E81,0x7E82,0x7E83,0x7E84,0x7E85,0x7E86,0x7E87,0x7E88,0x7E89,0x7E8A,0x7E8B,0x7E8C,0x7E8D,0x7E8E,0x7E8F, + 0x7E90,0x7E91,0x7E92,0x7E93,0x7E94,0x7E95,0x7E96,0x7E97,0x7E98,0x7E99,0x7E9A,0x7E9B,0x7E9C,0x7E9D,0x7E9E,0x7E9F, + 0x7EA0,0x7EA1,0x7EA2,0x7EA3,0x7EA4,0x7EA5,0x7EA6,0x7EA7,0x7EA8,0x7EA9,0x7EAA,0x7EAB,0x7EAC,0x7EAD,0x7EAE,0x7EAF, + 0x7EB0,0x7EB1,0x7EB2,0x7EB3,0x7EB4,0x7EB5,0x7EB6,0x7EB7,0x7EB8,0x7EB9,0x7EBA,0x7EBB,0x7EBC,0x7EBD,0x7EBE,0x7EBF, + 0x7EC0,0x7EC1,0x7EC2,0x7EC3,0x7EC4,0x7EC5,0x7EC6,0x7EC7,0x7EC8,0x7EC9,0x7ECA,0x7ECB,0x7ECC,0x7ECD,0x7ECE,0x7ECF, + 0x7ED0,0x7ED1,0x7ED2,0x7ED3,0x7ED4,0x7ED5,0x7ED6,0x7ED7,0x7ED8,0x7ED9,0x7EDA,0x7EDB,0x7EDC,0x7EDD,0x7EDE,0x7EDF, + 0x7EE0,0x7EE1,0x7EE2,0x7EE3,0x7EE4,0x7EE5,0x7EE6,0x7EE7,0x7EE8,0x7EE9,0x7EEA,0x7EEB,0x7EEC,0x7EED,0x7EEE,0x7EEF, + 0x7EF0,0x7EF1,0x7EF2,0x7EF3,0x7EF4,0x7EF5,0x7EF6,0x7EF7,0x7EF8,0x7EF9,0x7EFA,0x7EFB,0x7EFC,0x7EFD,0x7EFE,0x7EFF, + 0x7F00,0x7F01,0x7F02,0x7F03,0x7F04,0x7F05,0x7F06,0x7F07,0x7F08,0x7F09,0x7F0A,0x7F0B,0x7F0C,0x7F0D,0x7F0E,0x7F0F, + 0x7F10,0x7F11,0x7F12,0x7F13,0x7F14,0x7F15,0x7F16,0x7F17,0x7F18,0x7F19,0x7F1A,0x7F1B,0x7F1C,0x7F1D,0x7F1E,0x7F1F, + 0x7F20,0x7F21,0x7F22,0x7F23,0x7F24,0x7F25,0x7F26,0x7F27,0x7F28,0x7F29,0x7F2A,0x7F2B,0x7F2C,0x7F2D,0x7F2E,0x7F2F, + 0x7F30,0x7F31,0x7F32,0x7F33,0x7F34,0x7F35,0x7F36,0x7F37,0x7F38,0x7F39,0x7F3A,0x7F3B,0x7F3C,0x7F3D,0x7F3E,0x7F3F, + 0x7F40,0x7F41,0x7F42,0x7F43,0x7F44,0x7F45,0x7F46,0x7F47,0x7F48,0x7F49,0x7F4A,0x7F4B,0x7F4C,0x7F4D,0x7F4E,0x7F4F, + 0x7F50,0x7F51,0x7F52,0x7F53,0x7F54,0x7F55,0x7F56,0x7F57,0x7F58,0x7F59,0x7F5A,0x7F5B,0x7F5C,0x7F5D,0x7F5E,0x7F5F, + 0x7F60,0x7F61,0x7F62,0x7F63,0x7F64,0x7F65,0x7F66,0x7F67,0x7F68,0x7F69,0x7F6A,0x7F6B,0x7F6C,0x7F6D,0x7F6E,0x7F6F, + 0x7F70,0x7F71,0x7F72,0x7F73,0x7F74,0x7F75,0x7F76,0x7F77,0x7F78,0x7F79,0x7F7A,0x7F7B,0x7F7C,0x7F7D,0x7F7E,0x7F7F, + 0x7F80,0x7F81,0x7F82,0x7F83,0x7F84,0x7F85,0x7F86,0x7F87,0x7F88,0x7F89,0x7F8A,0x7F8B,0x7F8C,0x7F8D,0x7F8E,0x7F8F, + 0x7F90,0x7F91,0x7F92,0x7F93,0x7F94,0x7F95,0x7F96,0x7F97,0x7F98,0x7F99,0x7F9A,0x7F9B,0x7F9C,0x7F9D,0x7F9E,0x7F9F, + 0x7FA0,0x7FA1,0x7FA2,0x7FA3,0x7FA4,0x7FA5,0x7FA6,0x7FA7,0x7FA8,0x7FA9,0x7FAA,0x7FAB,0x7FAC,0x7FAD,0x7FAE,0x7FAF, + 0x7FB0,0x7FB1,0x7FB2,0x7FB3,0x7FB4,0x7FB5,0x7FB6,0x7FB7,0x7FB8,0x7FB9,0x7FBA,0x7FBB,0x7FBC,0x7FBD,0x7FBE,0x7FBF, + 0x7FC0,0x7FC1,0x7FC2,0x7FC3,0x7FC4,0x7FC5,0x7FC6,0x7FC7,0x7FC8,0x7FC9,0x7FCA,0x7FCB,0x7FCC,0x7FCD,0x7FCE,0x7FCF, + 0x7FD0,0x7FD1,0x7FD2,0x7FD3,0x7FD4,0x7FD5,0x7FD6,0x7FD7,0x7FD8,0x7FD9,0x7FDA,0x7FDB,0x7FDC,0x7FDD,0x7FDE,0x7FDF, + 0x7FE0,0x7FE1,0x7FE2,0x7FE3,0x7FE4,0x7FE5,0x7FE6,0x7FE7,0x7FE8,0x7FE9,0x7FEA,0x7FEB,0x7FEC,0x7FED,0x7FEE,0x7FEF, + 0x7FF0,0x7FF1,0x7FF2,0x7FF3,0x7FF4,0x7FF5,0x7FF6,0x7FF7,0x7FF8,0x7FF9,0x7FFA,0x7FFB,0x7FFC,0x7FFD,0x7FFE,0x7FFF, + 0x8000,0x8001,0x8002,0x8003,0x8004,0x8005,0x8006,0x8007,0x8008,0x8009,0x800A,0x800B,0x800C,0x800D,0x800E,0x800F, + 0x8010,0x8011,0x8012,0x8013,0x8014,0x8015,0x8016,0x8017,0x8018,0x8019,0x801A,0x801B,0x801C,0x801D,0x801E,0x801F, + 0x8020,0x8021,0x8022,0x8023,0x8024,0x8025,0x8026,0x8027,0x8028,0x8029,0x802A,0x802B,0x802C,0x802D,0x802E,0x802F, + 0x8030,0x8031,0x8032,0x8033,0x8034,0x8035,0x8036,0x8037,0x8038,0x8039,0x803A,0x803B,0x803C,0x803D,0x803E,0x803F, + 0x8040,0x8041,0x8042,0x8043,0x8044,0x8045,0x8046,0x8047,0x8048,0x8049,0x804A,0x804B,0x804C,0x804D,0x804E,0x804F, + 0x8050,0x8051,0x8052,0x8053,0x8054,0x8055,0x8056,0x8057,0x8058,0x8059,0x805A,0x805B,0x805C,0x805D,0x805E,0x805F, + 0x8060,0x8061,0x8062,0x8063,0x8064,0x8065,0x8066,0x8067,0x8068,0x8069,0x806A,0x806B,0x806C,0x806D,0x806E,0x806F, + 0x8070,0x8071,0x8072,0x8073,0x8074,0x8075,0x8076,0x8077,0x8078,0x8079,0x807A,0x807B,0x807C,0x807D,0x807E,0x807F, + 0x8080,0x8081,0x8082,0x8083,0x8084,0x8085,0x8086,0x8087,0x8088,0x8089,0x808A,0x808B,0x808C,0x808D,0x808E,0x808F, + 0x8090,0x8091,0x8092,0x8093,0x8094,0x8095,0x8096,0x8097,0x8098,0x8099,0x809A,0x809B,0x809C,0x809D,0x809E,0x809F, + 0x80A0,0x80A1,0x80A2,0x80A3,0x80A4,0x80A5,0x80A6,0x80A7,0x80A8,0x80A9,0x80AA,0x80AB,0x80AC,0x80AD,0x80AE,0x80AF, + 0x80B0,0x80B1,0x80B2,0x80B3,0x80B4,0x80B5,0x80B6,0x80B7,0x80B8,0x80B9,0x80BA,0x80BB,0x80BC,0x80BD,0x80BE,0x80BF, + 0x80C0,0x80C1,0x80C2,0x80C3,0x80C4,0x80C5,0x80C6,0x80C7,0x80C8,0x80C9,0x80CA,0x80CB,0x80CC,0x80CD,0x80CE,0x80CF, + 0x80D0,0x80D1,0x80D2,0x80D3,0x80D4,0x80D5,0x80D6,0x80D7,0x80D8,0x80D9,0x80DA,0x80DB,0x80DC,0x80DD,0x80DE,0x80DF, + 0x80E0,0x80E1,0x80E2,0x80E3,0x80E4,0x80E5,0x80E6,0x80E7,0x80E8,0x80E9,0x80EA,0x80EB,0x80EC,0x80ED,0x80EE,0x80EF, + 0x80F0,0x80F1,0x80F2,0x80F3,0x80F4,0x80F5,0x80F6,0x80F7,0x80F8,0x80F9,0x80FA,0x80FB,0x80FC,0x80FD,0x80FE,0x80FF, + 0x8100,0x8101,0x8102,0x8103,0x8104,0x8105,0x8106,0x8107,0x8108,0x8109,0x810A,0x810B,0x810C,0x810D,0x810E,0x810F, + 0x8110,0x8111,0x8112,0x8113,0x8114,0x8115,0x8116,0x8117,0x8118,0x8119,0x811A,0x811B,0x811C,0x811D,0x811E,0x811F, + 0x8120,0x8121,0x8122,0x8123,0x8124,0x8125,0x8126,0x8127,0x8128,0x8129,0x812A,0x812B,0x812C,0x812D,0x812E,0x812F, + 0x8130,0x8131,0x8132,0x8133,0x8134,0x8135,0x8136,0x8137,0x8138,0x8139,0x813A,0x813B,0x813C,0x813D,0x813E,0x813F, + 0x8140,0x8141,0x8142,0x8143,0x8144,0x8145,0x8146,0x8147,0x8148,0x8149,0x814A,0x814B,0x814C,0x814D,0x814E,0x814F, + 0x8150,0x8151,0x8152,0x8153,0x8154,0x8155,0x8156,0x8157,0x8158,0x8159,0x815A,0x815B,0x815C,0x815D,0x815E,0x815F, + 0x8160,0x8161,0x8162,0x8163,0x8164,0x8165,0x8166,0x8167,0x8168,0x8169,0x816A,0x816B,0x816C,0x816D,0x816E,0x816F, + 0x8170,0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177,0x8178,0x8179,0x817A,0x817B,0x817C,0x817D,0x817E,0x817F, + 0x8180,0x8181,0x8182,0x8183,0x8184,0x8185,0x8186,0x8187,0x8188,0x8189,0x818A,0x818B,0x818C,0x818D,0x818E,0x818F, + 0x8190,0x8191,0x8192,0x8193,0x8194,0x8195,0x8196,0x8197,0x8198,0x8199,0x819A,0x819B,0x819C,0x819D,0x819E,0x819F, + 0x81A0,0x81A1,0x81A2,0x81A3,0x81A4,0x81A5,0x81A6,0x81A7,0x81A8,0x81A9,0x81AA,0x81AB,0x81AC,0x81AD,0x81AE,0x81AF, + 0x81B0,0x81B1,0x81B2,0x81B3,0x81B4,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9,0x81BA,0x81BB,0x81BC,0x81BD,0x81BE,0x81BF, + 0x81C0,0x81C1,0x81C2,0x81C3,0x81C4,0x81C5,0x81C6,0x81C7,0x81C8,0x81C9,0x81CA,0x81CB,0x81CC,0x81CD,0x81CE,0x81CF, + 0x81D0,0x81D1,0x81D2,0x81D3,0x81D4,0x81D5,0x81D6,0x81D7,0x81D8,0x81D9,0x81DA,0x81DB,0x81DC,0x81DD,0x81DE,0x81DF, + 0x81E0,0x81E1,0x81E2,0x81E3,0x81E4,0x81E5,0x81E6,0x81E7,0x81E8,0x81E9,0x81EA,0x81EB,0x81EC,0x81ED,0x81EE,0x81EF, + 0x81F0,0x81F1,0x81F2,0x81F3,0x81F4,0x81F5,0x81F6,0x81F7,0x81F8,0x81F9,0x81FA,0x81FB,0x81FC,0x81FD,0x81FE,0x81FF, + 0x8200,0x8201,0x8202,0x8203,0x8204,0x8205,0x8206,0x8207,0x8208,0x8209,0x820A,0x820B,0x820C,0x820D,0x820E,0x820F, + 0x8210,0x8211,0x8212,0x8213,0x8214,0x8215,0x8216,0x8217,0x8218,0x8219,0x821A,0x821B,0x821C,0x821D,0x821E,0x821F, + 0x8220,0x8221,0x8222,0x8223,0x8224,0x8225,0x8226,0x8227,0x8228,0x8229,0x822A,0x822B,0x822C,0x822D,0x822E,0x822F, + 0x8230,0x8231,0x8232,0x8233,0x8234,0x8235,0x8236,0x8237,0x8238,0x8239,0x823A,0x823B,0x823C,0x823D,0x823E,0x823F, + 0x8240,0x8241,0x8242,0x8243,0x8244,0x8245,0x8246,0x8247,0x8248,0x8249,0x824A,0x824B,0x824C,0x824D,0x824E,0x824F, + 0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257,0x8258,0x8259,0x825A,0x825B,0x825C,0x825D,0x825E,0x825F, + 0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267,0x8268,0x8269,0x826A,0x826B,0x826C,0x826D,0x826E,0x826F, + 0x8270,0x8271,0x8272,0x8273,0x8274,0x8275,0x8276,0x8277,0x8278,0x8279,0x827A,0x827B,0x827C,0x827D,0x827E,0x827F, + 0x8280,0x8281,0x8282,0x8283,0x8284,0x8285,0x8286,0x8287,0x8288,0x8289,0x828A,0x828B,0x828C,0x828D,0x828E,0x828F, + 0x8290,0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297,0x8298,0x8299,0x829A,0x829B,0x829C,0x829D,0x829E,0x829F, + 0x82A0,0x82A1,0x82A2,0x82A3,0x82A4,0x82A5,0x82A6,0x82A7,0x82A8,0x82A9,0x82AA,0x82AB,0x82AC,0x82AD,0x82AE,0x82AF, + 0x82B0,0x82B1,0x82B2,0x82B3,0x82B4,0x82B5,0x82B6,0x82B7,0x82B8,0x82B9,0x82BA,0x82BB,0x82BC,0x82BD,0x82BE,0x82BF, + 0x82C0,0x82C1,0x82C2,0x82C3,0x82C4,0x82C5,0x82C6,0x82C7,0x82C8,0x82C9,0x82CA,0x82CB,0x82CC,0x82CD,0x82CE,0x82CF, + 0x82D0,0x82D1,0x82D2,0x82D3,0x82D4,0x82D5,0x82D6,0x82D7,0x82D8,0x82D9,0x82DA,0x82DB,0x82DC,0x82DD,0x82DE,0x82DF, + 0x82E0,0x82E1,0x82E2,0x82E3,0x82E4,0x82E5,0x82E6,0x82E7,0x82E8,0x82E9,0x82EA,0x82EB,0x82EC,0x82ED,0x82EE,0x82EF, + 0x82F0,0x82F1,0x82F2,0x82F3,0x82F4,0x82F5,0x82F6,0x82F7,0x82F8,0x82F9,0x82FA,0x82FB,0x82FC,0x82FD,0x82FE,0x82FF, + 0x8300,0x8301,0x8302,0x8303,0x8304,0x8305,0x8306,0x8307,0x8308,0x8309,0x830A,0x830B,0x830C,0x830D,0x830E,0x830F, + 0x8310,0x8311,0x8312,0x8313,0x8314,0x8315,0x8316,0x8317,0x8318,0x8319,0x831A,0x831B,0x831C,0x831D,0x831E,0x831F, + 0x8320,0x8321,0x8322,0x8323,0x8324,0x8325,0x8326,0x8327,0x8328,0x8329,0x832A,0x832B,0x832C,0x832D,0x832E,0x832F, + 0x8330,0x8331,0x8332,0x8333,0x8334,0x8335,0x8336,0x8337,0x8338,0x8339,0x833A,0x833B,0x833C,0x833D,0x833E,0x833F, + 0x8340,0x8341,0x8342,0x8343,0x8344,0x8345,0x8346,0x8347,0x8348,0x8349,0x834A,0x834B,0x834C,0x834D,0x834E,0x834F, + 0x8350,0x8351,0x8352,0x8353,0x8354,0x8355,0x8356,0x8357,0x8358,0x8359,0x835A,0x835B,0x835C,0x835D,0x835E,0x835F, + 0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0x8366,0x8367,0x8368,0x8369,0x836A,0x836B,0x836C,0x836D,0x836E,0x836F, + 0x8370,0x8371,0x8372,0x8373,0x8374,0x8375,0x8376,0x8377,0x8378,0x8379,0x837A,0x837B,0x837C,0x837D,0x837E,0x837F, + 0x8380,0x8381,0x8382,0x8383,0x8384,0x8385,0x8386,0x8387,0x8388,0x8389,0x838A,0x838B,0x838C,0x838D,0x838E,0x838F, + 0x8390,0x8391,0x8392,0x8393,0x8394,0x8395,0x8396,0x8397,0x8398,0x8399,0x839A,0x839B,0x839C,0x839D,0x839E,0x839F, + 0x83A0,0x83A1,0x83A2,0x83A3,0x83A4,0x83A5,0x83A6,0x83A7,0x83A8,0x83A9,0x83AA,0x83AB,0x83AC,0x83AD,0x83AE,0x83AF, + 0x83B0,0x83B1,0x83B2,0x83B3,0x83B4,0x83B5,0x83B6,0x83B7,0x83B8,0x83B9,0x83BA,0x83BB,0x83BC,0x83BD,0x83BE,0x83BF, + 0x83C0,0x83C1,0x83C2,0x83C3,0x83C4,0x83C5,0x83C6,0x83C7,0x83C8,0x83C9,0x83CA,0x83CB,0x83CC,0x83CD,0x83CE,0x83CF, + 0x83D0,0x83D1,0x83D2,0x83D3,0x83D4,0x83D5,0x83D6,0x83D7,0x83D8,0x83D9,0x83DA,0x83DB,0x83DC,0x83DD,0x83DE,0x83DF, + 0x83E0,0x83E1,0x83E2,0x83E3,0x83E4,0x83E5,0x83E6,0x83E7,0x83E8,0x83E9,0x83EA,0x83EB,0x83EC,0x83ED,0x83EE,0x83EF, + 0x83F0,0x83F1,0x83F2,0x83F3,0x83F4,0x83F5,0x83F6,0x83F7,0x83F8,0x83F9,0x83FA,0x83FB,0x83FC,0x83FD,0x83FE,0x83FF, + 0x8400,0x8401,0x8402,0x8403,0x8404,0x8405,0x8406,0x8407,0x8408,0x8409,0x840A,0x840B,0x840C,0x840D,0x840E,0x840F, + 0x8410,0x8411,0x8412,0x8413,0x8414,0x8415,0x8416,0x8417,0x8418,0x8419,0x841A,0x841B,0x841C,0x841D,0x841E,0x841F, + 0x8420,0x8421,0x8422,0x8423,0x8424,0x8425,0x8426,0x8427,0x8428,0x8429,0x842A,0x842B,0x842C,0x842D,0x842E,0x842F, + 0x8430,0x8431,0x8432,0x8433,0x8434,0x8435,0x8436,0x8437,0x8438,0x8439,0x843A,0x843B,0x843C,0x843D,0x843E,0x843F, + 0x8440,0x8441,0x8442,0x8443,0x8444,0x8445,0x8446,0x8447,0x8448,0x8449,0x844A,0x844B,0x844C,0x844D,0x844E,0x844F, + 0x8450,0x8451,0x8452,0x8453,0x8454,0x8455,0x8456,0x8457,0x8458,0x8459,0x845A,0x845B,0x845C,0x845D,0x845E,0x845F, + 0x8460,0x8461,0x8462,0x8463,0x8464,0x8465,0x8466,0x8467,0x8468,0x8469,0x846A,0x846B,0x846C,0x846D,0x846E,0x846F, + 0x8470,0x8471,0x8472,0x8473,0x8474,0x8475,0x8476,0x8477,0x8478,0x8479,0x847A,0x847B,0x847C,0x847D,0x847E,0x847F, + 0x8480,0x8481,0x8482,0x8483,0x8484,0x8485,0x8486,0x8487,0x8488,0x8489,0x848A,0x848B,0x848C,0x848D,0x848E,0x848F, + 0x8490,0x8491,0x8492,0x8493,0x8494,0x8495,0x8496,0x8497,0x8498,0x8499,0x849A,0x849B,0x849C,0x849D,0x849E,0x849F, + 0x84A0,0x84A1,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,0x84A7,0x84A8,0x84A9,0x84AA,0x84AB,0x84AC,0x84AD,0x84AE,0x84AF, + 0x84B0,0x84B1,0x84B2,0x84B3,0x84B4,0x84B5,0x84B6,0x84B7,0x84B8,0x84B9,0x84BA,0x84BB,0x84BC,0x84BD,0x84BE,0x84BF, + 0x84C0,0x84C1,0x84C2,0x84C3,0x84C4,0x84C5,0x84C6,0x84C7,0x84C8,0x84C9,0x84CA,0x84CB,0x84CC,0x84CD,0x84CE,0x84CF, + 0x84D0,0x84D1,0x84D2,0x84D3,0x84D4,0x84D5,0x84D6,0x84D7,0x84D8,0x84D9,0x84DA,0x84DB,0x84DC,0x84DD,0x84DE,0x84DF, + 0x84E0,0x84E1,0x84E2,0x84E3,0x84E4,0x84E5,0x84E6,0x84E7,0x84E8,0x84E9,0x84EA,0x84EB,0x84EC,0x84ED,0x84EE,0x84EF, + 0x84F0,0x84F1,0x84F2,0x84F3,0x84F4,0x84F5,0x84F6,0x84F7,0x84F8,0x84F9,0x84FA,0x84FB,0x84FC,0x84FD,0x84FE,0x84FF, + 0x8500,0x8501,0x8502,0x8503,0x8504,0x8505,0x8506,0x8507,0x8508,0x8509,0x850A,0x850B,0x850C,0x850D,0x850E,0x850F, + 0x8510,0x8511,0x8512,0x8513,0x8514,0x8515,0x8516,0x8517,0x8518,0x8519,0x851A,0x851B,0x851C,0x851D,0x851E,0x851F, + 0x8520,0x8521,0x8522,0x8523,0x8524,0x8525,0x8526,0x8527,0x8528,0x8529,0x852A,0x852B,0x852C,0x852D,0x852E,0x852F, + 0x8530,0x8531,0x8532,0x8533,0x8534,0x8535,0x8536,0x8537,0x8538,0x8539,0x853A,0x853B,0x853C,0x853D,0x853E,0x853F, + 0x8540,0x8541,0x8542,0x8543,0x8544,0x8545,0x8546,0x8547,0x8548,0x8549,0x854A,0x854B,0x854C,0x854D,0x854E,0x854F, + 0x8550,0x8551,0x8552,0x8553,0x8554,0x8555,0x8556,0x8557,0x8558,0x8559,0x855A,0x855B,0x855C,0x855D,0x855E,0x855F, + 0x8560,0x8561,0x8562,0x8563,0x8564,0x8565,0x8566,0x8567,0x8568,0x8569,0x856A,0x856B,0x856C,0x856D,0x856E,0x856F, + 0x8570,0x8571,0x8572,0x8573,0x8574,0x8575,0x8576,0x8577,0x8578,0x8579,0x857A,0x857B,0x857C,0x857D,0x857E,0x857F, + 0x8580,0x8581,0x8582,0x8583,0x8584,0x8585,0x8586,0x8587,0x8588,0x8589,0x858A,0x858B,0x858C,0x858D,0x858E,0x858F, + 0x8590,0x8591,0x8592,0x8593,0x8594,0x8595,0x8596,0x8597,0x8598,0x8599,0x859A,0x859B,0x859C,0x859D,0x859E,0x859F, + 0x85A0,0x85A1,0x85A2,0x85A3,0x85A4,0x85A5,0x85A6,0x85A7,0x85A8,0x85A9,0x85AA,0x85AB,0x85AC,0x85AD,0x85AE,0x85AF, + 0x85B0,0x85B1,0x85B2,0x85B3,0x85B4,0x85B5,0x85B6,0x85B7,0x85B8,0x85B9,0x85BA,0x85BB,0x85BC,0x85BD,0x85BE,0x85BF, + 0x85C0,0x85C1,0x85C2,0x85C3,0x85C4,0x85C5,0x85C6,0x85C7,0x85C8,0x85C9,0x85CA,0x85CB,0x85CC,0x85CD,0x85CE,0x85CF, + 0x85D0,0x85D1,0x85D2,0x85D3,0x85D4,0x85D5,0x85D6,0x85D7,0x85D8,0x85D9,0x85DA,0x85DB,0x85DC,0x85DD,0x85DE,0x85DF, + 0x85E0,0x85E1,0x85E2,0x85E3,0x85E4,0x85E5,0x85E6,0x85E7,0x85E8,0x85E9,0x85EA,0x85EB,0x85EC,0x85ED,0x85EE,0x85EF, + 0x85F0,0x85F1,0x85F2,0x85F3,0x85F4,0x85F5,0x85F6,0x85F7,0x85F8,0x85F9,0x85FA,0x85FB,0x85FC,0x85FD,0x85FE,0x85FF, + 0x8600,0x8601,0x8602,0x8603,0x8604,0x8605,0x8606,0x8607,0x8608,0x8609,0x860A,0x860B,0x860C,0x860D,0x860E,0x860F, + 0x8610,0x8611,0x8612,0x8613,0x8614,0x8615,0x8616,0x8617,0x8618,0x8619,0x861A,0x861B,0x861C,0x861D,0x861E,0x861F, + 0x8620,0x8621,0x8622,0x8623,0x8624,0x8625,0x8626,0x8627,0x8628,0x8629,0x862A,0x862B,0x862C,0x862D,0x862E,0x862F, + 0x8630,0x8631,0x8632,0x8633,0x8634,0x8635,0x8636,0x8637,0x8638,0x8639,0x863A,0x863B,0x863C,0x863D,0x863E,0x863F, + 0x8640,0x8641,0x8642,0x8643,0x8644,0x8645,0x8646,0x8647,0x8648,0x8649,0x864A,0x864B,0x864C,0x864D,0x864E,0x864F, + 0x8650,0x8651,0x8652,0x8653,0x8654,0x8655,0x8656,0x8657,0x8658,0x8659,0x865A,0x865B,0x865C,0x865D,0x865E,0x865F, + 0x8660,0x8661,0x8662,0x8663,0x8664,0x8665,0x8666,0x8667,0x8668,0x8669,0x866A,0x866B,0x866C,0x866D,0x866E,0x866F, + 0x8670,0x8671,0x8672,0x8673,0x8674,0x8675,0x8676,0x8677,0x8678,0x8679,0x867A,0x867B,0x867C,0x867D,0x867E,0x867F, + 0x8680,0x8681,0x8682,0x8683,0x8684,0x8685,0x8686,0x8687,0x8688,0x8689,0x868A,0x868B,0x868C,0x868D,0x868E,0x868F, + 0x8690,0x8691,0x8692,0x8693,0x8694,0x8695,0x8696,0x8697,0x8698,0x8699,0x869A,0x869B,0x869C,0x869D,0x869E,0x869F, + 0x86A0,0x86A1,0x86A2,0x86A3,0x86A4,0x86A5,0x86A6,0x86A7,0x86A8,0x86A9,0x86AA,0x86AB,0x86AC,0x86AD,0x86AE,0x86AF, + 0x86B0,0x86B1,0x86B2,0x86B3,0x86B4,0x86B5,0x86B6,0x86B7,0x86B8,0x86B9,0x86BA,0x86BB,0x86BC,0x86BD,0x86BE,0x86BF, + 0x86C0,0x86C1,0x86C2,0x86C3,0x86C4,0x86C5,0x86C6,0x86C7,0x86C8,0x86C9,0x86CA,0x86CB,0x86CC,0x86CD,0x86CE,0x86CF, + 0x86D0,0x86D1,0x86D2,0x86D3,0x86D4,0x86D5,0x86D6,0x86D7,0x86D8,0x86D9,0x86DA,0x86DB,0x86DC,0x86DD,0x86DE,0x86DF, + 0x86E0,0x86E1,0x86E2,0x86E3,0x86E4,0x86E5,0x86E6,0x86E7,0x86E8,0x86E9,0x86EA,0x86EB,0x86EC,0x86ED,0x86EE,0x86EF, + 0x86F0,0x86F1,0x86F2,0x86F3,0x86F4,0x86F5,0x86F6,0x86F7,0x86F8,0x86F9,0x86FA,0x86FB,0x86FC,0x86FD,0x86FE,0x86FF, + 0x8700,0x8701,0x8702,0x8703,0x8704,0x8705,0x8706,0x8707,0x8708,0x8709,0x870A,0x870B,0x870C,0x870D,0x870E,0x870F, + 0x8710,0x8711,0x8712,0x8713,0x8714,0x8715,0x8716,0x8717,0x8718,0x8719,0x871A,0x871B,0x871C,0x871D,0x871E,0x871F, + 0x8720,0x8721,0x8722,0x8723,0x8724,0x8725,0x8726,0x8727,0x8728,0x8729,0x872A,0x872B,0x872C,0x872D,0x872E,0x872F, + 0x8730,0x8731,0x8732,0x8733,0x8734,0x8735,0x8736,0x8737,0x8738,0x8739,0x873A,0x873B,0x873C,0x873D,0x873E,0x873F, + 0x8740,0x8741,0x8742,0x8743,0x8744,0x8745,0x8746,0x8747,0x8748,0x8749,0x874A,0x874B,0x874C,0x874D,0x874E,0x874F, + 0x8750,0x8751,0x8752,0x8753,0x8754,0x8755,0x8756,0x8757,0x8758,0x8759,0x875A,0x875B,0x875C,0x875D,0x875E,0x875F, + 0x8760,0x8761,0x8762,0x8763,0x8764,0x8765,0x8766,0x8767,0x8768,0x8769,0x876A,0x876B,0x876C,0x876D,0x876E,0x876F, + 0x8770,0x8771,0x8772,0x8773,0x8774,0x8775,0x8776,0x8777,0x8778,0x8779,0x877A,0x877B,0x877C,0x877D,0x877E,0x877F, + 0x8780,0x8781,0x8782,0x8783,0x8784,0x8785,0x8786,0x8787,0x8788,0x8789,0x878A,0x878B,0x878C,0x878D,0x878E,0x878F, + 0x8790,0x8791,0x8792,0x8793,0x8794,0x8795,0x8796,0x8797,0x8798,0x8799,0x879A,0x879B,0x879C,0x879D,0x879E,0x879F, + 0x87A0,0x87A1,0x87A2,0x87A3,0x87A4,0x87A5,0x87A6,0x87A7,0x87A8,0x87A9,0x87AA,0x87AB,0x87AC,0x87AD,0x87AE,0x87AF, + 0x87B0,0x87B1,0x87B2,0x87B3,0x87B4,0x87B5,0x87B6,0x87B7,0x87B8,0x87B9,0x87BA,0x87BB,0x87BC,0x87BD,0x87BE,0x87BF, + 0x87C0,0x87C1,0x87C2,0x87C3,0x87C4,0x87C5,0x87C6,0x87C7,0x87C8,0x87C9,0x87CA,0x87CB,0x87CC,0x87CD,0x87CE,0x87CF, + 0x87D0,0x87D1,0x87D2,0x87D3,0x87D4,0x87D5,0x87D6,0x87D7,0x87D8,0x87D9,0x87DA,0x87DB,0x87DC,0x87DD,0x87DE,0x87DF, + 0x87E0,0x87E1,0x87E2,0x87E3,0x87E4,0x87E5,0x87E6,0x87E7,0x87E8,0x87E9,0x87EA,0x87EB,0x87EC,0x87ED,0x87EE,0x87EF, + 0x87F0,0x87F1,0x87F2,0x87F3,0x87F4,0x87F5,0x87F6,0x87F7,0x87F8,0x87F9,0x87FA,0x87FB,0x87FC,0x87FD,0x87FE,0x87FF, + 0x8800,0x8801,0x8802,0x8803,0x8804,0x8805,0x8806,0x8807,0x8808,0x8809,0x880A,0x880B,0x880C,0x880D,0x880E,0x880F, + 0x8810,0x8811,0x8812,0x8813,0x8814,0x8815,0x8816,0x8817,0x8818,0x8819,0x881A,0x881B,0x881C,0x881D,0x881E,0x881F, + 0x8820,0x8821,0x8822,0x8823,0x8824,0x8825,0x8826,0x8827,0x8828,0x8829,0x882A,0x882B,0x882C,0x882D,0x882E,0x882F, + 0x8830,0x8831,0x8832,0x8833,0x8834,0x8835,0x8836,0x8837,0x8838,0x8839,0x883A,0x883B,0x883C,0x883D,0x883E,0x883F, + 0x8840,0x8841,0x8842,0x8843,0x8844,0x8845,0x8846,0x8847,0x8848,0x8849,0x884A,0x884B,0x884C,0x884D,0x884E,0x884F, + 0x8850,0x8851,0x8852,0x8853,0x8854,0x8855,0x8856,0x8857,0x8858,0x8859,0x885A,0x885B,0x885C,0x885D,0x885E,0x885F, + 0x8860,0x8861,0x8862,0x8863,0x8864,0x8865,0x8866,0x8867,0x8868,0x8869,0x886A,0x886B,0x886C,0x886D,0x886E,0x886F, + 0x8870,0x8871,0x8872,0x8873,0x8874,0x8875,0x8876,0x8877,0x8878,0x8879,0x887A,0x887B,0x887C,0x887D,0x887E,0x887F, + 0x8880,0x8881,0x8882,0x8883,0x8884,0x8885,0x8886,0x8887,0x8888,0x8889,0x888A,0x888B,0x888C,0x888D,0x888E,0x888F, + 0x8890,0x8891,0x8892,0x8893,0x8894,0x8895,0x8896,0x8897,0x8898,0x8899,0x889A,0x889B,0x889C,0x889D,0x889E,0x889F, + 0x88A0,0x88A1,0x88A2,0x88A3,0x88A4,0x88A5,0x88A6,0x88A7,0x88A8,0x88A9,0x88AA,0x88AB,0x88AC,0x88AD,0x88AE,0x88AF, + 0x88B0,0x88B1,0x88B2,0x88B3,0x88B4,0x88B5,0x88B6,0x88B7,0x88B8,0x88B9,0x88BA,0x88BB,0x88BC,0x88BD,0x88BE,0x88BF, + 0x88C0,0x88C1,0x88C2,0x88C3,0x88C4,0x88C5,0x88C6,0x88C7,0x88C8,0x88C9,0x88CA,0x88CB,0x88CC,0x88CD,0x88CE,0x88CF, + 0x88D0,0x88D1,0x88D2,0x88D3,0x88D4,0x88D5,0x88D6,0x88D7,0x88D8,0x88D9,0x88DA,0x88DB,0x88DC,0x88DD,0x88DE,0x88DF, + 0x88E0,0x88E1,0x88E2,0x88E3,0x88E4,0x88E5,0x88E6,0x88E7,0x88E8,0x88E9,0x88EA,0x88EB,0x88EC,0x88ED,0x88EE,0x88EF, + 0x88F0,0x88F1,0x88F2,0x88F3,0x88F4,0x88F5,0x88F6,0x88F7,0x88F8,0x88F9,0x88FA,0x88FB,0x88FC,0x88FD,0x88FE,0x88FF, + 0x8900,0x8901,0x8902,0x8903,0x8904,0x8905,0x8906,0x8907,0x8908,0x8909,0x890A,0x890B,0x890C,0x890D,0x890E,0x890F, + 0x8910,0x8911,0x8912,0x8913,0x8914,0x8915,0x8916,0x8917,0x8918,0x8919,0x891A,0x891B,0x891C,0x891D,0x891E,0x891F, + 0x8920,0x8921,0x8922,0x8923,0x8924,0x8925,0x8926,0x8927,0x8928,0x8929,0x892A,0x892B,0x892C,0x892D,0x892E,0x892F, + 0x8930,0x8931,0x8932,0x8933,0x8934,0x8935,0x8936,0x8937,0x8938,0x8939,0x893A,0x893B,0x893C,0x893D,0x893E,0x893F, + 0x8940,0x8941,0x8942,0x8943,0x8944,0x8945,0x8946,0x8947,0x8948,0x8949,0x894A,0x894B,0x894C,0x894D,0x894E,0x894F, + 0x8950,0x8951,0x8952,0x8953,0x8954,0x8955,0x8956,0x8957,0x8958,0x8959,0x895A,0x895B,0x895C,0x895D,0x895E,0x895F, + 0x8960,0x8961,0x8962,0x8963,0x8964,0x8965,0x8966,0x8967,0x8968,0x8969,0x896A,0x896B,0x896C,0x896D,0x896E,0x896F, + 0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0x8976,0x8977,0x8978,0x8979,0x897A,0x897B,0x897C,0x897D,0x897E,0x897F, + 0x8980,0x8981,0x8982,0x8983,0x8984,0x8985,0x8986,0x8987,0x8988,0x8989,0x898A,0x898B,0x898C,0x898D,0x898E,0x898F, + 0x8990,0x8991,0x8992,0x8993,0x8994,0x8995,0x8996,0x8997,0x8998,0x8999,0x899A,0x899B,0x899C,0x899D,0x899E,0x899F, + 0x89A0,0x89A1,0x89A2,0x89A3,0x89A4,0x89A5,0x89A6,0x89A7,0x89A8,0x89A9,0x89AA,0x89AB,0x89AC,0x89AD,0x89AE,0x89AF, + 0x89B0,0x89B1,0x89B2,0x89B3,0x89B4,0x89B5,0x89B6,0x89B7,0x89B8,0x89B9,0x89BA,0x89BB,0x89BC,0x89BD,0x89BE,0x89BF, + 0x89C0,0x89C1,0x89C2,0x89C3,0x89C4,0x89C5,0x89C6,0x89C7,0x89C8,0x89C9,0x89CA,0x89CB,0x89CC,0x89CD,0x89CE,0x89CF, + 0x89D0,0x89D1,0x89D2,0x89D3,0x89D4,0x89D5,0x89D6,0x89D7,0x89D8,0x89D9,0x89DA,0x89DB,0x89DC,0x89DD,0x89DE,0x89DF, + 0x89E0,0x89E1,0x89E2,0x89E3,0x89E4,0x89E5,0x89E6,0x89E7,0x89E8,0x89E9,0x89EA,0x89EB,0x89EC,0x89ED,0x89EE,0x89EF, + 0x89F0,0x89F1,0x89F2,0x89F3,0x89F4,0x89F5,0x89F6,0x89F7,0x89F8,0x89F9,0x89FA,0x89FB,0x89FC,0x89FD,0x89FE,0x89FF, + 0x8A00,0x8A01,0x8A02,0x8A03,0x8A04,0x8A05,0x8A06,0x8A07,0x8A08,0x8A09,0x8A0A,0x8A0B,0x8A0C,0x8A0D,0x8A0E,0x8A0F, + 0x8A10,0x8A11,0x8A12,0x8A13,0x8A14,0x8A15,0x8A16,0x8A17,0x8A18,0x8A19,0x8A1A,0x8A1B,0x8A1C,0x8A1D,0x8A1E,0x8A1F, + 0x8A20,0x8A21,0x8A22,0x8A23,0x8A24,0x8A25,0x8A26,0x8A27,0x8A28,0x8A29,0x8A2A,0x8A2B,0x8A2C,0x8A2D,0x8A2E,0x8A2F, + 0x8A30,0x8A31,0x8A32,0x8A33,0x8A34,0x8A35,0x8A36,0x8A37,0x8A38,0x8A39,0x8A3A,0x8A3B,0x8A3C,0x8A3D,0x8A3E,0x8A3F, + 0x8A40,0x8A41,0x8A42,0x8A43,0x8A44,0x8A45,0x8A46,0x8A47,0x8A48,0x8A49,0x8A4A,0x8A4B,0x8A4C,0x8A4D,0x8A4E,0x8A4F, + 0x8A50,0x8A51,0x8A52,0x8A53,0x8A54,0x8A55,0x8A56,0x8A57,0x8A58,0x8A59,0x8A5A,0x8A5B,0x8A5C,0x8A5D,0x8A5E,0x8A5F, + 0x8A60,0x8A61,0x8A62,0x8A63,0x8A64,0x8A65,0x8A66,0x8A67,0x8A68,0x8A69,0x8A6A,0x8A6B,0x8A6C,0x8A6D,0x8A6E,0x8A6F, + 0x8A70,0x8A71,0x8A72,0x8A73,0x8A74,0x8A75,0x8A76,0x8A77,0x8A78,0x8A79,0x8A7A,0x8A7B,0x8A7C,0x8A7D,0x8A7E,0x8A7F, + 0x8A80,0x8A81,0x8A82,0x8A83,0x8A84,0x8A85,0x8A86,0x8A87,0x8A88,0x8A89,0x8A8A,0x8A8B,0x8A8C,0x8A8D,0x8A8E,0x8A8F, + 0x8A90,0x8A91,0x8A92,0x8A93,0x8A94,0x8A95,0x8A96,0x8A97,0x8A98,0x8A99,0x8A9A,0x8A9B,0x8A9C,0x8A9D,0x8A9E,0x8A9F, + 0x8AA0,0x8AA1,0x8AA2,0x8AA3,0x8AA4,0x8AA5,0x8AA6,0x8AA7,0x8AA8,0x8AA9,0x8AAA,0x8AAB,0x8AAC,0x8AAD,0x8AAE,0x8AAF, + 0x8AB0,0x8AB1,0x8AB2,0x8AB3,0x8AB4,0x8AB5,0x8AB6,0x8AB7,0x8AB8,0x8AB9,0x8ABA,0x8ABB,0x8ABC,0x8ABD,0x8ABE,0x8ABF, + 0x8AC0,0x8AC1,0x8AC2,0x8AC3,0x8AC4,0x8AC5,0x8AC6,0x8AC7,0x8AC8,0x8AC9,0x8ACA,0x8ACB,0x8ACC,0x8ACD,0x8ACE,0x8ACF, + 0x8AD0,0x8AD1,0x8AD2,0x8AD3,0x8AD4,0x8AD5,0x8AD6,0x8AD7,0x8AD8,0x8AD9,0x8ADA,0x8ADB,0x8ADC,0x8ADD,0x8ADE,0x8ADF, + 0x8AE0,0x8AE1,0x8AE2,0x8AE3,0x8AE4,0x8AE5,0x8AE6,0x8AE7,0x8AE8,0x8AE9,0x8AEA,0x8AEB,0x8AEC,0x8AED,0x8AEE,0x8AEF, + 0x8AF0,0x8AF1,0x8AF2,0x8AF3,0x8AF4,0x8AF5,0x8AF6,0x8AF7,0x8AF8,0x8AF9,0x8AFA,0x8AFB,0x8AFC,0x8AFD,0x8AFE,0x8AFF, + 0x8B00,0x8B01,0x8B02,0x8B03,0x8B04,0x8B05,0x8B06,0x8B07,0x8B08,0x8B09,0x8B0A,0x8B0B,0x8B0C,0x8B0D,0x8B0E,0x8B0F, + 0x8B10,0x8B11,0x8B12,0x8B13,0x8B14,0x8B15,0x8B16,0x8B17,0x8B18,0x8B19,0x8B1A,0x8B1B,0x8B1C,0x8B1D,0x8B1E,0x8B1F, + 0x8B20,0x8B21,0x8B22,0x8B23,0x8B24,0x8B25,0x8B26,0x8B27,0x8B28,0x8B29,0x8B2A,0x8B2B,0x8B2C,0x8B2D,0x8B2E,0x8B2F, + 0x8B30,0x8B31,0x8B32,0x8B33,0x8B34,0x8B35,0x8B36,0x8B37,0x8B38,0x8B39,0x8B3A,0x8B3B,0x8B3C,0x8B3D,0x8B3E,0x8B3F, + 0x8B40,0x8B41,0x8B42,0x8B43,0x8B44,0x8B45,0x8B46,0x8B47,0x8B48,0x8B49,0x8B4A,0x8B4B,0x8B4C,0x8B4D,0x8B4E,0x8B4F, + 0x8B50,0x8B51,0x8B52,0x8B53,0x8B54,0x8B55,0x8B56,0x8B57,0x8B58,0x8B59,0x8B5A,0x8B5B,0x8B5C,0x8B5D,0x8B5E,0x8B5F, + 0x8B60,0x8B61,0x8B62,0x8B63,0x8B64,0x8B65,0x8B66,0x8B67,0x8B68,0x8B69,0x8B6A,0x8B6B,0x8B6C,0x8B6D,0x8B6E,0x8B6F, + 0x8B70,0x8B71,0x8B72,0x8B73,0x8B74,0x8B75,0x8B76,0x8B77,0x8B78,0x8B79,0x8B7A,0x8B7B,0x8B7C,0x8B7D,0x8B7E,0x8B7F, + 0x8B80,0x8B81,0x8B82,0x8B83,0x8B84,0x8B85,0x8B86,0x8B87,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0x8B8D,0x8B8E,0x8B8F, + 0x8B90,0x8B91,0x8B92,0x8B93,0x8B94,0x8B95,0x8B96,0x8B97,0x8B98,0x8B99,0x8B9A,0x8B9B,0x8B9C,0x8B9D,0x8B9E,0x8B9F, + 0x8BA0,0x8BA1,0x8BA2,0x8BA3,0x8BA4,0x8BA5,0x8BA6,0x8BA7,0x8BA8,0x8BA9,0x8BAA,0x8BAB,0x8BAC,0x8BAD,0x8BAE,0x8BAF, + 0x8BB0,0x8BB1,0x8BB2,0x8BB3,0x8BB4,0x8BB5,0x8BB6,0x8BB7,0x8BB8,0x8BB9,0x8BBA,0x8BBB,0x8BBC,0x8BBD,0x8BBE,0x8BBF, + 0x8BC0,0x8BC1,0x8BC2,0x8BC3,0x8BC4,0x8BC5,0x8BC6,0x8BC7,0x8BC8,0x8BC9,0x8BCA,0x8BCB,0x8BCC,0x8BCD,0x8BCE,0x8BCF, + 0x8BD0,0x8BD1,0x8BD2,0x8BD3,0x8BD4,0x8BD5,0x8BD6,0x8BD7,0x8BD8,0x8BD9,0x8BDA,0x8BDB,0x8BDC,0x8BDD,0x8BDE,0x8BDF, + 0x8BE0,0x8BE1,0x8BE2,0x8BE3,0x8BE4,0x8BE5,0x8BE6,0x8BE7,0x8BE8,0x8BE9,0x8BEA,0x8BEB,0x8BEC,0x8BED,0x8BEE,0x8BEF, + 0x8BF0,0x8BF1,0x8BF2,0x8BF3,0x8BF4,0x8BF5,0x8BF6,0x8BF7,0x8BF8,0x8BF9,0x8BFA,0x8BFB,0x8BFC,0x8BFD,0x8BFE,0x8BFF, + 0x8C00,0x8C01,0x8C02,0x8C03,0x8C04,0x8C05,0x8C06,0x8C07,0x8C08,0x8C09,0x8C0A,0x8C0B,0x8C0C,0x8C0D,0x8C0E,0x8C0F, + 0x8C10,0x8C11,0x8C12,0x8C13,0x8C14,0x8C15,0x8C16,0x8C17,0x8C18,0x8C19,0x8C1A,0x8C1B,0x8C1C,0x8C1D,0x8C1E,0x8C1F, + 0x8C20,0x8C21,0x8C22,0x8C23,0x8C24,0x8C25,0x8C26,0x8C27,0x8C28,0x8C29,0x8C2A,0x8C2B,0x8C2C,0x8C2D,0x8C2E,0x8C2F, + 0x8C30,0x8C31,0x8C32,0x8C33,0x8C34,0x8C35,0x8C36,0x8C37,0x8C38,0x8C39,0x8C3A,0x8C3B,0x8C3C,0x8C3D,0x8C3E,0x8C3F, + 0x8C40,0x8C41,0x8C42,0x8C43,0x8C44,0x8C45,0x8C46,0x8C47,0x8C48,0x8C49,0x8C4A,0x8C4B,0x8C4C,0x8C4D,0x8C4E,0x8C4F, + 0x8C50,0x8C51,0x8C52,0x8C53,0x8C54,0x8C55,0x8C56,0x8C57,0x8C58,0x8C59,0x8C5A,0x8C5B,0x8C5C,0x8C5D,0x8C5E,0x8C5F, + 0x8C60,0x8C61,0x8C62,0x8C63,0x8C64,0x8C65,0x8C66,0x8C67,0x8C68,0x8C69,0x8C6A,0x8C6B,0x8C6C,0x8C6D,0x8C6E,0x8C6F, + 0x8C70,0x8C71,0x8C72,0x8C73,0x8C74,0x8C75,0x8C76,0x8C77,0x8C78,0x8C79,0x8C7A,0x8C7B,0x8C7C,0x8C7D,0x8C7E,0x8C7F, + 0x8C80,0x8C81,0x8C82,0x8C83,0x8C84,0x8C85,0x8C86,0x8C87,0x8C88,0x8C89,0x8C8A,0x8C8B,0x8C8C,0x8C8D,0x8C8E,0x8C8F, + 0x8C90,0x8C91,0x8C92,0x8C93,0x8C94,0x8C95,0x8C96,0x8C97,0x8C98,0x8C99,0x8C9A,0x8C9B,0x8C9C,0x8C9D,0x8C9E,0x8C9F, + 0x8CA0,0x8CA1,0x8CA2,0x8CA3,0x8CA4,0x8CA5,0x8CA6,0x8CA7,0x8CA8,0x8CA9,0x8CAA,0x8CAB,0x8CAC,0x8CAD,0x8CAE,0x8CAF, + 0x8CB0,0x8CB1,0x8CB2,0x8CB3,0x8CB4,0x8CB5,0x8CB6,0x8CB7,0x8CB8,0x8CB9,0x8CBA,0x8CBB,0x8CBC,0x8CBD,0x8CBE,0x8CBF, + 0x8CC0,0x8CC1,0x8CC2,0x8CC3,0x8CC4,0x8CC5,0x8CC6,0x8CC7,0x8CC8,0x8CC9,0x8CCA,0x8CCB,0x8CCC,0x8CCD,0x8CCE,0x8CCF, + 0x8CD0,0x8CD1,0x8CD2,0x8CD3,0x8CD4,0x8CD5,0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,0x8CDB,0x8CDC,0x8CDD,0x8CDE,0x8CDF, + 0x8CE0,0x8CE1,0x8CE2,0x8CE3,0x8CE4,0x8CE5,0x8CE6,0x8CE7,0x8CE8,0x8CE9,0x8CEA,0x8CEB,0x8CEC,0x8CED,0x8CEE,0x8CEF, + 0x8CF0,0x8CF1,0x8CF2,0x8CF3,0x8CF4,0x8CF5,0x8CF6,0x8CF7,0x8CF8,0x8CF9,0x8CFA,0x8CFB,0x8CFC,0x8CFD,0x8CFE,0x8CFF, + 0x8D00,0x8D01,0x8D02,0x8D03,0x8D04,0x8D05,0x8D06,0x8D07,0x8D08,0x8D09,0x8D0A,0x8D0B,0x8D0C,0x8D0D,0x8D0E,0x8D0F, + 0x8D10,0x8D11,0x8D12,0x8D13,0x8D14,0x8D15,0x8D16,0x8D17,0x8D18,0x8D19,0x8D1A,0x8D1B,0x8D1C,0x8D1D,0x8D1E,0x8D1F, + 0x8D20,0x8D21,0x8D22,0x8D23,0x8D24,0x8D25,0x8D26,0x8D27,0x8D28,0x8D29,0x8D2A,0x8D2B,0x8D2C,0x8D2D,0x8D2E,0x8D2F, + 0x8D30,0x8D31,0x8D32,0x8D33,0x8D34,0x8D35,0x8D36,0x8D37,0x8D38,0x8D39,0x8D3A,0x8D3B,0x8D3C,0x8D3D,0x8D3E,0x8D3F, + 0x8D40,0x8D41,0x8D42,0x8D43,0x8D44,0x8D45,0x8D46,0x8D47,0x8D48,0x8D49,0x8D4A,0x8D4B,0x8D4C,0x8D4D,0x8D4E,0x8D4F, + 0x8D50,0x8D51,0x8D52,0x8D53,0x8D54,0x8D55,0x8D56,0x8D57,0x8D58,0x8D59,0x8D5A,0x8D5B,0x8D5C,0x8D5D,0x8D5E,0x8D5F, + 0x8D60,0x8D61,0x8D62,0x8D63,0x8D64,0x8D65,0x8D66,0x8D67,0x8D68,0x8D69,0x8D6A,0x8D6B,0x8D6C,0x8D6D,0x8D6E,0x8D6F, + 0x8D70,0x8D71,0x8D72,0x8D73,0x8D74,0x8D75,0x8D76,0x8D77,0x8D78,0x8D79,0x8D7A,0x8D7B,0x8D7C,0x8D7D,0x8D7E,0x8D7F, + 0x8D80,0x8D81,0x8D82,0x8D83,0x8D84,0x8D85,0x8D86,0x8D87,0x8D88,0x8D89,0x8D8A,0x8D8B,0x8D8C,0x8D8D,0x8D8E,0x8D8F, + 0x8D90,0x8D91,0x8D92,0x8D93,0x8D94,0x8D95,0x8D96,0x8D97,0x8D98,0x8D99,0x8D9A,0x8D9B,0x8D9C,0x8D9D,0x8D9E,0x8D9F, + 0x8DA0,0x8DA1,0x8DA2,0x8DA3,0x8DA4,0x8DA5,0x8DA6,0x8DA7,0x8DA8,0x8DA9,0x8DAA,0x8DAB,0x8DAC,0x8DAD,0x8DAE,0x8DAF, + 0x8DB0,0x8DB1,0x8DB2,0x8DB3,0x8DB4,0x8DB5,0x8DB6,0x8DB7,0x8DB8,0x8DB9,0x8DBA,0x8DBB,0x8DBC,0x8DBD,0x8DBE,0x8DBF, + 0x8DC0,0x8DC1,0x8DC2,0x8DC3,0x8DC4,0x8DC5,0x8DC6,0x8DC7,0x8DC8,0x8DC9,0x8DCA,0x8DCB,0x8DCC,0x8DCD,0x8DCE,0x8DCF, + 0x8DD0,0x8DD1,0x8DD2,0x8DD3,0x8DD4,0x8DD5,0x8DD6,0x8DD7,0x8DD8,0x8DD9,0x8DDA,0x8DDB,0x8DDC,0x8DDD,0x8DDE,0x8DDF, + 0x8DE0,0x8DE1,0x8DE2,0x8DE3,0x8DE4,0x8DE5,0x8DE6,0x8DE7,0x8DE8,0x8DE9,0x8DEA,0x8DEB,0x8DEC,0x8DED,0x8DEE,0x8DEF, + 0x8DF0,0x8DF1,0x8DF2,0x8DF3,0x8DF4,0x8DF5,0x8DF6,0x8DF7,0x8DF8,0x8DF9,0x8DFA,0x8DFB,0x8DFC,0x8DFD,0x8DFE,0x8DFF, + 0x8E00,0x8E01,0x8E02,0x8E03,0x8E04,0x8E05,0x8E06,0x8E07,0x8E08,0x8E09,0x8E0A,0x8E0B,0x8E0C,0x8E0D,0x8E0E,0x8E0F, + 0x8E10,0x8E11,0x8E12,0x8E13,0x8E14,0x8E15,0x8E16,0x8E17,0x8E18,0x8E19,0x8E1A,0x8E1B,0x8E1C,0x8E1D,0x8E1E,0x8E1F, + 0x8E20,0x8E21,0x8E22,0x8E23,0x8E24,0x8E25,0x8E26,0x8E27,0x8E28,0x8E29,0x8E2A,0x8E2B,0x8E2C,0x8E2D,0x8E2E,0x8E2F, + 0x8E30,0x8E31,0x8E32,0x8E33,0x8E34,0x8E35,0x8E36,0x8E37,0x8E38,0x8E39,0x8E3A,0x8E3B,0x8E3C,0x8E3D,0x8E3E,0x8E3F, + 0x8E40,0x8E41,0x8E42,0x8E43,0x8E44,0x8E45,0x8E46,0x8E47,0x8E48,0x8E49,0x8E4A,0x8E4B,0x8E4C,0x8E4D,0x8E4E,0x8E4F, + 0x8E50,0x8E51,0x8E52,0x8E53,0x8E54,0x8E55,0x8E56,0x8E57,0x8E58,0x8E59,0x8E5A,0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E5F, + 0x8E60,0x8E61,0x8E62,0x8E63,0x8E64,0x8E65,0x8E66,0x8E67,0x8E68,0x8E69,0x8E6A,0x8E6B,0x8E6C,0x8E6D,0x8E6E,0x8E6F, + 0x8E70,0x8E71,0x8E72,0x8E73,0x8E74,0x8E75,0x8E76,0x8E77,0x8E78,0x8E79,0x8E7A,0x8E7B,0x8E7C,0x8E7D,0x8E7E,0x8E7F, + 0x8E80,0x8E81,0x8E82,0x8E83,0x8E84,0x8E85,0x8E86,0x8E87,0x8E88,0x8E89,0x8E8A,0x8E8B,0x8E8C,0x8E8D,0x8E8E,0x8E8F, + 0x8E90,0x8E91,0x8E92,0x8E93,0x8E94,0x8E95,0x8E96,0x8E97,0x8E98,0x8E99,0x8E9A,0x8E9B,0x8E9C,0x8E9D,0x8E9E,0x8E9F, + 0x8EA0,0x8EA1,0x8EA2,0x8EA3,0x8EA4,0x8EA5,0x8EA6,0x8EA7,0x8EA8,0x8EA9,0x8EAA,0x8EAB,0x8EAC,0x8EAD,0x8EAE,0x8EAF, + 0x8EB0,0x8EB1,0x8EB2,0x8EB3,0x8EB4,0x8EB5,0x8EB6,0x8EB7,0x8EB8,0x8EB9,0x8EBA,0x8EBB,0x8EBC,0x8EBD,0x8EBE,0x8EBF, + 0x8EC0,0x8EC1,0x8EC2,0x8EC3,0x8EC4,0x8EC5,0x8EC6,0x8EC7,0x8EC8,0x8EC9,0x8ECA,0x8ECB,0x8ECC,0x8ECD,0x8ECE,0x8ECF, + 0x8ED0,0x8ED1,0x8ED2,0x8ED3,0x8ED4,0x8ED5,0x8ED6,0x8ED7,0x8ED8,0x8ED9,0x8EDA,0x8EDB,0x8EDC,0x8EDD,0x8EDE,0x8EDF, + 0x8EE0,0x8EE1,0x8EE2,0x8EE3,0x8EE4,0x8EE5,0x8EE6,0x8EE7,0x8EE8,0x8EE9,0x8EEA,0x8EEB,0x8EEC,0x8EED,0x8EEE,0x8EEF, + 0x8EF0,0x8EF1,0x8EF2,0x8EF3,0x8EF4,0x8EF5,0x8EF6,0x8EF7,0x8EF8,0x8EF9,0x8EFA,0x8EFB,0x8EFC,0x8EFD,0x8EFE,0x8EFF, + 0x8F00,0x8F01,0x8F02,0x8F03,0x8F04,0x8F05,0x8F06,0x8F07,0x8F08,0x8F09,0x8F0A,0x8F0B,0x8F0C,0x8F0D,0x8F0E,0x8F0F, + 0x8F10,0x8F11,0x8F12,0x8F13,0x8F14,0x8F15,0x8F16,0x8F17,0x8F18,0x8F19,0x8F1A,0x8F1B,0x8F1C,0x8F1D,0x8F1E,0x8F1F, + 0x8F20,0x8F21,0x8F22,0x8F23,0x8F24,0x8F25,0x8F26,0x8F27,0x8F28,0x8F29,0x8F2A,0x8F2B,0x8F2C,0x8F2D,0x8F2E,0x8F2F, + 0x8F30,0x8F31,0x8F32,0x8F33,0x8F34,0x8F35,0x8F36,0x8F37,0x8F38,0x8F39,0x8F3A,0x8F3B,0x8F3C,0x8F3D,0x8F3E,0x8F3F, + 0x8F40,0x8F41,0x8F42,0x8F43,0x8F44,0x8F45,0x8F46,0x8F47,0x8F48,0x8F49,0x8F4A,0x8F4B,0x8F4C,0x8F4D,0x8F4E,0x8F4F, + 0x8F50,0x8F51,0x8F52,0x8F53,0x8F54,0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A,0x8F5B,0x8F5C,0x8F5D,0x8F5E,0x8F5F, + 0x8F60,0x8F61,0x8F62,0x8F63,0x8F64,0x8F65,0x8F66,0x8F67,0x8F68,0x8F69,0x8F6A,0x8F6B,0x8F6C,0x8F6D,0x8F6E,0x8F6F, + 0x8F70,0x8F71,0x8F72,0x8F73,0x8F74,0x8F75,0x8F76,0x8F77,0x8F78,0x8F79,0x8F7A,0x8F7B,0x8F7C,0x8F7D,0x8F7E,0x8F7F, + 0x8F80,0x8F81,0x8F82,0x8F83,0x8F84,0x8F85,0x8F86,0x8F87,0x8F88,0x8F89,0x8F8A,0x8F8B,0x8F8C,0x8F8D,0x8F8E,0x8F8F, + 0x8F90,0x8F91,0x8F92,0x8F93,0x8F94,0x8F95,0x8F96,0x8F97,0x8F98,0x8F99,0x8F9A,0x8F9B,0x8F9C,0x8F9D,0x8F9E,0x8F9F, + 0x8FA0,0x8FA1,0x8FA2,0x8FA3,0x8FA4,0x8FA5,0x8FA6,0x8FA7,0x8FA8,0x8FA9,0x8FAA,0x8FAB,0x8FAC,0x8FAD,0x8FAE,0x8FAF, + 0x8FB0,0x8FB1,0x8FB2,0x8FB3,0x8FB4,0x8FB5,0x8FB6,0x8FB7,0x8FB8,0x8FB9,0x8FBA,0x8FBB,0x8FBC,0x8FBD,0x8FBE,0x8FBF, + 0x8FC0,0x8FC1,0x8FC2,0x8FC3,0x8FC4,0x8FC5,0x8FC6,0x8FC7,0x8FC8,0x8FC9,0x8FCA,0x8FCB,0x8FCC,0x8FCD,0x8FCE,0x8FCF, + 0x8FD0,0x8FD1,0x8FD2,0x8FD3,0x8FD4,0x8FD5,0x8FD6,0x8FD7,0x8FD8,0x8FD9,0x8FDA,0x8FDB,0x8FDC,0x8FDD,0x8FDE,0x8FDF, + 0x8FE0,0x8FE1,0x8FE2,0x8FE3,0x8FE4,0x8FE5,0x8FE6,0x8FE7,0x8FE8,0x8FE9,0x8FEA,0x8FEB,0x8FEC,0x8FED,0x8FEE,0x8FEF, + 0x8FF0,0x8FF1,0x8FF2,0x8FF3,0x8FF4,0x8FF5,0x8FF6,0x8FF7,0x8FF8,0x8FF9,0x8FFA,0x8FFB,0x8FFC,0x8FFD,0x8FFE,0x8FFF, + 0x9000,0x9001,0x9002,0x9003,0x9004,0x9005,0x9006,0x9007,0x9008,0x9009,0x900A,0x900B,0x900C,0x900D,0x900E,0x900F, + 0x9010,0x9011,0x9012,0x9013,0x9014,0x9015,0x9016,0x9017,0x9018,0x9019,0x901A,0x901B,0x901C,0x901D,0x901E,0x901F, + 0x9020,0x9021,0x9022,0x9023,0x9024,0x9025,0x9026,0x9027,0x9028,0x9029,0x902A,0x902B,0x902C,0x902D,0x902E,0x902F, + 0x9030,0x9031,0x9032,0x9033,0x9034,0x9035,0x9036,0x9037,0x9038,0x9039,0x903A,0x903B,0x903C,0x903D,0x903E,0x903F, + 0x9040,0x9041,0x9042,0x9043,0x9044,0x9045,0x9046,0x9047,0x9048,0x9049,0x904A,0x904B,0x904C,0x904D,0x904E,0x904F, + 0x9050,0x9051,0x9052,0x9053,0x9054,0x9055,0x9056,0x9057,0x9058,0x9059,0x905A,0x905B,0x905C,0x905D,0x905E,0x905F, + 0x9060,0x9061,0x9062,0x9063,0x9064,0x9065,0x9066,0x9067,0x9068,0x9069,0x906A,0x906B,0x906C,0x906D,0x906E,0x906F, + 0x9070,0x9071,0x9072,0x9073,0x9074,0x9075,0x9076,0x9077,0x9078,0x9079,0x907A,0x907B,0x907C,0x907D,0x907E,0x907F, + 0x9080,0x9081,0x9082,0x9083,0x9084,0x9085,0x9086,0x9087,0x9088,0x9089,0x908A,0x908B,0x908C,0x908D,0x908E,0x908F, + 0x9090,0x9091,0x9092,0x9093,0x9094,0x9095,0x9096,0x9097,0x9098,0x9099,0x909A,0x909B,0x909C,0x909D,0x909E,0x909F, + 0x90A0,0x90A1,0x90A2,0x90A3,0x90A4,0x90A5,0x90A6,0x90A7,0x90A8,0x90A9,0x90AA,0x90AB,0x90AC,0x90AD,0x90AE,0x90AF, + 0x90B0,0x90B1,0x90B2,0x90B3,0x90B4,0x90B5,0x90B6,0x90B7,0x90B8,0x90B9,0x90BA,0x90BB,0x90BC,0x90BD,0x90BE,0x90BF, + 0x90C0,0x90C1,0x90C2,0x90C3,0x90C4,0x90C5,0x90C6,0x90C7,0x90C8,0x90C9,0x90CA,0x90CB,0x90CC,0x90CD,0x90CE,0x90CF, + 0x90D0,0x90D1,0x90D2,0x90D3,0x90D4,0x90D5,0x90D6,0x90D7,0x90D8,0x90D9,0x90DA,0x90DB,0x90DC,0x90DD,0x90DE,0x90DF, + 0x90E0,0x90E1,0x90E2,0x90E3,0x90E4,0x90E5,0x90E6,0x90E7,0x90E8,0x90E9,0x90EA,0x90EB,0x90EC,0x90ED,0x90EE,0x90EF, + 0x90F0,0x90F1,0x90F2,0x90F3,0x90F4,0x90F5,0x90F6,0x90F7,0x90F8,0x90F9,0x90FA,0x90FB,0x90FC,0x90FD,0x90FE,0x90FF, + 0x9100,0x9101,0x9102,0x9103,0x9104,0x9105,0x9106,0x9107,0x9108,0x9109,0x910A,0x910B,0x910C,0x910D,0x910E,0x910F, + 0x9110,0x9111,0x9112,0x9113,0x9114,0x9115,0x9116,0x9117,0x9118,0x9119,0x911A,0x911B,0x911C,0x911D,0x911E,0x911F, + 0x9120,0x9121,0x9122,0x9123,0x9124,0x9125,0x9126,0x9127,0x9128,0x9129,0x912A,0x912B,0x912C,0x912D,0x912E,0x912F, + 0x9130,0x9131,0x9132,0x9133,0x9134,0x9135,0x9136,0x9137,0x9138,0x9139,0x913A,0x913B,0x913C,0x913D,0x913E,0x913F, + 0x9140,0x9141,0x9142,0x9143,0x9144,0x9145,0x9146,0x9147,0x9148,0x9149,0x914A,0x914B,0x914C,0x914D,0x914E,0x914F, + 0x9150,0x9151,0x9152,0x9153,0x9154,0x9155,0x9156,0x9157,0x9158,0x9159,0x915A,0x915B,0x915C,0x915D,0x915E,0x915F, + 0x9160,0x9161,0x9162,0x9163,0x9164,0x9165,0x9166,0x9167,0x9168,0x9169,0x916A,0x916B,0x916C,0x916D,0x916E,0x916F, + 0x9170,0x9171,0x9172,0x9173,0x9174,0x9175,0x9176,0x9177,0x9178,0x9179,0x917A,0x917B,0x917C,0x917D,0x917E,0x917F, + 0x9180,0x9181,0x9182,0x9183,0x9184,0x9185,0x9186,0x9187,0x9188,0x9189,0x918A,0x918B,0x918C,0x918D,0x918E,0x918F, + 0x9190,0x9191,0x9192,0x9193,0x9194,0x9195,0x9196,0x9197,0x9198,0x9199,0x919A,0x919B,0x919C,0x919D,0x919E,0x919F, + 0x91A0,0x91A1,0x91A2,0x91A3,0x91A4,0x91A5,0x91A6,0x91A7,0x91A8,0x91A9,0x91AA,0x91AB,0x91AC,0x91AD,0x91AE,0x91AF, + 0x91B0,0x91B1,0x91B2,0x91B3,0x91B4,0x91B5,0x91B6,0x91B7,0x91B8,0x91B9,0x91BA,0x91BB,0x91BC,0x91BD,0x91BE,0x91BF, + 0x91C0,0x91C1,0x91C2,0x91C3,0x91C4,0x91C5,0x91C6,0x91C7,0x91C8,0x91C9,0x91CA,0x91CB,0x91CC,0x91CD,0x91CE,0x91CF, + 0x91D0,0x91D1,0x91D2,0x91D3,0x91D4,0x91D5,0x91D6,0x91D7,0x91D8,0x91D9,0x91DA,0x91DB,0x91DC,0x91DD,0x91DE,0x91DF, + 0x91E0,0x91E1,0x91E2,0x91E3,0x91E4,0x91E5,0x91E6,0x91E7,0x91E8,0x91E9,0x91EA,0x91EB,0x91EC,0x91ED,0x91EE,0x91EF, + 0x91F0,0x91F1,0x91F2,0x91F3,0x91F4,0x91F5,0x91F6,0x91F7,0x91F8,0x91F9,0x91FA,0x91FB,0x91FC,0x91FD,0x91FE,0x91FF, + 0x9200,0x9201,0x9202,0x9203,0x9204,0x9205,0x9206,0x9207,0x9208,0x9209,0x920A,0x920B,0x920C,0x920D,0x920E,0x920F, + 0x9210,0x9211,0x9212,0x9213,0x9214,0x9215,0x9216,0x9217,0x9218,0x9219,0x921A,0x921B,0x921C,0x921D,0x921E,0x921F, + 0x9220,0x9221,0x9222,0x9223,0x9224,0x9225,0x9226,0x9227,0x9228,0x9229,0x922A,0x922B,0x922C,0x922D,0x922E,0x922F, + 0x9230,0x9231,0x9232,0x9233,0x9234,0x9235,0x9236,0x9237,0x9238,0x9239,0x923A,0x923B,0x923C,0x923D,0x923E,0x923F, + 0x9240,0x9241,0x9242,0x9243,0x9244,0x9245,0x9246,0x9247,0x9248,0x9249,0x924A,0x924B,0x924C,0x924D,0x924E,0x924F, + 0x9250,0x9251,0x9252,0x9253,0x9254,0x9255,0x9256,0x9257,0x9258,0x9259,0x925A,0x925B,0x925C,0x925D,0x925E,0x925F, + 0x9260,0x9261,0x9262,0x9263,0x9264,0x9265,0x9266,0x9267,0x9268,0x9269,0x926A,0x926B,0x926C,0x926D,0x926E,0x926F, + 0x9270,0x9271,0x9272,0x9273,0x9274,0x9275,0x9276,0x9277,0x9278,0x9279,0x927A,0x927B,0x927C,0x927D,0x927E,0x927F, + 0x9280,0x9281,0x9282,0x9283,0x9284,0x9285,0x9286,0x9287,0x9288,0x9289,0x928A,0x928B,0x928C,0x928D,0x928E,0x928F, + 0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296,0x9297,0x9298,0x9299,0x929A,0x929B,0x929C,0x929D,0x929E,0x929F, + 0x92A0,0x92A1,0x92A2,0x92A3,0x92A4,0x92A5,0x92A6,0x92A7,0x92A8,0x92A9,0x92AA,0x92AB,0x92AC,0x92AD,0x92AE,0x92AF, + 0x92B0,0x92B1,0x92B2,0x92B3,0x92B4,0x92B5,0x92B6,0x92B7,0x92B8,0x92B9,0x92BA,0x92BB,0x92BC,0x92BD,0x92BE,0x92BF, + 0x92C0,0x92C1,0x92C2,0x92C3,0x92C4,0x92C5,0x92C6,0x92C7,0x92C8,0x92C9,0x92CA,0x92CB,0x92CC,0x92CD,0x92CE,0x92CF, + 0x92D0,0x92D1,0x92D2,0x92D3,0x92D4,0x92D5,0x92D6,0x92D7,0x92D8,0x92D9,0x92DA,0x92DB,0x92DC,0x92DD,0x92DE,0x92DF, + 0x92E0,0x92E1,0x92E2,0x92E3,0x92E4,0x92E5,0x92E6,0x92E7,0x92E8,0x92E9,0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF, + 0x92F0,0x92F1,0x92F2,0x92F3,0x92F4,0x92F5,0x92F6,0x92F7,0x92F8,0x92F9,0x92FA,0x92FB,0x92FC,0x92FD,0x92FE,0x92FF, + 0x9300,0x9301,0x9302,0x9303,0x9304,0x9305,0x9306,0x9307,0x9308,0x9309,0x930A,0x930B,0x930C,0x930D,0x930E,0x930F, + 0x9310,0x9311,0x9312,0x9313,0x9314,0x9315,0x9316,0x9317,0x9318,0x9319,0x931A,0x931B,0x931C,0x931D,0x931E,0x931F, + 0x9320,0x9321,0x9322,0x9323,0x9324,0x9325,0x9326,0x9327,0x9328,0x9329,0x932A,0x932B,0x932C,0x932D,0x932E,0x932F, + 0x9330,0x9331,0x9332,0x9333,0x9334,0x9335,0x9336,0x9337,0x9338,0x9339,0x933A,0x933B,0x933C,0x933D,0x933E,0x933F, + 0x9340,0x9341,0x9342,0x9343,0x9344,0x9345,0x9346,0x9347,0x9348,0x9349,0x934A,0x934B,0x934C,0x934D,0x934E,0x934F, + 0x9350,0x9351,0x9352,0x9353,0x9354,0x9355,0x9356,0x9357,0x9358,0x9359,0x935A,0x935B,0x935C,0x935D,0x935E,0x935F, + 0x9360,0x9361,0x9362,0x9363,0x9364,0x9365,0x9366,0x9367,0x9368,0x9369,0x936A,0x936B,0x936C,0x936D,0x936E,0x936F, + 0x9370,0x9371,0x9372,0x9373,0x9374,0x9375,0x9376,0x9377,0x9378,0x9379,0x937A,0x937B,0x937C,0x937D,0x937E,0x937F, + 0x9380,0x9381,0x9382,0x9383,0x9384,0x9385,0x9386,0x9387,0x9388,0x9389,0x938A,0x938B,0x938C,0x938D,0x938E,0x938F, + 0x9390,0x9391,0x9392,0x9393,0x9394,0x9395,0x9396,0x9397,0x9398,0x9399,0x939A,0x939B,0x939C,0x939D,0x939E,0x939F, + 0x93A0,0x93A1,0x93A2,0x93A3,0x93A4,0x93A5,0x93A6,0x93A7,0x93A8,0x93A9,0x93AA,0x93AB,0x93AC,0x93AD,0x93AE,0x93AF, + 0x93B0,0x93B1,0x93B2,0x93B3,0x93B4,0x93B5,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,0x93BB,0x93BC,0x93BD,0x93BE,0x93BF, + 0x93C0,0x93C1,0x93C2,0x93C3,0x93C4,0x93C5,0x93C6,0x93C7,0x93C8,0x93C9,0x93CA,0x93CB,0x93CC,0x93CD,0x93CE,0x93CF, + 0x93D0,0x93D1,0x93D2,0x93D3,0x93D4,0x93D5,0x93D6,0x93D7,0x93D8,0x93D9,0x93DA,0x93DB,0x93DC,0x93DD,0x93DE,0x93DF, + 0x93E0,0x93E1,0x93E2,0x93E3,0x93E4,0x93E5,0x93E6,0x93E7,0x93E8,0x93E9,0x93EA,0x93EB,0x93EC,0x93ED,0x93EE,0x93EF, + 0x93F0,0x93F1,0x93F2,0x93F3,0x93F4,0x93F5,0x93F6,0x93F7,0x93F8,0x93F9,0x93FA,0x93FB,0x93FC,0x93FD,0x93FE,0x93FF, + 0x9400,0x9401,0x9402,0x9403,0x9404,0x9405,0x9406,0x9407,0x9408,0x9409,0x940A,0x940B,0x940C,0x940D,0x940E,0x940F, + 0x9410,0x9411,0x9412,0x9413,0x9414,0x9415,0x9416,0x9417,0x9418,0x9419,0x941A,0x941B,0x941C,0x941D,0x941E,0x941F, + 0x9420,0x9421,0x9422,0x9423,0x9424,0x9425,0x9426,0x9427,0x9428,0x9429,0x942A,0x942B,0x942C,0x942D,0x942E,0x942F, + 0x9430,0x9431,0x9432,0x9433,0x9434,0x9435,0x9436,0x9437,0x9438,0x9439,0x943A,0x943B,0x943C,0x943D,0x943E,0x943F, + 0x9440,0x9441,0x9442,0x9443,0x9444,0x9445,0x9446,0x9447,0x9448,0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,0x944F, + 0x9450,0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457,0x9458,0x9459,0x945A,0x945B,0x945C,0x945D,0x945E,0x945F, + 0x9460,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467,0x9468,0x9469,0x946A,0x946B,0x946C,0x946D,0x946E,0x946F, + 0x9470,0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477,0x9478,0x9479,0x947A,0x947B,0x947C,0x947D,0x947E,0x947F, + 0x9480,0x9481,0x9482,0x9483,0x9484,0x9485,0x9486,0x9487,0x9488,0x9489,0x948A,0x948B,0x948C,0x948D,0x948E,0x948F, + 0x9490,0x9491,0x9492,0x9493,0x9494,0x9495,0x9496,0x9497,0x9498,0x9499,0x949A,0x949B,0x949C,0x949D,0x949E,0x949F, + 0x94A0,0x94A1,0x94A2,0x94A3,0x94A4,0x94A5,0x94A6,0x94A7,0x94A8,0x94A9,0x94AA,0x94AB,0x94AC,0x94AD,0x94AE,0x94AF, + 0x94B0,0x94B1,0x94B2,0x94B3,0x94B4,0x94B5,0x94B6,0x94B7,0x94B8,0x94B9,0x94BA,0x94BB,0x94BC,0x94BD,0x94BE,0x94BF, + 0x94C0,0x94C1,0x94C2,0x94C3,0x94C4,0x94C5,0x94C6,0x94C7,0x94C8,0x94C9,0x94CA,0x94CB,0x94CC,0x94CD,0x94CE,0x94CF, + 0x94D0,0x94D1,0x94D2,0x94D3,0x94D4,0x94D5,0x94D6,0x94D7,0x94D8,0x94D9,0x94DA,0x94DB,0x94DC,0x94DD,0x94DE,0x94DF, + 0x94E0,0x94E1,0x94E2,0x94E3,0x94E4,0x94E5,0x94E6,0x94E7,0x94E8,0x94E9,0x94EA,0x94EB,0x94EC,0x94ED,0x94EE,0x94EF, + 0x94F0,0x94F1,0x94F2,0x94F3,0x94F4,0x94F5,0x94F6,0x94F7,0x94F8,0x94F9,0x94FA,0x94FB,0x94FC,0x94FD,0x94FE,0x94FF, + 0x9500,0x9501,0x9502,0x9503,0x9504,0x9505,0x9506,0x9507,0x9508,0x9509,0x950A,0x950B,0x950C,0x950D,0x950E,0x950F, + 0x9510,0x9511,0x9512,0x9513,0x9514,0x9515,0x9516,0x9517,0x9518,0x9519,0x951A,0x951B,0x951C,0x951D,0x951E,0x951F, + 0x9520,0x9521,0x9522,0x9523,0x9524,0x9525,0x9526,0x9527,0x9528,0x9529,0x952A,0x952B,0x952C,0x952D,0x952E,0x952F, + 0x9530,0x9531,0x9532,0x9533,0x9534,0x9535,0x9536,0x9537,0x9538,0x9539,0x953A,0x953B,0x953C,0x953D,0x953E,0x953F, + 0x9540,0x9541,0x9542,0x9543,0x9544,0x9545,0x9546,0x9547,0x9548,0x9549,0x954A,0x954B,0x954C,0x954D,0x954E,0x954F, + 0x9550,0x9551,0x9552,0x9553,0x9554,0x9555,0x9556,0x9557,0x9558,0x9559,0x955A,0x955B,0x955C,0x955D,0x955E,0x955F, + 0x9560,0x9561,0x9562,0x9563,0x9564,0x9565,0x9566,0x9567,0x9568,0x9569,0x956A,0x956B,0x956C,0x956D,0x956E,0x956F, + 0x9570,0x9571,0x9572,0x9573,0x9574,0x9575,0x9576,0x9577,0x9578,0x9579,0x957A,0x957B,0x957C,0x957D,0x957E,0x957F, + 0x9580,0x9581,0x9582,0x9583,0x9584,0x9585,0x9586,0x9587,0x9588,0x9589,0x958A,0x958B,0x958C,0x958D,0x958E,0x958F, + 0x9590,0x9591,0x9592,0x9593,0x9594,0x9595,0x9596,0x9597,0x9598,0x9599,0x959A,0x959B,0x959C,0x959D,0x959E,0x959F, + 0x95A0,0x95A1,0x95A2,0x95A3,0x95A4,0x95A5,0x95A6,0x95A7,0x95A8,0x95A9,0x95AA,0x95AB,0x95AC,0x95AD,0x95AE,0x95AF, + 0x95B0,0x95B1,0x95B2,0x95B3,0x95B4,0x95B5,0x95B6,0x95B7,0x95B8,0x95B9,0x95BA,0x95BB,0x95BC,0x95BD,0x95BE,0x95BF, + 0x95C0,0x95C1,0x95C2,0x95C3,0x95C4,0x95C5,0x95C6,0x95C7,0x95C8,0x95C9,0x95CA,0x95CB,0x95CC,0x95CD,0x95CE,0x95CF, + 0x95D0,0x95D1,0x95D2,0x95D3,0x95D4,0x95D5,0x95D6,0x95D7,0x95D8,0x95D9,0x95DA,0x95DB,0x95DC,0x95DD,0x95DE,0x95DF, + 0x95E0,0x95E1,0x95E2,0x95E3,0x95E4,0x95E5,0x95E6,0x95E7,0x95E8,0x95E9,0x95EA,0x95EB,0x95EC,0x95ED,0x95EE,0x95EF, + 0x95F0,0x95F1,0x95F2,0x95F3,0x95F4,0x95F5,0x95F6,0x95F7,0x95F8,0x95F9,0x95FA,0x95FB,0x95FC,0x95FD,0x95FE,0x95FF, + 0x9600,0x9601,0x9602,0x9603,0x9604,0x9605,0x9606,0x9607,0x9608,0x9609,0x960A,0x960B,0x960C,0x960D,0x960E,0x960F, + 0x9610,0x9611,0x9612,0x9613,0x9614,0x9615,0x9616,0x9617,0x9618,0x9619,0x961A,0x961B,0x961C,0x961D,0x961E,0x961F, + 0x9620,0x9621,0x9622,0x9623,0x9624,0x9625,0x9626,0x9627,0x9628,0x9629,0x962A,0x962B,0x962C,0x962D,0x962E,0x962F, + 0x9630,0x9631,0x9632,0x9633,0x9634,0x9635,0x9636,0x9637,0x9638,0x9639,0x963A,0x963B,0x963C,0x963D,0x963E,0x963F, + 0x9640,0x9641,0x9642,0x9643,0x9644,0x9645,0x9646,0x9647,0x9648,0x9649,0x964A,0x964B,0x964C,0x964D,0x964E,0x964F, + 0x9650,0x9651,0x9652,0x9653,0x9654,0x9655,0x9656,0x9657,0x9658,0x9659,0x965A,0x965B,0x965C,0x965D,0x965E,0x965F, + 0x9660,0x9661,0x9662,0x9663,0x9664,0x9665,0x9666,0x9667,0x9668,0x9669,0x966A,0x966B,0x966C,0x966D,0x966E,0x966F, + 0x9670,0x9671,0x9672,0x9673,0x9674,0x9675,0x9676,0x9677,0x9678,0x9679,0x967A,0x967B,0x967C,0x967D,0x967E,0x967F, + 0x9680,0x9681,0x9682,0x9683,0x9684,0x9685,0x9686,0x9687,0x9688,0x9689,0x968A,0x968B,0x968C,0x968D,0x968E,0x968F, + 0x9690,0x9691,0x9692,0x9693,0x9694,0x9695,0x9696,0x9697,0x9698,0x9699,0x969A,0x969B,0x969C,0x969D,0x969E,0x969F, + 0x96A0,0x96A1,0x96A2,0x96A3,0x96A4,0x96A5,0x96A6,0x96A7,0x96A8,0x96A9,0x96AA,0x96AB,0x96AC,0x96AD,0x96AE,0x96AF, + 0x96B0,0x96B1,0x96B2,0x96B3,0x96B4,0x96B5,0x96B6,0x96B7,0x96B8,0x96B9,0x96BA,0x96BB,0x96BC,0x96BD,0x96BE,0x96BF, + 0x96C0,0x96C1,0x96C2,0x96C3,0x96C4,0x96C5,0x96C6,0x96C7,0x96C8,0x96C9,0x96CA,0x96CB,0x96CC,0x96CD,0x96CE,0x96CF, + 0x96D0,0x96D1,0x96D2,0x96D3,0x96D4,0x96D5,0x96D6,0x96D7,0x96D8,0x96D9,0x96DA,0x96DB,0x96DC,0x96DD,0x96DE,0x96DF, + 0x96E0,0x96E1,0x96E2,0x96E3,0x96E4,0x96E5,0x96E6,0x96E7,0x96E8,0x96E9,0x96EA,0x96EB,0x96EC,0x96ED,0x96EE,0x96EF, + 0x96F0,0x96F1,0x96F2,0x96F3,0x96F4,0x96F5,0x96F6,0x96F7,0x96F8,0x96F9,0x96FA,0x96FB,0x96FC,0x96FD,0x96FE,0x96FF, + 0x9700,0x9701,0x9702,0x9703,0x9704,0x9705,0x9706,0x9707,0x9708,0x9709,0x970A,0x970B,0x970C,0x970D,0x970E,0x970F, + 0x9710,0x9711,0x9712,0x9713,0x9714,0x9715,0x9716,0x9717,0x9718,0x9719,0x971A,0x971B,0x971C,0x971D,0x971E,0x971F, + 0x9720,0x9721,0x9722,0x9723,0x9724,0x9725,0x9726,0x9727,0x9728,0x9729,0x972A,0x972B,0x972C,0x972D,0x972E,0x972F, + 0x9730,0x9731,0x9732,0x9733,0x9734,0x9735,0x9736,0x9737,0x9738,0x9739,0x973A,0x973B,0x973C,0x973D,0x973E,0x973F, + 0x9740,0x9741,0x9742,0x9743,0x9744,0x9745,0x9746,0x9747,0x9748,0x9749,0x974A,0x974B,0x974C,0x974D,0x974E,0x974F, + 0x9750,0x9751,0x9752,0x9753,0x9754,0x9755,0x9756,0x9757,0x9758,0x9759,0x975A,0x975B,0x975C,0x975D,0x975E,0x975F, + 0x9760,0x9761,0x9762,0x9763,0x9764,0x9765,0x9766,0x9767,0x9768,0x9769,0x976A,0x976B,0x976C,0x976D,0x976E,0x976F, + 0x9770,0x9771,0x9772,0x9773,0x9774,0x9775,0x9776,0x9777,0x9778,0x9779,0x977A,0x977B,0x977C,0x977D,0x977E,0x977F, + 0x9780,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786,0x9787,0x9788,0x9789,0x978A,0x978B,0x978C,0x978D,0x978E,0x978F, + 0x9790,0x9791,0x9792,0x9793,0x9794,0x9795,0x9796,0x9797,0x9798,0x9799,0x979A,0x979B,0x979C,0x979D,0x979E,0x979F, + 0x97A0,0x97A1,0x97A2,0x97A3,0x97A4,0x97A5,0x97A6,0x97A7,0x97A8,0x97A9,0x97AA,0x97AB,0x97AC,0x97AD,0x97AE,0x97AF, + 0x97B0,0x97B1,0x97B2,0x97B3,0x97B4,0x97B5,0x97B6,0x97B7,0x97B8,0x97B9,0x97BA,0x97BB,0x97BC,0x97BD,0x97BE,0x97BF, + 0x97C0,0x97C1,0x97C2,0x97C3,0x97C4,0x97C5,0x97C6,0x97C7,0x97C8,0x97C9,0x97CA,0x97CB,0x97CC,0x97CD,0x97CE,0x97CF, + 0x97D0,0x97D1,0x97D2,0x97D3,0x97D4,0x97D5,0x97D6,0x97D7,0x97D8,0x97D9,0x97DA,0x97DB,0x97DC,0x97DD,0x97DE,0x97DF, + 0x97E0,0x97E1,0x97E2,0x97E3,0x97E4,0x97E5,0x97E6,0x97E7,0x97E8,0x97E9,0x97EA,0x97EB,0x97EC,0x97ED,0x97EE,0x97EF, + 0x97F0,0x97F1,0x97F2,0x97F3,0x97F4,0x97F5,0x97F6,0x97F7,0x97F8,0x97F9,0x97FA,0x97FB,0x97FC,0x97FD,0x97FE,0x97FF, + 0x9800,0x9801,0x9802,0x9803,0x9804,0x9805,0x9806,0x9807,0x9808,0x9809,0x980A,0x980B,0x980C,0x980D,0x980E,0x980F, + 0x9810,0x9811,0x9812,0x9813,0x9814,0x9815,0x9816,0x9817,0x9818,0x9819,0x981A,0x981B,0x981C,0x981D,0x981E,0x981F, + 0x9820,0x9821,0x9822,0x9823,0x9824,0x9825,0x9826,0x9827,0x9828,0x9829,0x982A,0x982B,0x982C,0x982D,0x982E,0x982F, + 0x9830,0x9831,0x9832,0x9833,0x9834,0x9835,0x9836,0x9837,0x9838,0x9839,0x983A,0x983B,0x983C,0x983D,0x983E,0x983F, + 0x9840,0x9841,0x9842,0x9843,0x9844,0x9845,0x9846,0x9847,0x9848,0x9849,0x984A,0x984B,0x984C,0x984D,0x984E,0x984F, + 0x9850,0x9851,0x9852,0x9853,0x9854,0x9855,0x9856,0x9857,0x9858,0x9859,0x985A,0x985B,0x985C,0x985D,0x985E,0x985F, + 0x9860,0x9861,0x9862,0x9863,0x9864,0x9865,0x9866,0x9867,0x9868,0x9869,0x986A,0x986B,0x986C,0x986D,0x986E,0x986F, + 0x9870,0x9871,0x9872,0x9873,0x9874,0x9875,0x9876,0x9877,0x9878,0x9879,0x987A,0x987B,0x987C,0x987D,0x987E,0x987F, + 0x9880,0x9881,0x9882,0x9883,0x9884,0x9885,0x9886,0x9887,0x9888,0x9889,0x988A,0x988B,0x988C,0x988D,0x988E,0x988F, + 0x9890,0x9891,0x9892,0x9893,0x9894,0x9895,0x9896,0x9897,0x9898,0x9899,0x989A,0x989B,0x989C,0x989D,0x989E,0x989F, + 0x98A0,0x98A1,0x98A2,0x98A3,0x98A4,0x98A5,0x98A6,0x98A7,0x98A8,0x98A9,0x98AA,0x98AB,0x98AC,0x98AD,0x98AE,0x98AF, + 0x98B0,0x98B1,0x98B2,0x98B3,0x98B4,0x98B5,0x98B6,0x98B7,0x98B8,0x98B9,0x98BA,0x98BB,0x98BC,0x98BD,0x98BE,0x98BF, + 0x98C0,0x98C1,0x98C2,0x98C3,0x98C4,0x98C5,0x98C6,0x98C7,0x98C8,0x98C9,0x98CA,0x98CB,0x98CC,0x98CD,0x98CE,0x98CF, + 0x98D0,0x98D1,0x98D2,0x98D3,0x98D4,0x98D5,0x98D6,0x98D7,0x98D8,0x98D9,0x98DA,0x98DB,0x98DC,0x98DD,0x98DE,0x98DF, + 0x98E0,0x98E1,0x98E2,0x98E3,0x98E4,0x98E5,0x98E6,0x98E7,0x98E8,0x98E9,0x98EA,0x98EB,0x98EC,0x98ED,0x98EE,0x98EF, + 0x98F0,0x98F1,0x98F2,0x98F3,0x98F4,0x98F5,0x98F6,0x98F7,0x98F8,0x98F9,0x98FA,0x98FB,0x98FC,0x98FD,0x98FE,0x98FF, + 0x9900,0x9901,0x9902,0x9903,0x9904,0x9905,0x9906,0x9907,0x9908,0x9909,0x990A,0x990B,0x990C,0x990D,0x990E,0x990F, + 0x9910,0x9911,0x9912,0x9913,0x9914,0x9915,0x9916,0x9917,0x9918,0x9919,0x991A,0x991B,0x991C,0x991D,0x991E,0x991F, + 0x9920,0x9921,0x9922,0x9923,0x9924,0x9925,0x9926,0x9927,0x9928,0x9929,0x992A,0x992B,0x992C,0x992D,0x992E,0x992F, + 0x9930,0x9931,0x9932,0x9933,0x9934,0x9935,0x9936,0x9937,0x9938,0x9939,0x993A,0x993B,0x993C,0x993D,0x993E,0x993F, + 0x9940,0x9941,0x9942,0x9943,0x9944,0x9945,0x9946,0x9947,0x9948,0x9949,0x994A,0x994B,0x994C,0x994D,0x994E,0x994F, + 0x9950,0x9951,0x9952,0x9953,0x9954,0x9955,0x9956,0x9957,0x9958,0x9959,0x995A,0x995B,0x995C,0x995D,0x995E,0x995F, + 0x9960,0x9961,0x9962,0x9963,0x9964,0x9965,0x9966,0x9967,0x9968,0x9969,0x996A,0x996B,0x996C,0x996D,0x996E,0x996F, + 0x9970,0x9971,0x9972,0x9973,0x9974,0x9975,0x9976,0x9977,0x9978,0x9979,0x997A,0x997B,0x997C,0x997D,0x997E,0x997F, + 0x9980,0x9981,0x9982,0x9983,0x9984,0x9985,0x9986,0x9987,0x9988,0x9989,0x998A,0x998B,0x998C,0x998D,0x998E,0x998F, + 0x9990,0x9991,0x9992,0x9993,0x9994,0x9995,0x9996,0x9997,0x9998,0x9999,0x999A,0x999B,0x999C,0x999D,0x999E,0x999F, + 0x99A0,0x99A1,0x99A2,0x99A3,0x99A4,0x99A5,0x99A6,0x99A7,0x99A8,0x99A9,0x99AA,0x99AB,0x99AC,0x99AD,0x99AE,0x99AF, + 0x99B0,0x99B1,0x99B2,0x99B3,0x99B4,0x99B5,0x99B6,0x99B7,0x99B8,0x99B9,0x99BA,0x99BB,0x99BC,0x99BD,0x99BE,0x99BF, + 0x99C0,0x99C1,0x99C2,0x99C3,0x99C4,0x99C5,0x99C6,0x99C7,0x99C8,0x99C9,0x99CA,0x99CB,0x99CC,0x99CD,0x99CE,0x99CF, + 0x99D0,0x99D1,0x99D2,0x99D3,0x99D4,0x99D5,0x99D6,0x99D7,0x99D8,0x99D9,0x99DA,0x99DB,0x99DC,0x99DD,0x99DE,0x99DF, + 0x99E0,0x99E1,0x99E2,0x99E3,0x99E4,0x99E5,0x99E6,0x99E7,0x99E8,0x99E9,0x99EA,0x99EB,0x99EC,0x99ED,0x99EE,0x99EF, + 0x99F0,0x99F1,0x99F2,0x99F3,0x99F4,0x99F5,0x99F6,0x99F7,0x99F8,0x99F9,0x99FA,0x99FB,0x99FC,0x99FD,0x99FE,0x99FF, + 0x9A00,0x9A01,0x9A02,0x9A03,0x9A04,0x9A05,0x9A06,0x9A07,0x9A08,0x9A09,0x9A0A,0x9A0B,0x9A0C,0x9A0D,0x9A0E,0x9A0F, + 0x9A10,0x9A11,0x9A12,0x9A13,0x9A14,0x9A15,0x9A16,0x9A17,0x9A18,0x9A19,0x9A1A,0x9A1B,0x9A1C,0x9A1D,0x9A1E,0x9A1F, + 0x9A20,0x9A21,0x9A22,0x9A23,0x9A24,0x9A25,0x9A26,0x9A27,0x9A28,0x9A29,0x9A2A,0x9A2B,0x9A2C,0x9A2D,0x9A2E,0x9A2F, + 0x9A30,0x9A31,0x9A32,0x9A33,0x9A34,0x9A35,0x9A36,0x9A37,0x9A38,0x9A39,0x9A3A,0x9A3B,0x9A3C,0x9A3D,0x9A3E,0x9A3F, + 0x9A40,0x9A41,0x9A42,0x9A43,0x9A44,0x9A45,0x9A46,0x9A47,0x9A48,0x9A49,0x9A4A,0x9A4B,0x9A4C,0x9A4D,0x9A4E,0x9A4F, + 0x9A50,0x9A51,0x9A52,0x9A53,0x9A54,0x9A55,0x9A56,0x9A57,0x9A58,0x9A59,0x9A5A,0x9A5B,0x9A5C,0x9A5D,0x9A5E,0x9A5F, + 0x9A60,0x9A61,0x9A62,0x9A63,0x9A64,0x9A65,0x9A66,0x9A67,0x9A68,0x9A69,0x9A6A,0x9A6B,0x9A6C,0x9A6D,0x9A6E,0x9A6F, + 0x9A70,0x9A71,0x9A72,0x9A73,0x9A74,0x9A75,0x9A76,0x9A77,0x9A78,0x9A79,0x9A7A,0x9A7B,0x9A7C,0x9A7D,0x9A7E,0x9A7F, + 0x9A80,0x9A81,0x9A82,0x9A83,0x9A84,0x9A85,0x9A86,0x9A87,0x9A88,0x9A89,0x9A8A,0x9A8B,0x9A8C,0x9A8D,0x9A8E,0x9A8F, + 0x9A90,0x9A91,0x9A92,0x9A93,0x9A94,0x9A95,0x9A96,0x9A97,0x9A98,0x9A99,0x9A9A,0x9A9B,0x9A9C,0x9A9D,0x9A9E,0x9A9F, + 0x9AA0,0x9AA1,0x9AA2,0x9AA3,0x9AA4,0x9AA5,0x9AA6,0x9AA7,0x9AA8,0x9AA9,0x9AAA,0x9AAB,0x9AAC,0x9AAD,0x9AAE,0x9AAF, + 0x9AB0,0x9AB1,0x9AB2,0x9AB3,0x9AB4,0x9AB5,0x9AB6,0x9AB7,0x9AB8,0x9AB9,0x9ABA,0x9ABB,0x9ABC,0x9ABD,0x9ABE,0x9ABF, + 0x9AC0,0x9AC1,0x9AC2,0x9AC3,0x9AC4,0x9AC5,0x9AC6,0x9AC7,0x9AC8,0x9AC9,0x9ACA,0x9ACB,0x9ACC,0x9ACD,0x9ACE,0x9ACF, + 0x9AD0,0x9AD1,0x9AD2,0x9AD3,0x9AD4,0x9AD5,0x9AD6,0x9AD7,0x9AD8,0x9AD9,0x9ADA,0x9ADB,0x9ADC,0x9ADD,0x9ADE,0x9ADF, + 0x9AE0,0x9AE1,0x9AE2,0x9AE3,0x9AE4,0x9AE5,0x9AE6,0x9AE7,0x9AE8,0x9AE9,0x9AEA,0x9AEB,0x9AEC,0x9AED,0x9AEE,0x9AEF, + 0x9AF0,0x9AF1,0x9AF2,0x9AF3,0x9AF4,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AF9,0x9AFA,0x9AFB,0x9AFC,0x9AFD,0x9AFE,0x9AFF, + 0x9B00,0x9B01,0x9B02,0x9B03,0x9B04,0x9B05,0x9B06,0x9B07,0x9B08,0x9B09,0x9B0A,0x9B0B,0x9B0C,0x9B0D,0x9B0E,0x9B0F, + 0x9B10,0x9B11,0x9B12,0x9B13,0x9B14,0x9B15,0x9B16,0x9B17,0x9B18,0x9B19,0x9B1A,0x9B1B,0x9B1C,0x9B1D,0x9B1E,0x9B1F, + 0x9B20,0x9B21,0x9B22,0x9B23,0x9B24,0x9B25,0x9B26,0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2B,0x9B2C,0x9B2D,0x9B2E,0x9B2F, + 0x9B30,0x9B31,0x9B32,0x9B33,0x9B34,0x9B35,0x9B36,0x9B37,0x9B38,0x9B39,0x9B3A,0x9B3B,0x9B3C,0x9B3D,0x9B3E,0x9B3F, + 0x9B40,0x9B41,0x9B42,0x9B43,0x9B44,0x9B45,0x9B46,0x9B47,0x9B48,0x9B49,0x9B4A,0x9B4B,0x9B4C,0x9B4D,0x9B4E,0x9B4F, + 0x9B50,0x9B51,0x9B52,0x9B53,0x9B54,0x9B55,0x9B56,0x9B57,0x9B58,0x9B59,0x9B5A,0x9B5B,0x9B5C,0x9B5D,0x9B5E,0x9B5F, + 0x9B60,0x9B61,0x9B62,0x9B63,0x9B64,0x9B65,0x9B66,0x9B67,0x9B68,0x9B69,0x9B6A,0x9B6B,0x9B6C,0x9B6D,0x9B6E,0x9B6F, + 0x9B70,0x9B71,0x9B72,0x9B73,0x9B74,0x9B75,0x9B76,0x9B77,0x9B78,0x9B79,0x9B7A,0x9B7B,0x9B7C,0x9B7D,0x9B7E,0x9B7F, + 0x9B80,0x9B81,0x9B82,0x9B83,0x9B84,0x9B85,0x9B86,0x9B87,0x9B88,0x9B89,0x9B8A,0x9B8B,0x9B8C,0x9B8D,0x9B8E,0x9B8F, + 0x9B90,0x9B91,0x9B92,0x9B93,0x9B94,0x9B95,0x9B96,0x9B97,0x9B98,0x9B99,0x9B9A,0x9B9B,0x9B9C,0x9B9D,0x9B9E,0x9B9F, + 0x9BA0,0x9BA1,0x9BA2,0x9BA3,0x9BA4,0x9BA5,0x9BA6,0x9BA7,0x9BA8,0x9BA9,0x9BAA,0x9BAB,0x9BAC,0x9BAD,0x9BAE,0x9BAF, + 0x9BB0,0x9BB1,0x9BB2,0x9BB3,0x9BB4,0x9BB5,0x9BB6,0x9BB7,0x9BB8,0x9BB9,0x9BBA,0x9BBB,0x9BBC,0x9BBD,0x9BBE,0x9BBF, + 0x9BC0,0x9BC1,0x9BC2,0x9BC3,0x9BC4,0x9BC5,0x9BC6,0x9BC7,0x9BC8,0x9BC9,0x9BCA,0x9BCB,0x9BCC,0x9BCD,0x9BCE,0x9BCF, + 0x9BD0,0x9BD1,0x9BD2,0x9BD3,0x9BD4,0x9BD5,0x9BD6,0x9BD7,0x9BD8,0x9BD9,0x9BDA,0x9BDB,0x9BDC,0x9BDD,0x9BDE,0x9BDF, + 0x9BE0,0x9BE1,0x9BE2,0x9BE3,0x9BE4,0x9BE5,0x9BE6,0x9BE7,0x9BE8,0x9BE9,0x9BEA,0x9BEB,0x9BEC,0x9BED,0x9BEE,0x9BEF, + 0x9BF0,0x9BF1,0x9BF2,0x9BF3,0x9BF4,0x9BF5,0x9BF6,0x9BF7,0x9BF8,0x9BF9,0x9BFA,0x9BFB,0x9BFC,0x9BFD,0x9BFE,0x9BFF, + 0x9C00,0x9C01,0x9C02,0x9C03,0x9C04,0x9C05,0x9C06,0x9C07,0x9C08,0x9C09,0x9C0A,0x9C0B,0x9C0C,0x9C0D,0x9C0E,0x9C0F, + 0x9C10,0x9C11,0x9C12,0x9C13,0x9C14,0x9C15,0x9C16,0x9C17,0x9C18,0x9C19,0x9C1A,0x9C1B,0x9C1C,0x9C1D,0x9C1E,0x9C1F, + 0x9C20,0x9C21,0x9C22,0x9C23,0x9C24,0x9C25,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,0x9C2B,0x9C2C,0x9C2D,0x9C2E,0x9C2F, + 0x9C30,0x9C31,0x9C32,0x9C33,0x9C34,0x9C35,0x9C36,0x9C37,0x9C38,0x9C39,0x9C3A,0x9C3B,0x9C3C,0x9C3D,0x9C3E,0x9C3F, + 0x9C40,0x9C41,0x9C42,0x9C43,0x9C44,0x9C45,0x9C46,0x9C47,0x9C48,0x9C49,0x9C4A,0x9C4B,0x9C4C,0x9C4D,0x9C4E,0x9C4F, + 0x9C50,0x9C51,0x9C52,0x9C53,0x9C54,0x9C55,0x9C56,0x9C57,0x9C58,0x9C59,0x9C5A,0x9C5B,0x9C5C,0x9C5D,0x9C5E,0x9C5F, + 0x9C60,0x9C61,0x9C62,0x9C63,0x9C64,0x9C65,0x9C66,0x9C67,0x9C68,0x9C69,0x9C6A,0x9C6B,0x9C6C,0x9C6D,0x9C6E,0x9C6F, + 0x9C70,0x9C71,0x9C72,0x9C73,0x9C74,0x9C75,0x9C76,0x9C77,0x9C78,0x9C79,0x9C7A,0x9C7B,0x9C7C,0x9C7D,0x9C7E,0x9C7F, + 0x9C80,0x9C81,0x9C82,0x9C83,0x9C84,0x9C85,0x9C86,0x9C87,0x9C88,0x9C89,0x9C8A,0x9C8B,0x9C8C,0x9C8D,0x9C8E,0x9C8F, + 0x9C90,0x9C91,0x9C92,0x9C93,0x9C94,0x9C95,0x9C96,0x9C97,0x9C98,0x9C99,0x9C9A,0x9C9B,0x9C9C,0x9C9D,0x9C9E,0x9C9F, + 0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA4,0x9CA5,0x9CA6,0x9CA7,0x9CA8,0x9CA9,0x9CAA,0x9CAB,0x9CAC,0x9CAD,0x9CAE,0x9CAF, + 0x9CB0,0x9CB1,0x9CB2,0x9CB3,0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CB8,0x9CB9,0x9CBA,0x9CBB,0x9CBC,0x9CBD,0x9CBE,0x9CBF, + 0x9CC0,0x9CC1,0x9CC2,0x9CC3,0x9CC4,0x9CC5,0x9CC6,0x9CC7,0x9CC8,0x9CC9,0x9CCA,0x9CCB,0x9CCC,0x9CCD,0x9CCE,0x9CCF, + 0x9CD0,0x9CD1,0x9CD2,0x9CD3,0x9CD4,0x9CD5,0x9CD6,0x9CD7,0x9CD8,0x9CD9,0x9CDA,0x9CDB,0x9CDC,0x9CDD,0x9CDE,0x9CDF, + 0x9CE0,0x9CE1,0x9CE2,0x9CE3,0x9CE4,0x9CE5,0x9CE6,0x9CE7,0x9CE8,0x9CE9,0x9CEA,0x9CEB,0x9CEC,0x9CED,0x9CEE,0x9CEF, + 0x9CF0,0x9CF1,0x9CF2,0x9CF3,0x9CF4,0x9CF5,0x9CF6,0x9CF7,0x9CF8,0x9CF9,0x9CFA,0x9CFB,0x9CFC,0x9CFD,0x9CFE,0x9CFF, + 0x9D00,0x9D01,0x9D02,0x9D03,0x9D04,0x9D05,0x9D06,0x9D07,0x9D08,0x9D09,0x9D0A,0x9D0B,0x9D0C,0x9D0D,0x9D0E,0x9D0F, + 0x9D10,0x9D11,0x9D12,0x9D13,0x9D14,0x9D15,0x9D16,0x9D17,0x9D18,0x9D19,0x9D1A,0x9D1B,0x9D1C,0x9D1D,0x9D1E,0x9D1F, + 0x9D20,0x9D21,0x9D22,0x9D23,0x9D24,0x9D25,0x9D26,0x9D27,0x9D28,0x9D29,0x9D2A,0x9D2B,0x9D2C,0x9D2D,0x9D2E,0x9D2F, + 0x9D30,0x9D31,0x9D32,0x9D33,0x9D34,0x9D35,0x9D36,0x9D37,0x9D38,0x9D39,0x9D3A,0x9D3B,0x9D3C,0x9D3D,0x9D3E,0x9D3F, + 0x9D40,0x9D41,0x9D42,0x9D43,0x9D44,0x9D45,0x9D46,0x9D47,0x9D48,0x9D49,0x9D4A,0x9D4B,0x9D4C,0x9D4D,0x9D4E,0x9D4F, + 0x9D50,0x9D51,0x9D52,0x9D53,0x9D54,0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0x9D5A,0x9D5B,0x9D5C,0x9D5D,0x9D5E,0x9D5F, + 0x9D60,0x9D61,0x9D62,0x9D63,0x9D64,0x9D65,0x9D66,0x9D67,0x9D68,0x9D69,0x9D6A,0x9D6B,0x9D6C,0x9D6D,0x9D6E,0x9D6F, + 0x9D70,0x9D71,0x9D72,0x9D73,0x9D74,0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A,0x9D7B,0x9D7C,0x9D7D,0x9D7E,0x9D7F, + 0x9D80,0x9D81,0x9D82,0x9D83,0x9D84,0x9D85,0x9D86,0x9D87,0x9D88,0x9D89,0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F, + 0x9D90,0x9D91,0x9D92,0x9D93,0x9D94,0x9D95,0x9D96,0x9D97,0x9D98,0x9D99,0x9D9A,0x9D9B,0x9D9C,0x9D9D,0x9D9E,0x9D9F, + 0x9DA0,0x9DA1,0x9DA2,0x9DA3,0x9DA4,0x9DA5,0x9DA6,0x9DA7,0x9DA8,0x9DA9,0x9DAA,0x9DAB,0x9DAC,0x9DAD,0x9DAE,0x9DAF, + 0x9DB0,0x9DB1,0x9DB2,0x9DB3,0x9DB4,0x9DB5,0x9DB6,0x9DB7,0x9DB8,0x9DB9,0x9DBA,0x9DBB,0x9DBC,0x9DBD,0x9DBE,0x9DBF, + 0x9DC0,0x9DC1,0x9DC2,0x9DC3,0x9DC4,0x9DC5,0x9DC6,0x9DC7,0x9DC8,0x9DC9,0x9DCA,0x9DCB,0x9DCC,0x9DCD,0x9DCE,0x9DCF, + 0x9DD0,0x9DD1,0x9DD2,0x9DD3,0x9DD4,0x9DD5,0x9DD6,0x9DD7,0x9DD8,0x9DD9,0x9DDA,0x9DDB,0x9DDC,0x9DDD,0x9DDE,0x9DDF, + 0x9DE0,0x9DE1,0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6,0x9DE7,0x9DE8,0x9DE9,0x9DEA,0x9DEB,0x9DEC,0x9DED,0x9DEE,0x9DEF, + 0x9DF0,0x9DF1,0x9DF2,0x9DF3,0x9DF4,0x9DF5,0x9DF6,0x9DF7,0x9DF8,0x9DF9,0x9DFA,0x9DFB,0x9DFC,0x9DFD,0x9DFE,0x9DFF, + 0x9E00,0x9E01,0x9E02,0x9E03,0x9E04,0x9E05,0x9E06,0x9E07,0x9E08,0x9E09,0x9E0A,0x9E0B,0x9E0C,0x9E0D,0x9E0E,0x9E0F, + 0x9E10,0x9E11,0x9E12,0x9E13,0x9E14,0x9E15,0x9E16,0x9E17,0x9E18,0x9E19,0x9E1A,0x9E1B,0x9E1C,0x9E1D,0x9E1E,0x9E1F, + 0x9E20,0x9E21,0x9E22,0x9E23,0x9E24,0x9E25,0x9E26,0x9E27,0x9E28,0x9E29,0x9E2A,0x9E2B,0x9E2C,0x9E2D,0x9E2E,0x9E2F, + 0x9E30,0x9E31,0x9E32,0x9E33,0x9E34,0x9E35,0x9E36,0x9E37,0x9E38,0x9E39,0x9E3A,0x9E3B,0x9E3C,0x9E3D,0x9E3E,0x9E3F, + 0x9E40,0x9E41,0x9E42,0x9E43,0x9E44,0x9E45,0x9E46,0x9E47,0x9E48,0x9E49,0x9E4A,0x9E4B,0x9E4C,0x9E4D,0x9E4E,0x9E4F, + 0x9E50,0x9E51,0x9E52,0x9E53,0x9E54,0x9E55,0x9E56,0x9E57,0x9E58,0x9E59,0x9E5A,0x9E5B,0x9E5C,0x9E5D,0x9E5E,0x9E5F, + 0x9E60,0x9E61,0x9E62,0x9E63,0x9E64,0x9E65,0x9E66,0x9E67,0x9E68,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E6D,0x9E6E,0x9E6F, + 0x9E70,0x9E71,0x9E72,0x9E73,0x9E74,0x9E75,0x9E76,0x9E77,0x9E78,0x9E79,0x9E7A,0x9E7B,0x9E7C,0x9E7D,0x9E7E,0x9E7F, + 0x9E80,0x9E81,0x9E82,0x9E83,0x9E84,0x9E85,0x9E86,0x9E87,0x9E88,0x9E89,0x9E8A,0x9E8B,0x9E8C,0x9E8D,0x9E8E,0x9E8F, + 0x9E90,0x9E91,0x9E92,0x9E93,0x9E94,0x9E95,0x9E96,0x9E97,0x9E98,0x9E99,0x9E9A,0x9E9B,0x9E9C,0x9E9D,0x9E9E,0x9E9F, + 0x9EA0,0x9EA1,0x9EA2,0x9EA3,0x9EA4,0x9EA5,0x9EA6,0x9EA7,0x9EA8,0x9EA9,0x9EAA,0x9EAB,0x9EAC,0x9EAD,0x9EAE,0x9EAF, + 0x9EB0,0x9EB1,0x9EB2,0x9EB3,0x9EB4,0x9EB5,0x9EB6,0x9EB7,0x9EB8,0x9EB9,0x9EBA,0x9EBB,0x9EBC,0x9EBD,0x9EBE,0x9EBF, + 0x9EC0,0x9EC1,0x9EC2,0x9EC3,0x9EC4,0x9EC5,0x9EC6,0x9EC7,0x9EC8,0x9EC9,0x9ECA,0x9ECB,0x9ECC,0x9ECD,0x9ECE,0x9ECF, + 0x9ED0,0x9ED1,0x9ED2,0x9ED3,0x9ED4,0x9ED5,0x9ED6,0x9ED7,0x9ED8,0x9ED9,0x9EDA,0x9EDB,0x9EDC,0x9EDD,0x9EDE,0x9EDF, + 0x9EE0,0x9EE1,0x9EE2,0x9EE3,0x9EE4,0x9EE5,0x9EE6,0x9EE7,0x9EE8,0x9EE9,0x9EEA,0x9EEB,0x9EEC,0x9EED,0x9EEE,0x9EEF, + 0x9EF0,0x9EF1,0x9EF2,0x9EF3,0x9EF4,0x9EF5,0x9EF6,0x9EF7,0x9EF8,0x9EF9,0x9EFA,0x9EFB,0x9EFC,0x9EFD,0x9EFE,0x9EFF, + 0x9F00,0x9F01,0x9F02,0x9F03,0x9F04,0x9F05,0x9F06,0x9F07,0x9F08,0x9F09,0x9F0A,0x9F0B,0x9F0C,0x9F0D,0x9F0E,0x9F0F, + 0x9F10,0x9F11,0x9F12,0x9F13,0x9F14,0x9F15,0x9F16,0x9F17,0x9F18,0x9F19,0x9F1A,0x9F1B,0x9F1C,0x9F1D,0x9F1E,0x9F1F, + 0x9F20,0x9F21,0x9F22,0x9F23,0x9F24,0x9F25,0x9F26,0x9F27,0x9F28,0x9F29,0x9F2A,0x9F2B,0x9F2C,0x9F2D,0x9F2E,0x9F2F, + 0x9F30,0x9F31,0x9F32,0x9F33,0x9F34,0x9F35,0x9F36,0x9F37,0x9F38,0x9F39,0x9F3A,0x9F3B,0x9F3C,0x9F3D,0x9F3E,0x9F3F, + 0x9F40,0x9F41,0x9F42,0x9F43,0x9F44,0x9F45,0x9F46,0x9F47,0x9F48,0x9F49,0x9F4A,0x9F4B,0x9F4C,0x9F4D,0x9F4E,0x9F4F, + 0x9F50,0x9F51,0x9F52,0x9F53,0x9F54,0x9F55,0x9F56,0x9F57,0x9F58,0x9F59,0x9F5A,0x9F5B,0x9F5C,0x9F5D,0x9F5E,0x9F5F, + 0x9F60,0x9F61,0x9F62,0x9F63,0x9F64,0x9F65,0x9F66,0x9F67,0x9F68,0x9F69,0x9F6A,0x9F6B,0x9F6C,0x9F6D,0x9F6E,0x9F6F, + 0x9F70,0x9F71,0x9F72,0x9F73,0x9F74,0x9F75,0x9F76,0x9F77,0x9F78,0x9F79,0x9F7A,0x9F7B,0x9F7C,0x9F7D,0x9F7E,0x9F7F, + 0x9F80,0x9F81,0x9F82,0x9F83,0x9F84,0x9F85,0x9F86,0x9F87,0x9F88,0x9F89,0x9F8A,0x9F8B,0x9F8C,0x9F8D,0x9F8E,0x9F8F, + 0x9F90,0x9F91,0x9F92,0x9F93,0x9F94,0x9F95,0x9F96,0x9F97,0x9F98,0x9F99,0x9F9A,0x9F9B,0x9F9C,0x9F9D,0x9F9E,0x9F9F, + 0x9FA0,0x9FA1,0x9FA2,0x9FA3,0x9FA4,0x9FA5,0x9FA6,0x9FA7,0x9FA8,0x9FA9,0x9FAA,0x9FAB,0x9FAC,0x9FAD,0x9FAE,0x9FAF, + 0x9FB0,0x9FB1,0x9FB2,0x9FB3,0x9FB4,0x9FB5,0x9FB6,0x9FB7,0x9FB8,0x9FB9,0x9FBA,0x9FBB,0x9FBC,0x9FBD,0x9FBE,0x9FBF, + 0x9FC0,0x9FC1,0x9FC2,0x9FC3,0x9FC4,0x9FC5,0x9FC6,0x9FC7,0x9FC8,0x9FC9,0x9FCA,0x9FCB,0x9FCC,0x9FCD,0x9FCE,0x9FCF, + 0x9FD0,0x9FD1,0x9FD2,0x9FD3,0x9FD4,0x9FD5,0x9FD6,0x9FD7,0x9FD8,0x9FD9,0x9FDA,0x9FDB,0x9FDC,0x9FDD,0x9FDE,0x9FDF, + 0x9FE0,0x9FE1,0x9FE2,0x9FE3,0x9FE4,0x9FE5,0x9FE6,0x9FE7,0x9FE8,0x9FE9,0x9FEA,0x9FEB,0x9FEC,0x9FED,0x9FEE,0x9FEF, + 0x9FF0,0x9FF1,0x9FF2,0x9FF3,0x9FF4,0x9FF5,0x9FF6,0x9FF7,0x9FF8,0x9FF9,0x9FFA,0x9FFB,0x9FFC,0x9FFD,0x9FFE,0x9FFF, + 0xA000,0xA001,0xA002,0xA003,0xA004,0xA005,0xA006,0xA007,0xA008,0xA009,0xA00A,0xA00B,0xA00C,0xA00D,0xA00E,0xA00F, + 0xA010,0xA011,0xA012,0xA013,0xA014,0xA015,0xA016,0xA017,0xA018,0xA019,0xA01A,0xA01B,0xA01C,0xA01D,0xA01E,0xA01F, + 0xA020,0xA021,0xA022,0xA023,0xA024,0xA025,0xA026,0xA027,0xA028,0xA029,0xA02A,0xA02B,0xA02C,0xA02D,0xA02E,0xA02F, + 0xA030,0xA031,0xA032,0xA033,0xA034,0xA035,0xA036,0xA037,0xA038,0xA039,0xA03A,0xA03B,0xA03C,0xA03D,0xA03E,0xA03F, + 0xA040,0xA041,0xA042,0xA043,0xA044,0xA045,0xA046,0xA047,0xA048,0xA049,0xA04A,0xA04B,0xA04C,0xA04D,0xA04E,0xA04F, + 0xA050,0xA051,0xA052,0xA053,0xA054,0xA055,0xA056,0xA057,0xA058,0xA059,0xA05A,0xA05B,0xA05C,0xA05D,0xA05E,0xA05F, + 0xA060,0xA061,0xA062,0xA063,0xA064,0xA065,0xA066,0xA067,0xA068,0xA069,0xA06A,0xA06B,0xA06C,0xA06D,0xA06E,0xA06F, + 0xA070,0xA071,0xA072,0xA073,0xA074,0xA075,0xA076,0xA077,0xA078,0xA079,0xA07A,0xA07B,0xA07C,0xA07D,0xA07E,0xA07F, + 0xA080,0xA081,0xA082,0xA083,0xA084,0xA085,0xA086,0xA087,0xA088,0xA089,0xA08A,0xA08B,0xA08C,0xA08D,0xA08E,0xA08F, + 0xA090,0xA091,0xA092,0xA093,0xA094,0xA095,0xA096,0xA097,0xA098,0xA099,0xA09A,0xA09B,0xA09C,0xA09D,0xA09E,0xA09F, + 0xA0A0,0xA0A1,0xA0A2,0xA0A3,0xA0A4,0xA0A5,0xA0A6,0xA0A7,0xA0A8,0xA0A9,0xA0AA,0xA0AB,0xA0AC,0xA0AD,0xA0AE,0xA0AF, + 0xA0B0,0xA0B1,0xA0B2,0xA0B3,0xA0B4,0xA0B5,0xA0B6,0xA0B7,0xA0B8,0xA0B9,0xA0BA,0xA0BB,0xA0BC,0xA0BD,0xA0BE,0xA0BF, + 0xA0C0,0xA0C1,0xA0C2,0xA0C3,0xA0C4,0xA0C5,0xA0C6,0xA0C7,0xA0C8,0xA0C9,0xA0CA,0xA0CB,0xA0CC,0xA0CD,0xA0CE,0xA0CF, + 0xA0D0,0xA0D1,0xA0D2,0xA0D3,0xA0D4,0xA0D5,0xA0D6,0xA0D7,0xA0D8,0xA0D9,0xA0DA,0xA0DB,0xA0DC,0xA0DD,0xA0DE,0xA0DF, + 0xA0E0,0xA0E1,0xA0E2,0xA0E3,0xA0E4,0xA0E5,0xA0E6,0xA0E7,0xA0E8,0xA0E9,0xA0EA,0xA0EB,0xA0EC,0xA0ED,0xA0EE,0xA0EF, + 0xA0F0,0xA0F1,0xA0F2,0xA0F3,0xA0F4,0xA0F5,0xA0F6,0xA0F7,0xA0F8,0xA0F9,0xA0FA,0xA0FB,0xA0FC,0xA0FD,0xA0FE,0xA0FF, + 0xA100,0xA101,0xA102,0xA103,0xA104,0xA105,0xA106,0xA107,0xA108,0xA109,0xA10A,0xA10B,0xA10C,0xA10D,0xA10E,0xA10F, + 0xA110,0xA111,0xA112,0xA113,0xA114,0xA115,0xA116,0xA117,0xA118,0xA119,0xA11A,0xA11B,0xA11C,0xA11D,0xA11E,0xA11F, + 0xA120,0xA121,0xA122,0xA123,0xA124,0xA125,0xA126,0xA127,0xA128,0xA129,0xA12A,0xA12B,0xA12C,0xA12D,0xA12E,0xA12F, + 0xA130,0xA131,0xA132,0xA133,0xA134,0xA135,0xA136,0xA137,0xA138,0xA139,0xA13A,0xA13B,0xA13C,0xA13D,0xA13E,0xA13F, + 0xA140,0xA141,0xA142,0xA143,0xA144,0xA145,0xA146,0xA147,0xA148,0xA149,0xA14A,0xA14B,0xA14C,0xA14D,0xA14E,0xA14F, + 0xA150,0xA151,0xA152,0xA153,0xA154,0xA155,0xA156,0xA157,0xA158,0xA159,0xA15A,0xA15B,0xA15C,0xA15D,0xA15E,0xA15F, + 0xA160,0xA161,0xA162,0xA163,0xA164,0xA165,0xA166,0xA167,0xA168,0xA169,0xA16A,0xA16B,0xA16C,0xA16D,0xA16E,0xA16F, + 0xA170,0xA171,0xA172,0xA173,0xA174,0xA175,0xA176,0xA177,0xA178,0xA179,0xA17A,0xA17B,0xA17C,0xA17D,0xA17E,0xA17F, + 0xA180,0xA181,0xA182,0xA183,0xA184,0xA185,0xA186,0xA187,0xA188,0xA189,0xA18A,0xA18B,0xA18C,0xA18D,0xA18E,0xA18F, + 0xA190,0xA191,0xA192,0xA193,0xA194,0xA195,0xA196,0xA197,0xA198,0xA199,0xA19A,0xA19B,0xA19C,0xA19D,0xA19E,0xA19F, + 0xA1A0,0xA1A1,0xA1A2,0xA1A3,0xA1A4,0xA1A5,0xA1A6,0xA1A7,0xA1A8,0xA1A9,0xA1AA,0xA1AB,0xA1AC,0xA1AD,0xA1AE,0xA1AF, + 0xA1B0,0xA1B1,0xA1B2,0xA1B3,0xA1B4,0xA1B5,0xA1B6,0xA1B7,0xA1B8,0xA1B9,0xA1BA,0xA1BB,0xA1BC,0xA1BD,0xA1BE,0xA1BF, + 0xA1C0,0xA1C1,0xA1C2,0xA1C3,0xA1C4,0xA1C5,0xA1C6,0xA1C7,0xA1C8,0xA1C9,0xA1CA,0xA1CB,0xA1CC,0xA1CD,0xA1CE,0xA1CF, + 0xA1D0,0xA1D1,0xA1D2,0xA1D3,0xA1D4,0xA1D5,0xA1D6,0xA1D7,0xA1D8,0xA1D9,0xA1DA,0xA1DB,0xA1DC,0xA1DD,0xA1DE,0xA1DF, + 0xA1E0,0xA1E1,0xA1E2,0xA1E3,0xA1E4,0xA1E5,0xA1E6,0xA1E7,0xA1E8,0xA1E9,0xA1EA,0xA1EB,0xA1EC,0xA1ED,0xA1EE,0xA1EF, + 0xA1F0,0xA1F1,0xA1F2,0xA1F3,0xA1F4,0xA1F5,0xA1F6,0xA1F7,0xA1F8,0xA1F9,0xA1FA,0xA1FB,0xA1FC,0xA1FD,0xA1FE,0xA1FF, + 0xA200,0xA201,0xA202,0xA203,0xA204,0xA205,0xA206,0xA207,0xA208,0xA209,0xA20A,0xA20B,0xA20C,0xA20D,0xA20E,0xA20F, + 0xA210,0xA211,0xA212,0xA213,0xA214,0xA215,0xA216,0xA217,0xA218,0xA219,0xA21A,0xA21B,0xA21C,0xA21D,0xA21E,0xA21F, + 0xA220,0xA221,0xA222,0xA223,0xA224,0xA225,0xA226,0xA227,0xA228,0xA229,0xA22A,0xA22B,0xA22C,0xA22D,0xA22E,0xA22F, + 0xA230,0xA231,0xA232,0xA233,0xA234,0xA235,0xA236,0xA237,0xA238,0xA239,0xA23A,0xA23B,0xA23C,0xA23D,0xA23E,0xA23F, + 0xA240,0xA241,0xA242,0xA243,0xA244,0xA245,0xA246,0xA247,0xA248,0xA249,0xA24A,0xA24B,0xA24C,0xA24D,0xA24E,0xA24F, + 0xA250,0xA251,0xA252,0xA253,0xA254,0xA255,0xA256,0xA257,0xA258,0xA259,0xA25A,0xA25B,0xA25C,0xA25D,0xA25E,0xA25F, + 0xA260,0xA261,0xA262,0xA263,0xA264,0xA265,0xA266,0xA267,0xA268,0xA269,0xA26A,0xA26B,0xA26C,0xA26D,0xA26E,0xA26F, + 0xA270,0xA271,0xA272,0xA273,0xA274,0xA275,0xA276,0xA277,0xA278,0xA279,0xA27A,0xA27B,0xA27C,0xA27D,0xA27E,0xA27F, + 0xA280,0xA281,0xA282,0xA283,0xA284,0xA285,0xA286,0xA287,0xA288,0xA289,0xA28A,0xA28B,0xA28C,0xA28D,0xA28E,0xA28F, + 0xA290,0xA291,0xA292,0xA293,0xA294,0xA295,0xA296,0xA297,0xA298,0xA299,0xA29A,0xA29B,0xA29C,0xA29D,0xA29E,0xA29F, + 0xA2A0,0xA2A1,0xA2A2,0xA2A3,0xA2A4,0xA2A5,0xA2A6,0xA2A7,0xA2A8,0xA2A9,0xA2AA,0xA2AB,0xA2AC,0xA2AD,0xA2AE,0xA2AF, + 0xA2B0,0xA2B1,0xA2B2,0xA2B3,0xA2B4,0xA2B5,0xA2B6,0xA2B7,0xA2B8,0xA2B9,0xA2BA,0xA2BB,0xA2BC,0xA2BD,0xA2BE,0xA2BF, + 0xA2C0,0xA2C1,0xA2C2,0xA2C3,0xA2C4,0xA2C5,0xA2C6,0xA2C7,0xA2C8,0xA2C9,0xA2CA,0xA2CB,0xA2CC,0xA2CD,0xA2CE,0xA2CF, + 0xA2D0,0xA2D1,0xA2D2,0xA2D3,0xA2D4,0xA2D5,0xA2D6,0xA2D7,0xA2D8,0xA2D9,0xA2DA,0xA2DB,0xA2DC,0xA2DD,0xA2DE,0xA2DF, + 0xA2E0,0xA2E1,0xA2E2,0xA2E3,0xA2E4,0xA2E5,0xA2E6,0xA2E7,0xA2E8,0xA2E9,0xA2EA,0xA2EB,0xA2EC,0xA2ED,0xA2EE,0xA2EF, + 0xA2F0,0xA2F1,0xA2F2,0xA2F3,0xA2F4,0xA2F5,0xA2F6,0xA2F7,0xA2F8,0xA2F9,0xA2FA,0xA2FB,0xA2FC,0xA2FD,0xA2FE,0xA2FF, + 0xA300,0xA301,0xA302,0xA303,0xA304,0xA305,0xA306,0xA307,0xA308,0xA309,0xA30A,0xA30B,0xA30C,0xA30D,0xA30E,0xA30F, + 0xA310,0xA311,0xA312,0xA313,0xA314,0xA315,0xA316,0xA317,0xA318,0xA319,0xA31A,0xA31B,0xA31C,0xA31D,0xA31E,0xA31F, + 0xA320,0xA321,0xA322,0xA323,0xA324,0xA325,0xA326,0xA327,0xA328,0xA329,0xA32A,0xA32B,0xA32C,0xA32D,0xA32E,0xA32F, + 0xA330,0xA331,0xA332,0xA333,0xA334,0xA335,0xA336,0xA337,0xA338,0xA339,0xA33A,0xA33B,0xA33C,0xA33D,0xA33E,0xA33F, + 0xA340,0xA341,0xA342,0xA343,0xA344,0xA345,0xA346,0xA347,0xA348,0xA349,0xA34A,0xA34B,0xA34C,0xA34D,0xA34E,0xA34F, + 0xA350,0xA351,0xA352,0xA353,0xA354,0xA355,0xA356,0xA357,0xA358,0xA359,0xA35A,0xA35B,0xA35C,0xA35D,0xA35E,0xA35F, + 0xA360,0xA361,0xA362,0xA363,0xA364,0xA365,0xA366,0xA367,0xA368,0xA369,0xA36A,0xA36B,0xA36C,0xA36D,0xA36E,0xA36F, + 0xA370,0xA371,0xA372,0xA373,0xA374,0xA375,0xA376,0xA377,0xA378,0xA379,0xA37A,0xA37B,0xA37C,0xA37D,0xA37E,0xA37F, + 0xA380,0xA381,0xA382,0xA383,0xA384,0xA385,0xA386,0xA387,0xA388,0xA389,0xA38A,0xA38B,0xA38C,0xA38D,0xA38E,0xA38F, + 0xA390,0xA391,0xA392,0xA393,0xA394,0xA395,0xA396,0xA397,0xA398,0xA399,0xA39A,0xA39B,0xA39C,0xA39D,0xA39E,0xA39F, + 0xA3A0,0xA3A1,0xA3A2,0xA3A3,0xA3A4,0xA3A5,0xA3A6,0xA3A7,0xA3A8,0xA3A9,0xA3AA,0xA3AB,0xA3AC,0xA3AD,0xA3AE,0xA3AF, + 0xA3B0,0xA3B1,0xA3B2,0xA3B3,0xA3B4,0xA3B5,0xA3B6,0xA3B7,0xA3B8,0xA3B9,0xA3BA,0xA3BB,0xA3BC,0xA3BD,0xA3BE,0xA3BF, + 0xA3C0,0xA3C1,0xA3C2,0xA3C3,0xA3C4,0xA3C5,0xA3C6,0xA3C7,0xA3C8,0xA3C9,0xA3CA,0xA3CB,0xA3CC,0xA3CD,0xA3CE,0xA3CF, + 0xA3D0,0xA3D1,0xA3D2,0xA3D3,0xA3D4,0xA3D5,0xA3D6,0xA3D7,0xA3D8,0xA3D9,0xA3DA,0xA3DB,0xA3DC,0xA3DD,0xA3DE,0xA3DF, + 0xA3E0,0xA3E1,0xA3E2,0xA3E3,0xA3E4,0xA3E5,0xA3E6,0xA3E7,0xA3E8,0xA3E9,0xA3EA,0xA3EB,0xA3EC,0xA3ED,0xA3EE,0xA3EF, + 0xA3F0,0xA3F1,0xA3F2,0xA3F3,0xA3F4,0xA3F5,0xA3F6,0xA3F7,0xA3F8,0xA3F9,0xA3FA,0xA3FB,0xA3FC,0xA3FD,0xA3FE,0xA3FF, + 0xA400,0xA401,0xA402,0xA403,0xA404,0xA405,0xA406,0xA407,0xA408,0xA409,0xA40A,0xA40B,0xA40C,0xA40D,0xA40E,0xA40F, + 0xA410,0xA411,0xA412,0xA413,0xA414,0xA415,0xA416,0xA417,0xA418,0xA419,0xA41A,0xA41B,0xA41C,0xA41D,0xA41E,0xA41F, + 0xA420,0xA421,0xA422,0xA423,0xA424,0xA425,0xA426,0xA427,0xA428,0xA429,0xA42A,0xA42B,0xA42C,0xA42D,0xA42E,0xA42F, + 0xA430,0xA431,0xA432,0xA433,0xA434,0xA435,0xA436,0xA437,0xA438,0xA439,0xA43A,0xA43B,0xA43C,0xA43D,0xA43E,0xA43F, + 0xA440,0xA441,0xA442,0xA443,0xA444,0xA445,0xA446,0xA447,0xA448,0xA449,0xA44A,0xA44B,0xA44C,0xA44D,0xA44E,0xA44F, + 0xA450,0xA451,0xA452,0xA453,0xA454,0xA455,0xA456,0xA457,0xA458,0xA459,0xA45A,0xA45B,0xA45C,0xA45D,0xA45E,0xA45F, + 0xA460,0xA461,0xA462,0xA463,0xA464,0xA465,0xA466,0xA467,0xA468,0xA469,0xA46A,0xA46B,0xA46C,0xA46D,0xA46E,0xA46F, + 0xA470,0xA471,0xA472,0xA473,0xA474,0xA475,0xA476,0xA477,0xA478,0xA479,0xA47A,0xA47B,0xA47C,0xA47D,0xA47E,0xA47F, + 0xA480,0xA481,0xA482,0xA483,0xA484,0xA485,0xA486,0xA487,0xA488,0xA489,0xA48A,0xA48B,0xA48C,0xA48D,0xA48E,0xA48F, + 0xA490,0xA491,0xA492,0xA493,0xA494,0xA495,0xA496,0xA497,0xA498,0xA499,0xA49A,0xA49B,0xA49C,0xA49D,0xA49E,0xA49F, + 0xA4A0,0xA4A1,0xA4A2,0xA4A3,0xA4A4,0xA4A5,0xA4A6,0xA4A7,0xA4A8,0xA4A9,0xA4AA,0xA4AB,0xA4AC,0xA4AD,0xA4AE,0xA4AF, + 0xA4B0,0xA4B1,0xA4B2,0xA4B3,0xA4B4,0xA4B5,0xA4B6,0xA4B7,0xA4B8,0xA4B9,0xA4BA,0xA4BB,0xA4BC,0xA4BD,0xA4BE,0xA4BF, + 0xA4C0,0xA4C1,0xA4C2,0xA4C3,0xA4C4,0xA4C5,0xA4C6,0xA4C7,0xA4C8,0xA4C9,0xA4CA,0xA4CB,0xA4CC,0xA4CD,0xA4CE,0xA4CF, + 0xA4D0,0xA4D1,0xA4D2,0xA4D3,0xA4D4,0xA4D5,0xA4D6,0xA4D7,0xA4D8,0xA4D9,0xA4DA,0xA4DB,0xA4DC,0xA4DD,0xA4DE,0xA4DF, + 0xA4E0,0xA4E1,0xA4E2,0xA4E3,0xA4E4,0xA4E5,0xA4E6,0xA4E7,0xA4E8,0xA4E9,0xA4EA,0xA4EB,0xA4EC,0xA4ED,0xA4EE,0xA4EF, + 0xA4F0,0xA4F1,0xA4F2,0xA4F3,0xA4F4,0xA4F5,0xA4F6,0xA4F7,0xA4F8,0xA4F9,0xA4FA,0xA4FB,0xA4FC,0xA4FD,0xA4FE,0xA4FF, + 0xA500,0xA501,0xA502,0xA503,0xA504,0xA505,0xA506,0xA507,0xA508,0xA509,0xA50A,0xA50B,0xA50C,0xA50D,0xA50E,0xA50F, + 0xA510,0xA511,0xA512,0xA513,0xA514,0xA515,0xA516,0xA517,0xA518,0xA519,0xA51A,0xA51B,0xA51C,0xA51D,0xA51E,0xA51F, + 0xA520,0xA521,0xA522,0xA523,0xA524,0xA525,0xA526,0xA527,0xA528,0xA529,0xA52A,0xA52B,0xA52C,0xA52D,0xA52E,0xA52F, + 0xA530,0xA531,0xA532,0xA533,0xA534,0xA535,0xA536,0xA537,0xA538,0xA539,0xA53A,0xA53B,0xA53C,0xA53D,0xA53E,0xA53F, + 0xA540,0xA541,0xA542,0xA543,0xA544,0xA545,0xA546,0xA547,0xA548,0xA549,0xA54A,0xA54B,0xA54C,0xA54D,0xA54E,0xA54F, + 0xA550,0xA551,0xA552,0xA553,0xA554,0xA555,0xA556,0xA557,0xA558,0xA559,0xA55A,0xA55B,0xA55C,0xA55D,0xA55E,0xA55F, + 0xA560,0xA561,0xA562,0xA563,0xA564,0xA565,0xA566,0xA567,0xA568,0xA569,0xA56A,0xA56B,0xA56C,0xA56D,0xA56E,0xA56F, + 0xA570,0xA571,0xA572,0xA573,0xA574,0xA575,0xA576,0xA577,0xA578,0xA579,0xA57A,0xA57B,0xA57C,0xA57D,0xA57E,0xA57F, + 0xA580,0xA581,0xA582,0xA583,0xA584,0xA585,0xA586,0xA587,0xA588,0xA589,0xA58A,0xA58B,0xA58C,0xA58D,0xA58E,0xA58F, + 0xA590,0xA591,0xA592,0xA593,0xA594,0xA595,0xA596,0xA597,0xA598,0xA599,0xA59A,0xA59B,0xA59C,0xA59D,0xA59E,0xA59F, + 0xA5A0,0xA5A1,0xA5A2,0xA5A3,0xA5A4,0xA5A5,0xA5A6,0xA5A7,0xA5A8,0xA5A9,0xA5AA,0xA5AB,0xA5AC,0xA5AD,0xA5AE,0xA5AF, + 0xA5B0,0xA5B1,0xA5B2,0xA5B3,0xA5B4,0xA5B5,0xA5B6,0xA5B7,0xA5B8,0xA5B9,0xA5BA,0xA5BB,0xA5BC,0xA5BD,0xA5BE,0xA5BF, + 0xA5C0,0xA5C1,0xA5C2,0xA5C3,0xA5C4,0xA5C5,0xA5C6,0xA5C7,0xA5C8,0xA5C9,0xA5CA,0xA5CB,0xA5CC,0xA5CD,0xA5CE,0xA5CF, + 0xA5D0,0xA5D1,0xA5D2,0xA5D3,0xA5D4,0xA5D5,0xA5D6,0xA5D7,0xA5D8,0xA5D9,0xA5DA,0xA5DB,0xA5DC,0xA5DD,0xA5DE,0xA5DF, + 0xA5E0,0xA5E1,0xA5E2,0xA5E3,0xA5E4,0xA5E5,0xA5E6,0xA5E7,0xA5E8,0xA5E9,0xA5EA,0xA5EB,0xA5EC,0xA5ED,0xA5EE,0xA5EF, + 0xA5F0,0xA5F1,0xA5F2,0xA5F3,0xA5F4,0xA5F5,0xA5F6,0xA5F7,0xA5F8,0xA5F9,0xA5FA,0xA5FB,0xA5FC,0xA5FD,0xA5FE,0xA5FF, + 0xA600,0xA601,0xA602,0xA603,0xA604,0xA605,0xA606,0xA607,0xA608,0xA609,0xA60A,0xA60B,0xA60C,0xA60D,0xA60E,0xA60F, + 0xA610,0xA611,0xA612,0xA613,0xA614,0xA615,0xA616,0xA617,0xA618,0xA619,0xA61A,0xA61B,0xA61C,0xA61D,0xA61E,0xA61F, + 0xA620,0xA621,0xA622,0xA623,0xA624,0xA625,0xA626,0xA627,0xA628,0xA629,0xA62A,0xA62B,0xA62C,0xA62D,0xA62E,0xA62F, + 0xA630,0xA631,0xA632,0xA633,0xA634,0xA635,0xA636,0xA637,0xA638,0xA639,0xA63A,0xA63B,0xA63C,0xA63D,0xA63E,0xA63F, + 0xA640,0xA641,0xA642,0xA643,0xA644,0xA645,0xA646,0xA647,0xA648,0xA649,0xA64A,0xA64B,0xA64C,0xA64D,0xA64E,0xA64F, + 0xA650,0xA651,0xA652,0xA653,0xA654,0xA655,0xA656,0xA657,0xA658,0xA659,0xA65A,0xA65B,0xA65C,0xA65D,0xA65E,0xA65F, + 0xA660,0xA661,0xA662,0xA663,0xA664,0xA665,0xA666,0xA667,0xA668,0xA669,0xA66A,0xA66B,0xA66C,0xA66D,0xA66E,0xA66F, + 0xA670,0xA671,0xA672,0xA673,0xA674,0xA675,0xA676,0xA677,0xA678,0xA679,0xA67A,0xA67B,0xA67C,0xA67D,0xA67E,0xA67F, + 0xA680,0xA681,0xA682,0xA683,0xA684,0xA685,0xA686,0xA687,0xA688,0xA689,0xA68A,0xA68B,0xA68C,0xA68D,0xA68E,0xA68F, + 0xA690,0xA691,0xA692,0xA693,0xA694,0xA695,0xA696,0xA697,0xA698,0xA699,0xA69A,0xA69B,0xA69C,0xA69D,0xA69E,0xA69F, + 0xA6A0,0xA6A1,0xA6A2,0xA6A3,0xA6A4,0xA6A5,0xA6A6,0xA6A7,0xA6A8,0xA6A9,0xA6AA,0xA6AB,0xA6AC,0xA6AD,0xA6AE,0xA6AF, + 0xA6B0,0xA6B1,0xA6B2,0xA6B3,0xA6B4,0xA6B5,0xA6B6,0xA6B7,0xA6B8,0xA6B9,0xA6BA,0xA6BB,0xA6BC,0xA6BD,0xA6BE,0xA6BF, + 0xA6C0,0xA6C1,0xA6C2,0xA6C3,0xA6C4,0xA6C5,0xA6C6,0xA6C7,0xA6C8,0xA6C9,0xA6CA,0xA6CB,0xA6CC,0xA6CD,0xA6CE,0xA6CF, + 0xA6D0,0xA6D1,0xA6D2,0xA6D3,0xA6D4,0xA6D5,0xA6D6,0xA6D7,0xA6D8,0xA6D9,0xA6DA,0xA6DB,0xA6DC,0xA6DD,0xA6DE,0xA6DF, + 0xA6E0,0xA6E1,0xA6E2,0xA6E3,0xA6E4,0xA6E5,0xA6E6,0xA6E7,0xA6E8,0xA6E9,0xA6EA,0xA6EB,0xA6EC,0xA6ED,0xA6EE,0xA6EF, + 0xA6F0,0xA6F1,0xA6F2,0xA6F3,0xA6F4,0xA6F5,0xA6F6,0xA6F7,0xA6F8,0xA6F9,0xA6FA,0xA6FB,0xA6FC,0xA6FD,0xA6FE,0xA6FF, + 0xA700,0xA701,0xA702,0xA703,0xA704,0xA705,0xA706,0xA707,0xA708,0xA709,0xA70A,0xA70B,0xA70C,0xA70D,0xA70E,0xA70F, + 0xA710,0xA711,0xA712,0xA713,0xA714,0xA715,0xA716,0xA717,0xA718,0xA719,0xA71A,0xA71B,0xA71C,0xA71D,0xA71E,0xA71F, + 0xA720,0xA721,0xA722,0xA723,0xA724,0xA725,0xA726,0xA727,0xA728,0xA729,0xA72A,0xA72B,0xA72C,0xA72D,0xA72E,0xA72F, + 0xA730,0xA731,0xA732,0xA733,0xA734,0xA735,0xA736,0xA737,0xA738,0xA739,0xA73A,0xA73B,0xA73C,0xA73D,0xA73E,0xA73F, + 0xA740,0xA741,0xA742,0xA743,0xA744,0xA745,0xA746,0xA747,0xA748,0xA749,0xA74A,0xA74B,0xA74C,0xA74D,0xA74E,0xA74F, + 0xA750,0xA751,0xA752,0xA753,0xA754,0xA755,0xA756,0xA757,0xA758,0xA759,0xA75A,0xA75B,0xA75C,0xA75D,0xA75E,0xA75F, + 0xA760,0xA761,0xA762,0xA763,0xA764,0xA765,0xA766,0xA767,0xA768,0xA769,0xA76A,0xA76B,0xA76C,0xA76D,0xA76E,0xA76F, + 0xA770,0xA771,0xA772,0xA773,0xA774,0xA775,0xA776,0xA777,0xA778,0xA779,0xA77A,0xA77B,0xA77C,0xA77D,0xA77E,0xA77F, + 0xA780,0xA781,0xA782,0xA783,0xA784,0xA785,0xA786,0xA787,0xA788,0xA789,0xA78A,0xA78B,0xA78C,0xA78D,0xA78E,0xA78F, + 0xA790,0xA791,0xA792,0xA793,0xA794,0xA795,0xA796,0xA797,0xA798,0xA799,0xA79A,0xA79B,0xA79C,0xA79D,0xA79E,0xA79F, + 0xA7A0,0xA7A1,0xA7A2,0xA7A3,0xA7A4,0xA7A5,0xA7A6,0xA7A7,0xA7A8,0xA7A9,0xA7AA,0xA7AB,0xA7AC,0xA7AD,0xA7AE,0xA7AF, + 0xA7B0,0xA7B1,0xA7B2,0xA7B3,0xA7B4,0xA7B5,0xA7B6,0xA7B7,0xA7B8,0xA7B9,0xA7BA,0xA7BB,0xA7BC,0xA7BD,0xA7BE,0xA7BF, + 0xA7C0,0xA7C1,0xA7C2,0xA7C3,0xA7C4,0xA7C5,0xA7C6,0xA7C7,0xA7C8,0xA7C9,0xA7CA,0xA7CB,0xA7CC,0xA7CD,0xA7CE,0xA7CF, + 0xA7D0,0xA7D1,0xA7D2,0xA7D3,0xA7D4,0xA7D5,0xA7D6,0xA7D7,0xA7D8,0xA7D9,0xA7DA,0xA7DB,0xA7DC,0xA7DD,0xA7DE,0xA7DF, + 0xA7E0,0xA7E1,0xA7E2,0xA7E3,0xA7E4,0xA7E5,0xA7E6,0xA7E7,0xA7E8,0xA7E9,0xA7EA,0xA7EB,0xA7EC,0xA7ED,0xA7EE,0xA7EF, + 0xA7F0,0xA7F1,0xA7F2,0xA7F3,0xA7F4,0xA7F5,0xA7F6,0xA7F7,0xA7F8,0xA7F9,0xA7FA,0xA7FB,0xA7FC,0xA7FD,0xA7FE,0xA7FF, + 0xA800,0xA801,0xA802,0xA803,0xA804,0xA805,0xA806,0xA807,0xA808,0xA809,0xA80A,0xA80B,0xA80C,0xA80D,0xA80E,0xA80F, + 0xA810,0xA811,0xA812,0xA813,0xA814,0xA815,0xA816,0xA817,0xA818,0xA819,0xA81A,0xA81B,0xA81C,0xA81D,0xA81E,0xA81F, + 0xA820,0xA821,0xA822,0xA823,0xA824,0xA825,0xA826,0xA827,0xA828,0xA829,0xA82A,0xA82B,0xA82C,0xA82D,0xA82E,0xA82F, + 0xA830,0xA831,0xA832,0xA833,0xA834,0xA835,0xA836,0xA837,0xA838,0xA839,0xA83A,0xA83B,0xA83C,0xA83D,0xA83E,0xA83F, + 0xA840,0xA841,0xA842,0xA843,0xA844,0xA845,0xA846,0xA847,0xA848,0xA849,0xA84A,0xA84B,0xA84C,0xA84D,0xA84E,0xA84F, + 0xA850,0xA851,0xA852,0xA853,0xA854,0xA855,0xA856,0xA857,0xA858,0xA859,0xA85A,0xA85B,0xA85C,0xA85D,0xA85E,0xA85F, + 0xA860,0xA861,0xA862,0xA863,0xA864,0xA865,0xA866,0xA867,0xA868,0xA869,0xA86A,0xA86B,0xA86C,0xA86D,0xA86E,0xA86F, + 0xA870,0xA871,0xA872,0xA873,0xA874,0xA875,0xA876,0xA877,0xA878,0xA879,0xA87A,0xA87B,0xA87C,0xA87D,0xA87E,0xA87F, + 0xA880,0xA881,0xA882,0xA883,0xA884,0xA885,0xA886,0xA887,0xA888,0xA889,0xA88A,0xA88B,0xA88C,0xA88D,0xA88E,0xA88F, + 0xA890,0xA891,0xA892,0xA893,0xA894,0xA895,0xA896,0xA897,0xA898,0xA899,0xA89A,0xA89B,0xA89C,0xA89D,0xA89E,0xA89F, + 0xA8A0,0xA8A1,0xA8A2,0xA8A3,0xA8A4,0xA8A5,0xA8A6,0xA8A7,0xA8A8,0xA8A9,0xA8AA,0xA8AB,0xA8AC,0xA8AD,0xA8AE,0xA8AF, + 0xA8B0,0xA8B1,0xA8B2,0xA8B3,0xA8B4,0xA8B5,0xA8B6,0xA8B7,0xA8B8,0xA8B9,0xA8BA,0xA8BB,0xA8BC,0xA8BD,0xA8BE,0xA8BF, + 0xA8C0,0xA8C1,0xA8C2,0xA8C3,0xA8C4,0xA8C5,0xA8C6,0xA8C7,0xA8C8,0xA8C9,0xA8CA,0xA8CB,0xA8CC,0xA8CD,0xA8CE,0xA8CF, + 0xA8D0,0xA8D1,0xA8D2,0xA8D3,0xA8D4,0xA8D5,0xA8D6,0xA8D7,0xA8D8,0xA8D9,0xA8DA,0xA8DB,0xA8DC,0xA8DD,0xA8DE,0xA8DF, + 0xA8E0,0xA8E1,0xA8E2,0xA8E3,0xA8E4,0xA8E5,0xA8E6,0xA8E7,0xA8E8,0xA8E9,0xA8EA,0xA8EB,0xA8EC,0xA8ED,0xA8EE,0xA8EF, + 0xA8F0,0xA8F1,0xA8F2,0xA8F3,0xA8F4,0xA8F5,0xA8F6,0xA8F7,0xA8F8,0xA8F9,0xA8FA,0xA8FB,0xA8FC,0xA8FD,0xA8FE,0xA8FF, + 0xA900,0xA901,0xA902,0xA903,0xA904,0xA905,0xA906,0xA907,0xA908,0xA909,0xA90A,0xA90B,0xA90C,0xA90D,0xA90E,0xA90F, + 0xA910,0xA911,0xA912,0xA913,0xA914,0xA915,0xA916,0xA917,0xA918,0xA919,0xA91A,0xA91B,0xA91C,0xA91D,0xA91E,0xA91F, + 0xA920,0xA921,0xA922,0xA923,0xA924,0xA925,0xA926,0xA927,0xA928,0xA929,0xA92A,0xA92B,0xA92C,0xA92D,0xA92E,0xA92F, + 0xA930,0xA931,0xA932,0xA933,0xA934,0xA935,0xA936,0xA937,0xA938,0xA939,0xA93A,0xA93B,0xA93C,0xA93D,0xA93E,0xA93F, + 0xA940,0xA941,0xA942,0xA943,0xA944,0xA945,0xA946,0xA947,0xA948,0xA949,0xA94A,0xA94B,0xA94C,0xA94D,0xA94E,0xA94F, + 0xA950,0xA951,0xA952,0xA953,0xA954,0xA955,0xA956,0xA957,0xA958,0xA959,0xA95A,0xA95B,0xA95C,0xA95D,0xA95E,0xA95F, + 0xA960,0xA961,0xA962,0xA963,0xA964,0xA965,0xA966,0xA967,0xA968,0xA969,0xA96A,0xA96B,0xA96C,0xA96D,0xA96E,0xA96F, + 0xA970,0xA971,0xA972,0xA973,0xA974,0xA975,0xA976,0xA977,0xA978,0xA979,0xA97A,0xA97B,0xA97C,0xA97D,0xA97E,0xA97F, + 0xA980,0xA981,0xA982,0xA983,0xA984,0xA985,0xA986,0xA987,0xA988,0xA989,0xA98A,0xA98B,0xA98C,0xA98D,0xA98E,0xA98F, + 0xA990,0xA991,0xA992,0xA993,0xA994,0xA995,0xA996,0xA997,0xA998,0xA999,0xA99A,0xA99B,0xA99C,0xA99D,0xA99E,0xA99F, + 0xA9A0,0xA9A1,0xA9A2,0xA9A3,0xA9A4,0xA9A5,0xA9A6,0xA9A7,0xA9A8,0xA9A9,0xA9AA,0xA9AB,0xA9AC,0xA9AD,0xA9AE,0xA9AF, + 0xA9B0,0xA9B1,0xA9B2,0xA9B3,0xA9B4,0xA9B5,0xA9B6,0xA9B7,0xA9B8,0xA9B9,0xA9BA,0xA9BB,0xA9BC,0xA9BD,0xA9BE,0xA9BF, + 0xA9C0,0xA9C1,0xA9C2,0xA9C3,0xA9C4,0xA9C5,0xA9C6,0xA9C7,0xA9C8,0xA9C9,0xA9CA,0xA9CB,0xA9CC,0xA9CD,0xA9CE,0xA9CF, + 0xA9D0,0xA9D1,0xA9D2,0xA9D3,0xA9D4,0xA9D5,0xA9D6,0xA9D7,0xA9D8,0xA9D9,0xA9DA,0xA9DB,0xA9DC,0xA9DD,0xA9DE,0xA9DF, + 0xA9E0,0xA9E1,0xA9E2,0xA9E3,0xA9E4,0xA9E5,0xA9E6,0xA9E7,0xA9E8,0xA9E9,0xA9EA,0xA9EB,0xA9EC,0xA9ED,0xA9EE,0xA9EF, + 0xA9F0,0xA9F1,0xA9F2,0xA9F3,0xA9F4,0xA9F5,0xA9F6,0xA9F7,0xA9F8,0xA9F9,0xA9FA,0xA9FB,0xA9FC,0xA9FD,0xA9FE,0xA9FF, + 0xAA00,0xAA01,0xAA02,0xAA03,0xAA04,0xAA05,0xAA06,0xAA07,0xAA08,0xAA09,0xAA0A,0xAA0B,0xAA0C,0xAA0D,0xAA0E,0xAA0F, + 0xAA10,0xAA11,0xAA12,0xAA13,0xAA14,0xAA15,0xAA16,0xAA17,0xAA18,0xAA19,0xAA1A,0xAA1B,0xAA1C,0xAA1D,0xAA1E,0xAA1F, + 0xAA20,0xAA21,0xAA22,0xAA23,0xAA24,0xAA25,0xAA26,0xAA27,0xAA28,0xAA29,0xAA2A,0xAA2B,0xAA2C,0xAA2D,0xAA2E,0xAA2F, + 0xAA30,0xAA31,0xAA32,0xAA33,0xAA34,0xAA35,0xAA36,0xAA37,0xAA38,0xAA39,0xAA3A,0xAA3B,0xAA3C,0xAA3D,0xAA3E,0xAA3F, + 0xAA40,0xAA41,0xAA42,0xAA43,0xAA44,0xAA45,0xAA46,0xAA47,0xAA48,0xAA49,0xAA4A,0xAA4B,0xAA4C,0xAA4D,0xAA4E,0xAA4F, + 0xAA50,0xAA51,0xAA52,0xAA53,0xAA54,0xAA55,0xAA56,0xAA57,0xAA58,0xAA59,0xAA5A,0xAA5B,0xAA5C,0xAA5D,0xAA5E,0xAA5F, + 0xAA60,0xAA61,0xAA62,0xAA63,0xAA64,0xAA65,0xAA66,0xAA67,0xAA68,0xAA69,0xAA6A,0xAA6B,0xAA6C,0xAA6D,0xAA6E,0xAA6F, + 0xAA70,0xAA71,0xAA72,0xAA73,0xAA74,0xAA75,0xAA76,0xAA77,0xAA78,0xAA79,0xAA7A,0xAA7B,0xAA7C,0xAA7D,0xAA7E,0xAA7F, + 0xAA80,0xAA81,0xAA82,0xAA83,0xAA84,0xAA85,0xAA86,0xAA87,0xAA88,0xAA89,0xAA8A,0xAA8B,0xAA8C,0xAA8D,0xAA8E,0xAA8F, + 0xAA90,0xAA91,0xAA92,0xAA93,0xAA94,0xAA95,0xAA96,0xAA97,0xAA98,0xAA99,0xAA9A,0xAA9B,0xAA9C,0xAA9D,0xAA9E,0xAA9F, + 0xAAA0,0xAAA1,0xAAA2,0xAAA3,0xAAA4,0xAAA5,0xAAA6,0xAAA7,0xAAA8,0xAAA9,0xAAAA,0xAAAB,0xAAAC,0xAAAD,0xAAAE,0xAAAF, + 0xAAB0,0xAAB1,0xAAB2,0xAAB3,0xAAB4,0xAAB5,0xAAB6,0xAAB7,0xAAB8,0xAAB9,0xAABA,0xAABB,0xAABC,0xAABD,0xAABE,0xAABF, + 0xAAC0,0xAAC1,0xAAC2,0xAAC3,0xAAC4,0xAAC5,0xAAC6,0xAAC7,0xAAC8,0xAAC9,0xAACA,0xAACB,0xAACC,0xAACD,0xAACE,0xAACF, + 0xAAD0,0xAAD1,0xAAD2,0xAAD3,0xAAD4,0xAAD5,0xAAD6,0xAAD7,0xAAD8,0xAAD9,0xAADA,0xAADB,0xAADC,0xAADD,0xAADE,0xAADF, + 0xAAE0,0xAAE1,0xAAE2,0xAAE3,0xAAE4,0xAAE5,0xAAE6,0xAAE7,0xAAE8,0xAAE9,0xAAEA,0xAAEB,0xAAEC,0xAAED,0xAAEE,0xAAEF, + 0xAAF0,0xAAF1,0xAAF2,0xAAF3,0xAAF4,0xAAF5,0xAAF6,0xAAF7,0xAAF8,0xAAF9,0xAAFA,0xAAFB,0xAAFC,0xAAFD,0xAAFE,0xAAFF, + 0xAB00,0xAB01,0xAB02,0xAB03,0xAB04,0xAB05,0xAB06,0xAB07,0xAB08,0xAB09,0xAB0A,0xAB0B,0xAB0C,0xAB0D,0xAB0E,0xAB0F, + 0xAB10,0xAB11,0xAB12,0xAB13,0xAB14,0xAB15,0xAB16,0xAB17,0xAB18,0xAB19,0xAB1A,0xAB1B,0xAB1C,0xAB1D,0xAB1E,0xAB1F, + 0xAB20,0xAB21,0xAB22,0xAB23,0xAB24,0xAB25,0xAB26,0xAB27,0xAB28,0xAB29,0xAB2A,0xAB2B,0xAB2C,0xAB2D,0xAB2E,0xAB2F, + 0xAB30,0xAB31,0xAB32,0xAB33,0xAB34,0xAB35,0xAB36,0xAB37,0xAB38,0xAB39,0xAB3A,0xAB3B,0xAB3C,0xAB3D,0xAB3E,0xAB3F, + 0xAB40,0xAB41,0xAB42,0xAB43,0xAB44,0xAB45,0xAB46,0xAB47,0xAB48,0xAB49,0xAB4A,0xAB4B,0xAB4C,0xAB4D,0xAB4E,0xAB4F, + 0xAB50,0xAB51,0xAB52,0xAB53,0xAB54,0xAB55,0xAB56,0xAB57,0xAB58,0xAB59,0xAB5A,0xAB5B,0xAB5C,0xAB5D,0xAB5E,0xAB5F, + 0xAB60,0xAB61,0xAB62,0xAB63,0xAB64,0xAB65,0xAB66,0xAB67,0xAB68,0xAB69,0xAB6A,0xAB6B,0xAB6C,0xAB6D,0xAB6E,0xAB6F, + 0xAB70,0xAB71,0xAB72,0xAB73,0xAB74,0xAB75,0xAB76,0xAB77,0xAB78,0xAB79,0xAB7A,0xAB7B,0xAB7C,0xAB7D,0xAB7E,0xAB7F, + 0xAB80,0xAB81,0xAB82,0xAB83,0xAB84,0xAB85,0xAB86,0xAB87,0xAB88,0xAB89,0xAB8A,0xAB8B,0xAB8C,0xAB8D,0xAB8E,0xAB8F, + 0xAB90,0xAB91,0xAB92,0xAB93,0xAB94,0xAB95,0xAB96,0xAB97,0xAB98,0xAB99,0xAB9A,0xAB9B,0xAB9C,0xAB9D,0xAB9E,0xAB9F, + 0xABA0,0xABA1,0xABA2,0xABA3,0xABA4,0xABA5,0xABA6,0xABA7,0xABA8,0xABA9,0xABAA,0xABAB,0xABAC,0xABAD,0xABAE,0xABAF, + 0xABB0,0xABB1,0xABB2,0xABB3,0xABB4,0xABB5,0xABB6,0xABB7,0xABB8,0xABB9,0xABBA,0xABBB,0xABBC,0xABBD,0xABBE,0xABBF, + 0xABC0,0xABC1,0xABC2,0xABC3,0xABC4,0xABC5,0xABC6,0xABC7,0xABC8,0xABC9,0xABCA,0xABCB,0xABCC,0xABCD,0xABCE,0xABCF, + 0xABD0,0xABD1,0xABD2,0xABD3,0xABD4,0xABD5,0xABD6,0xABD7,0xABD8,0xABD9,0xABDA,0xABDB,0xABDC,0xABDD,0xABDE,0xABDF, + 0xABE0,0xABE1,0xABE2,0xABE3,0xABE4,0xABE5,0xABE6,0xABE7,0xABE8,0xABE9,0xABEA,0xABEB,0xABEC,0xABED,0xABEE,0xABEF, + 0xABF0,0xABF1,0xABF2,0xABF3,0xABF4,0xABF5,0xABF6,0xABF7,0xABF8,0xABF9,0xABFA,0xABFB,0xABFC,0xABFD,0xABFE,0xABFF, + 0xAC00,0xAC01,0xAC02,0xAC03,0xAC04,0xAC05,0xAC06,0xAC07,0xAC08,0xAC09,0xAC0A,0xAC0B,0xAC0C,0xAC0D,0xAC0E,0xAC0F, + 0xAC10,0xAC11,0xAC12,0xAC13,0xAC14,0xAC15,0xAC16,0xAC17,0xAC18,0xAC19,0xAC1A,0xAC1B,0xAC1C,0xAC1D,0xAC1E,0xAC1F, + 0xAC20,0xAC21,0xAC22,0xAC23,0xAC24,0xAC25,0xAC26,0xAC27,0xAC28,0xAC29,0xAC2A,0xAC2B,0xAC2C,0xAC2D,0xAC2E,0xAC2F, + 0xAC30,0xAC31,0xAC32,0xAC33,0xAC34,0xAC35,0xAC36,0xAC37,0xAC38,0xAC39,0xAC3A,0xAC3B,0xAC3C,0xAC3D,0xAC3E,0xAC3F, + 0xAC40,0xAC41,0xAC42,0xAC43,0xAC44,0xAC45,0xAC46,0xAC47,0xAC48,0xAC49,0xAC4A,0xAC4B,0xAC4C,0xAC4D,0xAC4E,0xAC4F, + 0xAC50,0xAC51,0xAC52,0xAC53,0xAC54,0xAC55,0xAC56,0xAC57,0xAC58,0xAC59,0xAC5A,0xAC5B,0xAC5C,0xAC5D,0xAC5E,0xAC5F, + 0xAC60,0xAC61,0xAC62,0xAC63,0xAC64,0xAC65,0xAC66,0xAC67,0xAC68,0xAC69,0xAC6A,0xAC6B,0xAC6C,0xAC6D,0xAC6E,0xAC6F, + 0xAC70,0xAC71,0xAC72,0xAC73,0xAC74,0xAC75,0xAC76,0xAC77,0xAC78,0xAC79,0xAC7A,0xAC7B,0xAC7C,0xAC7D,0xAC7E,0xAC7F, + 0xAC80,0xAC81,0xAC82,0xAC83,0xAC84,0xAC85,0xAC86,0xAC87,0xAC88,0xAC89,0xAC8A,0xAC8B,0xAC8C,0xAC8D,0xAC8E,0xAC8F, + 0xAC90,0xAC91,0xAC92,0xAC93,0xAC94,0xAC95,0xAC96,0xAC97,0xAC98,0xAC99,0xAC9A,0xAC9B,0xAC9C,0xAC9D,0xAC9E,0xAC9F, + 0xACA0,0xACA1,0xACA2,0xACA3,0xACA4,0xACA5,0xACA6,0xACA7,0xACA8,0xACA9,0xACAA,0xACAB,0xACAC,0xACAD,0xACAE,0xACAF, + 0xACB0,0xACB1,0xACB2,0xACB3,0xACB4,0xACB5,0xACB6,0xACB7,0xACB8,0xACB9,0xACBA,0xACBB,0xACBC,0xACBD,0xACBE,0xACBF, + 0xACC0,0xACC1,0xACC2,0xACC3,0xACC4,0xACC5,0xACC6,0xACC7,0xACC8,0xACC9,0xACCA,0xACCB,0xACCC,0xACCD,0xACCE,0xACCF, + 0xACD0,0xACD1,0xACD2,0xACD3,0xACD4,0xACD5,0xACD6,0xACD7,0xACD8,0xACD9,0xACDA,0xACDB,0xACDC,0xACDD,0xACDE,0xACDF, + 0xACE0,0xACE1,0xACE2,0xACE3,0xACE4,0xACE5,0xACE6,0xACE7,0xACE8,0xACE9,0xACEA,0xACEB,0xACEC,0xACED,0xACEE,0xACEF, + 0xACF0,0xACF1,0xACF2,0xACF3,0xACF4,0xACF5,0xACF6,0xACF7,0xACF8,0xACF9,0xACFA,0xACFB,0xACFC,0xACFD,0xACFE,0xACFF, + 0xAD00,0xAD01,0xAD02,0xAD03,0xAD04,0xAD05,0xAD06,0xAD07,0xAD08,0xAD09,0xAD0A,0xAD0B,0xAD0C,0xAD0D,0xAD0E,0xAD0F, + 0xAD10,0xAD11,0xAD12,0xAD13,0xAD14,0xAD15,0xAD16,0xAD17,0xAD18,0xAD19,0xAD1A,0xAD1B,0xAD1C,0xAD1D,0xAD1E,0xAD1F, + 0xAD20,0xAD21,0xAD22,0xAD23,0xAD24,0xAD25,0xAD26,0xAD27,0xAD28,0xAD29,0xAD2A,0xAD2B,0xAD2C,0xAD2D,0xAD2E,0xAD2F, + 0xAD30,0xAD31,0xAD32,0xAD33,0xAD34,0xAD35,0xAD36,0xAD37,0xAD38,0xAD39,0xAD3A,0xAD3B,0xAD3C,0xAD3D,0xAD3E,0xAD3F, + 0xAD40,0xAD41,0xAD42,0xAD43,0xAD44,0xAD45,0xAD46,0xAD47,0xAD48,0xAD49,0xAD4A,0xAD4B,0xAD4C,0xAD4D,0xAD4E,0xAD4F, + 0xAD50,0xAD51,0xAD52,0xAD53,0xAD54,0xAD55,0xAD56,0xAD57,0xAD58,0xAD59,0xAD5A,0xAD5B,0xAD5C,0xAD5D,0xAD5E,0xAD5F, + 0xAD60,0xAD61,0xAD62,0xAD63,0xAD64,0xAD65,0xAD66,0xAD67,0xAD68,0xAD69,0xAD6A,0xAD6B,0xAD6C,0xAD6D,0xAD6E,0xAD6F, + 0xAD70,0xAD71,0xAD72,0xAD73,0xAD74,0xAD75,0xAD76,0xAD77,0xAD78,0xAD79,0xAD7A,0xAD7B,0xAD7C,0xAD7D,0xAD7E,0xAD7F, + 0xAD80,0xAD81,0xAD82,0xAD83,0xAD84,0xAD85,0xAD86,0xAD87,0xAD88,0xAD89,0xAD8A,0xAD8B,0xAD8C,0xAD8D,0xAD8E,0xAD8F, + 0xAD90,0xAD91,0xAD92,0xAD93,0xAD94,0xAD95,0xAD96,0xAD97,0xAD98,0xAD99,0xAD9A,0xAD9B,0xAD9C,0xAD9D,0xAD9E,0xAD9F, + 0xADA0,0xADA1,0xADA2,0xADA3,0xADA4,0xADA5,0xADA6,0xADA7,0xADA8,0xADA9,0xADAA,0xADAB,0xADAC,0xADAD,0xADAE,0xADAF, + 0xADB0,0xADB1,0xADB2,0xADB3,0xADB4,0xADB5,0xADB6,0xADB7,0xADB8,0xADB9,0xADBA,0xADBB,0xADBC,0xADBD,0xADBE,0xADBF, + 0xADC0,0xADC1,0xADC2,0xADC3,0xADC4,0xADC5,0xADC6,0xADC7,0xADC8,0xADC9,0xADCA,0xADCB,0xADCC,0xADCD,0xADCE,0xADCF, + 0xADD0,0xADD1,0xADD2,0xADD3,0xADD4,0xADD5,0xADD6,0xADD7,0xADD8,0xADD9,0xADDA,0xADDB,0xADDC,0xADDD,0xADDE,0xADDF, + 0xADE0,0xADE1,0xADE2,0xADE3,0xADE4,0xADE5,0xADE6,0xADE7,0xADE8,0xADE9,0xADEA,0xADEB,0xADEC,0xADED,0xADEE,0xADEF, + 0xADF0,0xADF1,0xADF2,0xADF3,0xADF4,0xADF5,0xADF6,0xADF7,0xADF8,0xADF9,0xADFA,0xADFB,0xADFC,0xADFD,0xADFE,0xADFF, + 0xAE00,0xAE01,0xAE02,0xAE03,0xAE04,0xAE05,0xAE06,0xAE07,0xAE08,0xAE09,0xAE0A,0xAE0B,0xAE0C,0xAE0D,0xAE0E,0xAE0F, + 0xAE10,0xAE11,0xAE12,0xAE13,0xAE14,0xAE15,0xAE16,0xAE17,0xAE18,0xAE19,0xAE1A,0xAE1B,0xAE1C,0xAE1D,0xAE1E,0xAE1F, + 0xAE20,0xAE21,0xAE22,0xAE23,0xAE24,0xAE25,0xAE26,0xAE27,0xAE28,0xAE29,0xAE2A,0xAE2B,0xAE2C,0xAE2D,0xAE2E,0xAE2F, + 0xAE30,0xAE31,0xAE32,0xAE33,0xAE34,0xAE35,0xAE36,0xAE37,0xAE38,0xAE39,0xAE3A,0xAE3B,0xAE3C,0xAE3D,0xAE3E,0xAE3F, + 0xAE40,0xAE41,0xAE42,0xAE43,0xAE44,0xAE45,0xAE46,0xAE47,0xAE48,0xAE49,0xAE4A,0xAE4B,0xAE4C,0xAE4D,0xAE4E,0xAE4F, + 0xAE50,0xAE51,0xAE52,0xAE53,0xAE54,0xAE55,0xAE56,0xAE57,0xAE58,0xAE59,0xAE5A,0xAE5B,0xAE5C,0xAE5D,0xAE5E,0xAE5F, + 0xAE60,0xAE61,0xAE62,0xAE63,0xAE64,0xAE65,0xAE66,0xAE67,0xAE68,0xAE69,0xAE6A,0xAE6B,0xAE6C,0xAE6D,0xAE6E,0xAE6F, + 0xAE70,0xAE71,0xAE72,0xAE73,0xAE74,0xAE75,0xAE76,0xAE77,0xAE78,0xAE79,0xAE7A,0xAE7B,0xAE7C,0xAE7D,0xAE7E,0xAE7F, + 0xAE80,0xAE81,0xAE82,0xAE83,0xAE84,0xAE85,0xAE86,0xAE87,0xAE88,0xAE89,0xAE8A,0xAE8B,0xAE8C,0xAE8D,0xAE8E,0xAE8F, + 0xAE90,0xAE91,0xAE92,0xAE93,0xAE94,0xAE95,0xAE96,0xAE97,0xAE98,0xAE99,0xAE9A,0xAE9B,0xAE9C,0xAE9D,0xAE9E,0xAE9F, + 0xAEA0,0xAEA1,0xAEA2,0xAEA3,0xAEA4,0xAEA5,0xAEA6,0xAEA7,0xAEA8,0xAEA9,0xAEAA,0xAEAB,0xAEAC,0xAEAD,0xAEAE,0xAEAF, + 0xAEB0,0xAEB1,0xAEB2,0xAEB3,0xAEB4,0xAEB5,0xAEB6,0xAEB7,0xAEB8,0xAEB9,0xAEBA,0xAEBB,0xAEBC,0xAEBD,0xAEBE,0xAEBF, + 0xAEC0,0xAEC1,0xAEC2,0xAEC3,0xAEC4,0xAEC5,0xAEC6,0xAEC7,0xAEC8,0xAEC9,0xAECA,0xAECB,0xAECC,0xAECD,0xAECE,0xAECF, + 0xAED0,0xAED1,0xAED2,0xAED3,0xAED4,0xAED5,0xAED6,0xAED7,0xAED8,0xAED9,0xAEDA,0xAEDB,0xAEDC,0xAEDD,0xAEDE,0xAEDF, + 0xAEE0,0xAEE1,0xAEE2,0xAEE3,0xAEE4,0xAEE5,0xAEE6,0xAEE7,0xAEE8,0xAEE9,0xAEEA,0xAEEB,0xAEEC,0xAEED,0xAEEE,0xAEEF, + 0xAEF0,0xAEF1,0xAEF2,0xAEF3,0xAEF4,0xAEF5,0xAEF6,0xAEF7,0xAEF8,0xAEF9,0xAEFA,0xAEFB,0xAEFC,0xAEFD,0xAEFE,0xAEFF, + 0xAF00,0xAF01,0xAF02,0xAF03,0xAF04,0xAF05,0xAF06,0xAF07,0xAF08,0xAF09,0xAF0A,0xAF0B,0xAF0C,0xAF0D,0xAF0E,0xAF0F, + 0xAF10,0xAF11,0xAF12,0xAF13,0xAF14,0xAF15,0xAF16,0xAF17,0xAF18,0xAF19,0xAF1A,0xAF1B,0xAF1C,0xAF1D,0xAF1E,0xAF1F, + 0xAF20,0xAF21,0xAF22,0xAF23,0xAF24,0xAF25,0xAF26,0xAF27,0xAF28,0xAF29,0xAF2A,0xAF2B,0xAF2C,0xAF2D,0xAF2E,0xAF2F, + 0xAF30,0xAF31,0xAF32,0xAF33,0xAF34,0xAF35,0xAF36,0xAF37,0xAF38,0xAF39,0xAF3A,0xAF3B,0xAF3C,0xAF3D,0xAF3E,0xAF3F, + 0xAF40,0xAF41,0xAF42,0xAF43,0xAF44,0xAF45,0xAF46,0xAF47,0xAF48,0xAF49,0xAF4A,0xAF4B,0xAF4C,0xAF4D,0xAF4E,0xAF4F, + 0xAF50,0xAF51,0xAF52,0xAF53,0xAF54,0xAF55,0xAF56,0xAF57,0xAF58,0xAF59,0xAF5A,0xAF5B,0xAF5C,0xAF5D,0xAF5E,0xAF5F, + 0xAF60,0xAF61,0xAF62,0xAF63,0xAF64,0xAF65,0xAF66,0xAF67,0xAF68,0xAF69,0xAF6A,0xAF6B,0xAF6C,0xAF6D,0xAF6E,0xAF6F, + 0xAF70,0xAF71,0xAF72,0xAF73,0xAF74,0xAF75,0xAF76,0xAF77,0xAF78,0xAF79,0xAF7A,0xAF7B,0xAF7C,0xAF7D,0xAF7E,0xAF7F, + 0xAF80,0xAF81,0xAF82,0xAF83,0xAF84,0xAF85,0xAF86,0xAF87,0xAF88,0xAF89,0xAF8A,0xAF8B,0xAF8C,0xAF8D,0xAF8E,0xAF8F, + 0xAF90,0xAF91,0xAF92,0xAF93,0xAF94,0xAF95,0xAF96,0xAF97,0xAF98,0xAF99,0xAF9A,0xAF9B,0xAF9C,0xAF9D,0xAF9E,0xAF9F, + 0xAFA0,0xAFA1,0xAFA2,0xAFA3,0xAFA4,0xAFA5,0xAFA6,0xAFA7,0xAFA8,0xAFA9,0xAFAA,0xAFAB,0xAFAC,0xAFAD,0xAFAE,0xAFAF, + 0xAFB0,0xAFB1,0xAFB2,0xAFB3,0xAFB4,0xAFB5,0xAFB6,0xAFB7,0xAFB8,0xAFB9,0xAFBA,0xAFBB,0xAFBC,0xAFBD,0xAFBE,0xAFBF, + 0xAFC0,0xAFC1,0xAFC2,0xAFC3,0xAFC4,0xAFC5,0xAFC6,0xAFC7,0xAFC8,0xAFC9,0xAFCA,0xAFCB,0xAFCC,0xAFCD,0xAFCE,0xAFCF, + 0xAFD0,0xAFD1,0xAFD2,0xAFD3,0xAFD4,0xAFD5,0xAFD6,0xAFD7,0xAFD8,0xAFD9,0xAFDA,0xAFDB,0xAFDC,0xAFDD,0xAFDE,0xAFDF, + 0xAFE0,0xAFE1,0xAFE2,0xAFE3,0xAFE4,0xAFE5,0xAFE6,0xAFE7,0xAFE8,0xAFE9,0xAFEA,0xAFEB,0xAFEC,0xAFED,0xAFEE,0xAFEF, + 0xAFF0,0xAFF1,0xAFF2,0xAFF3,0xAFF4,0xAFF5,0xAFF6,0xAFF7,0xAFF8,0xAFF9,0xAFFA,0xAFFB,0xAFFC,0xAFFD,0xAFFE,0xAFFF, + 0xB000,0xB001,0xB002,0xB003,0xB004,0xB005,0xB006,0xB007,0xB008,0xB009,0xB00A,0xB00B,0xB00C,0xB00D,0xB00E,0xB00F, + 0xB010,0xB011,0xB012,0xB013,0xB014,0xB015,0xB016,0xB017,0xB018,0xB019,0xB01A,0xB01B,0xB01C,0xB01D,0xB01E,0xB01F, + 0xB020,0xB021,0xB022,0xB023,0xB024,0xB025,0xB026,0xB027,0xB028,0xB029,0xB02A,0xB02B,0xB02C,0xB02D,0xB02E,0xB02F, + 0xB030,0xB031,0xB032,0xB033,0xB034,0xB035,0xB036,0xB037,0xB038,0xB039,0xB03A,0xB03B,0xB03C,0xB03D,0xB03E,0xB03F, + 0xB040,0xB041,0xB042,0xB043,0xB044,0xB045,0xB046,0xB047,0xB048,0xB049,0xB04A,0xB04B,0xB04C,0xB04D,0xB04E,0xB04F, + 0xB050,0xB051,0xB052,0xB053,0xB054,0xB055,0xB056,0xB057,0xB058,0xB059,0xB05A,0xB05B,0xB05C,0xB05D,0xB05E,0xB05F, + 0xB060,0xB061,0xB062,0xB063,0xB064,0xB065,0xB066,0xB067,0xB068,0xB069,0xB06A,0xB06B,0xB06C,0xB06D,0xB06E,0xB06F, + 0xB070,0xB071,0xB072,0xB073,0xB074,0xB075,0xB076,0xB077,0xB078,0xB079,0xB07A,0xB07B,0xB07C,0xB07D,0xB07E,0xB07F, + 0xB080,0xB081,0xB082,0xB083,0xB084,0xB085,0xB086,0xB087,0xB088,0xB089,0xB08A,0xB08B,0xB08C,0xB08D,0xB08E,0xB08F, + 0xB090,0xB091,0xB092,0xB093,0xB094,0xB095,0xB096,0xB097,0xB098,0xB099,0xB09A,0xB09B,0xB09C,0xB09D,0xB09E,0xB09F, + 0xB0A0,0xB0A1,0xB0A2,0xB0A3,0xB0A4,0xB0A5,0xB0A6,0xB0A7,0xB0A8,0xB0A9,0xB0AA,0xB0AB,0xB0AC,0xB0AD,0xB0AE,0xB0AF, + 0xB0B0,0xB0B1,0xB0B2,0xB0B3,0xB0B4,0xB0B5,0xB0B6,0xB0B7,0xB0B8,0xB0B9,0xB0BA,0xB0BB,0xB0BC,0xB0BD,0xB0BE,0xB0BF, + 0xB0C0,0xB0C1,0xB0C2,0xB0C3,0xB0C4,0xB0C5,0xB0C6,0xB0C7,0xB0C8,0xB0C9,0xB0CA,0xB0CB,0xB0CC,0xB0CD,0xB0CE,0xB0CF, + 0xB0D0,0xB0D1,0xB0D2,0xB0D3,0xB0D4,0xB0D5,0xB0D6,0xB0D7,0xB0D8,0xB0D9,0xB0DA,0xB0DB,0xB0DC,0xB0DD,0xB0DE,0xB0DF, + 0xB0E0,0xB0E1,0xB0E2,0xB0E3,0xB0E4,0xB0E5,0xB0E6,0xB0E7,0xB0E8,0xB0E9,0xB0EA,0xB0EB,0xB0EC,0xB0ED,0xB0EE,0xB0EF, + 0xB0F0,0xB0F1,0xB0F2,0xB0F3,0xB0F4,0xB0F5,0xB0F6,0xB0F7,0xB0F8,0xB0F9,0xB0FA,0xB0FB,0xB0FC,0xB0FD,0xB0FE,0xB0FF, + 0xB100,0xB101,0xB102,0xB103,0xB104,0xB105,0xB106,0xB107,0xB108,0xB109,0xB10A,0xB10B,0xB10C,0xB10D,0xB10E,0xB10F, + 0xB110,0xB111,0xB112,0xB113,0xB114,0xB115,0xB116,0xB117,0xB118,0xB119,0xB11A,0xB11B,0xB11C,0xB11D,0xB11E,0xB11F, + 0xB120,0xB121,0xB122,0xB123,0xB124,0xB125,0xB126,0xB127,0xB128,0xB129,0xB12A,0xB12B,0xB12C,0xB12D,0xB12E,0xB12F, + 0xB130,0xB131,0xB132,0xB133,0xB134,0xB135,0xB136,0xB137,0xB138,0xB139,0xB13A,0xB13B,0xB13C,0xB13D,0xB13E,0xB13F, + 0xB140,0xB141,0xB142,0xB143,0xB144,0xB145,0xB146,0xB147,0xB148,0xB149,0xB14A,0xB14B,0xB14C,0xB14D,0xB14E,0xB14F, + 0xB150,0xB151,0xB152,0xB153,0xB154,0xB155,0xB156,0xB157,0xB158,0xB159,0xB15A,0xB15B,0xB15C,0xB15D,0xB15E,0xB15F, + 0xB160,0xB161,0xB162,0xB163,0xB164,0xB165,0xB166,0xB167,0xB168,0xB169,0xB16A,0xB16B,0xB16C,0xB16D,0xB16E,0xB16F, + 0xB170,0xB171,0xB172,0xB173,0xB174,0xB175,0xB176,0xB177,0xB178,0xB179,0xB17A,0xB17B,0xB17C,0xB17D,0xB17E,0xB17F, + 0xB180,0xB181,0xB182,0xB183,0xB184,0xB185,0xB186,0xB187,0xB188,0xB189,0xB18A,0xB18B,0xB18C,0xB18D,0xB18E,0xB18F, + 0xB190,0xB191,0xB192,0xB193,0xB194,0xB195,0xB196,0xB197,0xB198,0xB199,0xB19A,0xB19B,0xB19C,0xB19D,0xB19E,0xB19F, + 0xB1A0,0xB1A1,0xB1A2,0xB1A3,0xB1A4,0xB1A5,0xB1A6,0xB1A7,0xB1A8,0xB1A9,0xB1AA,0xB1AB,0xB1AC,0xB1AD,0xB1AE,0xB1AF, + 0xB1B0,0xB1B1,0xB1B2,0xB1B3,0xB1B4,0xB1B5,0xB1B6,0xB1B7,0xB1B8,0xB1B9,0xB1BA,0xB1BB,0xB1BC,0xB1BD,0xB1BE,0xB1BF, + 0xB1C0,0xB1C1,0xB1C2,0xB1C3,0xB1C4,0xB1C5,0xB1C6,0xB1C7,0xB1C8,0xB1C9,0xB1CA,0xB1CB,0xB1CC,0xB1CD,0xB1CE,0xB1CF, + 0xB1D0,0xB1D1,0xB1D2,0xB1D3,0xB1D4,0xB1D5,0xB1D6,0xB1D7,0xB1D8,0xB1D9,0xB1DA,0xB1DB,0xB1DC,0xB1DD,0xB1DE,0xB1DF, + 0xB1E0,0xB1E1,0xB1E2,0xB1E3,0xB1E4,0xB1E5,0xB1E6,0xB1E7,0xB1E8,0xB1E9,0xB1EA,0xB1EB,0xB1EC,0xB1ED,0xB1EE,0xB1EF, + 0xB1F0,0xB1F1,0xB1F2,0xB1F3,0xB1F4,0xB1F5,0xB1F6,0xB1F7,0xB1F8,0xB1F9,0xB1FA,0xB1FB,0xB1FC,0xB1FD,0xB1FE,0xB1FF, + 0xB200,0xB201,0xB202,0xB203,0xB204,0xB205,0xB206,0xB207,0xB208,0xB209,0xB20A,0xB20B,0xB20C,0xB20D,0xB20E,0xB20F, + 0xB210,0xB211,0xB212,0xB213,0xB214,0xB215,0xB216,0xB217,0xB218,0xB219,0xB21A,0xB21B,0xB21C,0xB21D,0xB21E,0xB21F, + 0xB220,0xB221,0xB222,0xB223,0xB224,0xB225,0xB226,0xB227,0xB228,0xB229,0xB22A,0xB22B,0xB22C,0xB22D,0xB22E,0xB22F, + 0xB230,0xB231,0xB232,0xB233,0xB234,0xB235,0xB236,0xB237,0xB238,0xB239,0xB23A,0xB23B,0xB23C,0xB23D,0xB23E,0xB23F, + 0xB240,0xB241,0xB242,0xB243,0xB244,0xB245,0xB246,0xB247,0xB248,0xB249,0xB24A,0xB24B,0xB24C,0xB24D,0xB24E,0xB24F, + 0xB250,0xB251,0xB252,0xB253,0xB254,0xB255,0xB256,0xB257,0xB258,0xB259,0xB25A,0xB25B,0xB25C,0xB25D,0xB25E,0xB25F, + 0xB260,0xB261,0xB262,0xB263,0xB264,0xB265,0xB266,0xB267,0xB268,0xB269,0xB26A,0xB26B,0xB26C,0xB26D,0xB26E,0xB26F, + 0xB270,0xB271,0xB272,0xB273,0xB274,0xB275,0xB276,0xB277,0xB278,0xB279,0xB27A,0xB27B,0xB27C,0xB27D,0xB27E,0xB27F, + 0xB280,0xB281,0xB282,0xB283,0xB284,0xB285,0xB286,0xB287,0xB288,0xB289,0xB28A,0xB28B,0xB28C,0xB28D,0xB28E,0xB28F, + 0xB290,0xB291,0xB292,0xB293,0xB294,0xB295,0xB296,0xB297,0xB298,0xB299,0xB29A,0xB29B,0xB29C,0xB29D,0xB29E,0xB29F, + 0xB2A0,0xB2A1,0xB2A2,0xB2A3,0xB2A4,0xB2A5,0xB2A6,0xB2A7,0xB2A8,0xB2A9,0xB2AA,0xB2AB,0xB2AC,0xB2AD,0xB2AE,0xB2AF, + 0xB2B0,0xB2B1,0xB2B2,0xB2B3,0xB2B4,0xB2B5,0xB2B6,0xB2B7,0xB2B8,0xB2B9,0xB2BA,0xB2BB,0xB2BC,0xB2BD,0xB2BE,0xB2BF, + 0xB2C0,0xB2C1,0xB2C2,0xB2C3,0xB2C4,0xB2C5,0xB2C6,0xB2C7,0xB2C8,0xB2C9,0xB2CA,0xB2CB,0xB2CC,0xB2CD,0xB2CE,0xB2CF, + 0xB2D0,0xB2D1,0xB2D2,0xB2D3,0xB2D4,0xB2D5,0xB2D6,0xB2D7,0xB2D8,0xB2D9,0xB2DA,0xB2DB,0xB2DC,0xB2DD,0xB2DE,0xB2DF, + 0xB2E0,0xB2E1,0xB2E2,0xB2E3,0xB2E4,0xB2E5,0xB2E6,0xB2E7,0xB2E8,0xB2E9,0xB2EA,0xB2EB,0xB2EC,0xB2ED,0xB2EE,0xB2EF, + 0xB2F0,0xB2F1,0xB2F2,0xB2F3,0xB2F4,0xB2F5,0xB2F6,0xB2F7,0xB2F8,0xB2F9,0xB2FA,0xB2FB,0xB2FC,0xB2FD,0xB2FE,0xB2FF, + 0xB300,0xB301,0xB302,0xB303,0xB304,0xB305,0xB306,0xB307,0xB308,0xB309,0xB30A,0xB30B,0xB30C,0xB30D,0xB30E,0xB30F, + 0xB310,0xB311,0xB312,0xB313,0xB314,0xB315,0xB316,0xB317,0xB318,0xB319,0xB31A,0xB31B,0xB31C,0xB31D,0xB31E,0xB31F, + 0xB320,0xB321,0xB322,0xB323,0xB324,0xB325,0xB326,0xB327,0xB328,0xB329,0xB32A,0xB32B,0xB32C,0xB32D,0xB32E,0xB32F, + 0xB330,0xB331,0xB332,0xB333,0xB334,0xB335,0xB336,0xB337,0xB338,0xB339,0xB33A,0xB33B,0xB33C,0xB33D,0xB33E,0xB33F, + 0xB340,0xB341,0xB342,0xB343,0xB344,0xB345,0xB346,0xB347,0xB348,0xB349,0xB34A,0xB34B,0xB34C,0xB34D,0xB34E,0xB34F, + 0xB350,0xB351,0xB352,0xB353,0xB354,0xB355,0xB356,0xB357,0xB358,0xB359,0xB35A,0xB35B,0xB35C,0xB35D,0xB35E,0xB35F, + 0xB360,0xB361,0xB362,0xB363,0xB364,0xB365,0xB366,0xB367,0xB368,0xB369,0xB36A,0xB36B,0xB36C,0xB36D,0xB36E,0xB36F, + 0xB370,0xB371,0xB372,0xB373,0xB374,0xB375,0xB376,0xB377,0xB378,0xB379,0xB37A,0xB37B,0xB37C,0xB37D,0xB37E,0xB37F, + 0xB380,0xB381,0xB382,0xB383,0xB384,0xB385,0xB386,0xB387,0xB388,0xB389,0xB38A,0xB38B,0xB38C,0xB38D,0xB38E,0xB38F, + 0xB390,0xB391,0xB392,0xB393,0xB394,0xB395,0xB396,0xB397,0xB398,0xB399,0xB39A,0xB39B,0xB39C,0xB39D,0xB39E,0xB39F, + 0xB3A0,0xB3A1,0xB3A2,0xB3A3,0xB3A4,0xB3A5,0xB3A6,0xB3A7,0xB3A8,0xB3A9,0xB3AA,0xB3AB,0xB3AC,0xB3AD,0xB3AE,0xB3AF, + 0xB3B0,0xB3B1,0xB3B2,0xB3B3,0xB3B4,0xB3B5,0xB3B6,0xB3B7,0xB3B8,0xB3B9,0xB3BA,0xB3BB,0xB3BC,0xB3BD,0xB3BE,0xB3BF, + 0xB3C0,0xB3C1,0xB3C2,0xB3C3,0xB3C4,0xB3C5,0xB3C6,0xB3C7,0xB3C8,0xB3C9,0xB3CA,0xB3CB,0xB3CC,0xB3CD,0xB3CE,0xB3CF, + 0xB3D0,0xB3D1,0xB3D2,0xB3D3,0xB3D4,0xB3D5,0xB3D6,0xB3D7,0xB3D8,0xB3D9,0xB3DA,0xB3DB,0xB3DC,0xB3DD,0xB3DE,0xB3DF, + 0xB3E0,0xB3E1,0xB3E2,0xB3E3,0xB3E4,0xB3E5,0xB3E6,0xB3E7,0xB3E8,0xB3E9,0xB3EA,0xB3EB,0xB3EC,0xB3ED,0xB3EE,0xB3EF, + 0xB3F0,0xB3F1,0xB3F2,0xB3F3,0xB3F4,0xB3F5,0xB3F6,0xB3F7,0xB3F8,0xB3F9,0xB3FA,0xB3FB,0xB3FC,0xB3FD,0xB3FE,0xB3FF, + 0xB400,0xB401,0xB402,0xB403,0xB404,0xB405,0xB406,0xB407,0xB408,0xB409,0xB40A,0xB40B,0xB40C,0xB40D,0xB40E,0xB40F, + 0xB410,0xB411,0xB412,0xB413,0xB414,0xB415,0xB416,0xB417,0xB418,0xB419,0xB41A,0xB41B,0xB41C,0xB41D,0xB41E,0xB41F, + 0xB420,0xB421,0xB422,0xB423,0xB424,0xB425,0xB426,0xB427,0xB428,0xB429,0xB42A,0xB42B,0xB42C,0xB42D,0xB42E,0xB42F, + 0xB430,0xB431,0xB432,0xB433,0xB434,0xB435,0xB436,0xB437,0xB438,0xB439,0xB43A,0xB43B,0xB43C,0xB43D,0xB43E,0xB43F, + 0xB440,0xB441,0xB442,0xB443,0xB444,0xB445,0xB446,0xB447,0xB448,0xB449,0xB44A,0xB44B,0xB44C,0xB44D,0xB44E,0xB44F, + 0xB450,0xB451,0xB452,0xB453,0xB454,0xB455,0xB456,0xB457,0xB458,0xB459,0xB45A,0xB45B,0xB45C,0xB45D,0xB45E,0xB45F, + 0xB460,0xB461,0xB462,0xB463,0xB464,0xB465,0xB466,0xB467,0xB468,0xB469,0xB46A,0xB46B,0xB46C,0xB46D,0xB46E,0xB46F, + 0xB470,0xB471,0xB472,0xB473,0xB474,0xB475,0xB476,0xB477,0xB478,0xB479,0xB47A,0xB47B,0xB47C,0xB47D,0xB47E,0xB47F, + 0xB480,0xB481,0xB482,0xB483,0xB484,0xB485,0xB486,0xB487,0xB488,0xB489,0xB48A,0xB48B,0xB48C,0xB48D,0xB48E,0xB48F, + 0xB490,0xB491,0xB492,0xB493,0xB494,0xB495,0xB496,0xB497,0xB498,0xB499,0xB49A,0xB49B,0xB49C,0xB49D,0xB49E,0xB49F, + 0xB4A0,0xB4A1,0xB4A2,0xB4A3,0xB4A4,0xB4A5,0xB4A6,0xB4A7,0xB4A8,0xB4A9,0xB4AA,0xB4AB,0xB4AC,0xB4AD,0xB4AE,0xB4AF, + 0xB4B0,0xB4B1,0xB4B2,0xB4B3,0xB4B4,0xB4B5,0xB4B6,0xB4B7,0xB4B8,0xB4B9,0xB4BA,0xB4BB,0xB4BC,0xB4BD,0xB4BE,0xB4BF, + 0xB4C0,0xB4C1,0xB4C2,0xB4C3,0xB4C4,0xB4C5,0xB4C6,0xB4C7,0xB4C8,0xB4C9,0xB4CA,0xB4CB,0xB4CC,0xB4CD,0xB4CE,0xB4CF, + 0xB4D0,0xB4D1,0xB4D2,0xB4D3,0xB4D4,0xB4D5,0xB4D6,0xB4D7,0xB4D8,0xB4D9,0xB4DA,0xB4DB,0xB4DC,0xB4DD,0xB4DE,0xB4DF, + 0xB4E0,0xB4E1,0xB4E2,0xB4E3,0xB4E4,0xB4E5,0xB4E6,0xB4E7,0xB4E8,0xB4E9,0xB4EA,0xB4EB,0xB4EC,0xB4ED,0xB4EE,0xB4EF, + 0xB4F0,0xB4F1,0xB4F2,0xB4F3,0xB4F4,0xB4F5,0xB4F6,0xB4F7,0xB4F8,0xB4F9,0xB4FA,0xB4FB,0xB4FC,0xB4FD,0xB4FE,0xB4FF, + 0xB500,0xB501,0xB502,0xB503,0xB504,0xB505,0xB506,0xB507,0xB508,0xB509,0xB50A,0xB50B,0xB50C,0xB50D,0xB50E,0xB50F, + 0xB510,0xB511,0xB512,0xB513,0xB514,0xB515,0xB516,0xB517,0xB518,0xB519,0xB51A,0xB51B,0xB51C,0xB51D,0xB51E,0xB51F, + 0xB520,0xB521,0xB522,0xB523,0xB524,0xB525,0xB526,0xB527,0xB528,0xB529,0xB52A,0xB52B,0xB52C,0xB52D,0xB52E,0xB52F, + 0xB530,0xB531,0xB532,0xB533,0xB534,0xB535,0xB536,0xB537,0xB538,0xB539,0xB53A,0xB53B,0xB53C,0xB53D,0xB53E,0xB53F, + 0xB540,0xB541,0xB542,0xB543,0xB544,0xB545,0xB546,0xB547,0xB548,0xB549,0xB54A,0xB54B,0xB54C,0xB54D,0xB54E,0xB54F, + 0xB550,0xB551,0xB552,0xB553,0xB554,0xB555,0xB556,0xB557,0xB558,0xB559,0xB55A,0xB55B,0xB55C,0xB55D,0xB55E,0xB55F, + 0xB560,0xB561,0xB562,0xB563,0xB564,0xB565,0xB566,0xB567,0xB568,0xB569,0xB56A,0xB56B,0xB56C,0xB56D,0xB56E,0xB56F, + 0xB570,0xB571,0xB572,0xB573,0xB574,0xB575,0xB576,0xB577,0xB578,0xB579,0xB57A,0xB57B,0xB57C,0xB57D,0xB57E,0xB57F, + 0xB580,0xB581,0xB582,0xB583,0xB584,0xB585,0xB586,0xB587,0xB588,0xB589,0xB58A,0xB58B,0xB58C,0xB58D,0xB58E,0xB58F, + 0xB590,0xB591,0xB592,0xB593,0xB594,0xB595,0xB596,0xB597,0xB598,0xB599,0xB59A,0xB59B,0xB59C,0xB59D,0xB59E,0xB59F, + 0xB5A0,0xB5A1,0xB5A2,0xB5A3,0xB5A4,0xB5A5,0xB5A6,0xB5A7,0xB5A8,0xB5A9,0xB5AA,0xB5AB,0xB5AC,0xB5AD,0xB5AE,0xB5AF, + 0xB5B0,0xB5B1,0xB5B2,0xB5B3,0xB5B4,0xB5B5,0xB5B6,0xB5B7,0xB5B8,0xB5B9,0xB5BA,0xB5BB,0xB5BC,0xB5BD,0xB5BE,0xB5BF, + 0xB5C0,0xB5C1,0xB5C2,0xB5C3,0xB5C4,0xB5C5,0xB5C6,0xB5C7,0xB5C8,0xB5C9,0xB5CA,0xB5CB,0xB5CC,0xB5CD,0xB5CE,0xB5CF, + 0xB5D0,0xB5D1,0xB5D2,0xB5D3,0xB5D4,0xB5D5,0xB5D6,0xB5D7,0xB5D8,0xB5D9,0xB5DA,0xB5DB,0xB5DC,0xB5DD,0xB5DE,0xB5DF, + 0xB5E0,0xB5E1,0xB5E2,0xB5E3,0xB5E4,0xB5E5,0xB5E6,0xB5E7,0xB5E8,0xB5E9,0xB5EA,0xB5EB,0xB5EC,0xB5ED,0xB5EE,0xB5EF, + 0xB5F0,0xB5F1,0xB5F2,0xB5F3,0xB5F4,0xB5F5,0xB5F6,0xB5F7,0xB5F8,0xB5F9,0xB5FA,0xB5FB,0xB5FC,0xB5FD,0xB5FE,0xB5FF, + 0xB600,0xB601,0xB602,0xB603,0xB604,0xB605,0xB606,0xB607,0xB608,0xB609,0xB60A,0xB60B,0xB60C,0xB60D,0xB60E,0xB60F, + 0xB610,0xB611,0xB612,0xB613,0xB614,0xB615,0xB616,0xB617,0xB618,0xB619,0xB61A,0xB61B,0xB61C,0xB61D,0xB61E,0xB61F, + 0xB620,0xB621,0xB622,0xB623,0xB624,0xB625,0xB626,0xB627,0xB628,0xB629,0xB62A,0xB62B,0xB62C,0xB62D,0xB62E,0xB62F, + 0xB630,0xB631,0xB632,0xB633,0xB634,0xB635,0xB636,0xB637,0xB638,0xB639,0xB63A,0xB63B,0xB63C,0xB63D,0xB63E,0xB63F, + 0xB640,0xB641,0xB642,0xB643,0xB644,0xB645,0xB646,0xB647,0xB648,0xB649,0xB64A,0xB64B,0xB64C,0xB64D,0xB64E,0xB64F, + 0xB650,0xB651,0xB652,0xB653,0xB654,0xB655,0xB656,0xB657,0xB658,0xB659,0xB65A,0xB65B,0xB65C,0xB65D,0xB65E,0xB65F, + 0xB660,0xB661,0xB662,0xB663,0xB664,0xB665,0xB666,0xB667,0xB668,0xB669,0xB66A,0xB66B,0xB66C,0xB66D,0xB66E,0xB66F, + 0xB670,0xB671,0xB672,0xB673,0xB674,0xB675,0xB676,0xB677,0xB678,0xB679,0xB67A,0xB67B,0xB67C,0xB67D,0xB67E,0xB67F, + 0xB680,0xB681,0xB682,0xB683,0xB684,0xB685,0xB686,0xB687,0xB688,0xB689,0xB68A,0xB68B,0xB68C,0xB68D,0xB68E,0xB68F, + 0xB690,0xB691,0xB692,0xB693,0xB694,0xB695,0xB696,0xB697,0xB698,0xB699,0xB69A,0xB69B,0xB69C,0xB69D,0xB69E,0xB69F, + 0xB6A0,0xB6A1,0xB6A2,0xB6A3,0xB6A4,0xB6A5,0xB6A6,0xB6A7,0xB6A8,0xB6A9,0xB6AA,0xB6AB,0xB6AC,0xB6AD,0xB6AE,0xB6AF, + 0xB6B0,0xB6B1,0xB6B2,0xB6B3,0xB6B4,0xB6B5,0xB6B6,0xB6B7,0xB6B8,0xB6B9,0xB6BA,0xB6BB,0xB6BC,0xB6BD,0xB6BE,0xB6BF, + 0xB6C0,0xB6C1,0xB6C2,0xB6C3,0xB6C4,0xB6C5,0xB6C6,0xB6C7,0xB6C8,0xB6C9,0xB6CA,0xB6CB,0xB6CC,0xB6CD,0xB6CE,0xB6CF, + 0xB6D0,0xB6D1,0xB6D2,0xB6D3,0xB6D4,0xB6D5,0xB6D6,0xB6D7,0xB6D8,0xB6D9,0xB6DA,0xB6DB,0xB6DC,0xB6DD,0xB6DE,0xB6DF, + 0xB6E0,0xB6E1,0xB6E2,0xB6E3,0xB6E4,0xB6E5,0xB6E6,0xB6E7,0xB6E8,0xB6E9,0xB6EA,0xB6EB,0xB6EC,0xB6ED,0xB6EE,0xB6EF, + 0xB6F0,0xB6F1,0xB6F2,0xB6F3,0xB6F4,0xB6F5,0xB6F6,0xB6F7,0xB6F8,0xB6F9,0xB6FA,0xB6FB,0xB6FC,0xB6FD,0xB6FE,0xB6FF, + 0xB700,0xB701,0xB702,0xB703,0xB704,0xB705,0xB706,0xB707,0xB708,0xB709,0xB70A,0xB70B,0xB70C,0xB70D,0xB70E,0xB70F, + 0xB710,0xB711,0xB712,0xB713,0xB714,0xB715,0xB716,0xB717,0xB718,0xB719,0xB71A,0xB71B,0xB71C,0xB71D,0xB71E,0xB71F, + 0xB720,0xB721,0xB722,0xB723,0xB724,0xB725,0xB726,0xB727,0xB728,0xB729,0xB72A,0xB72B,0xB72C,0xB72D,0xB72E,0xB72F, + 0xB730,0xB731,0xB732,0xB733,0xB734,0xB735,0xB736,0xB737,0xB738,0xB739,0xB73A,0xB73B,0xB73C,0xB73D,0xB73E,0xB73F, + 0xB740,0xB741,0xB742,0xB743,0xB744,0xB745,0xB746,0xB747,0xB748,0xB749,0xB74A,0xB74B,0xB74C,0xB74D,0xB74E,0xB74F, + 0xB750,0xB751,0xB752,0xB753,0xB754,0xB755,0xB756,0xB757,0xB758,0xB759,0xB75A,0xB75B,0xB75C,0xB75D,0xB75E,0xB75F, + 0xB760,0xB761,0xB762,0xB763,0xB764,0xB765,0xB766,0xB767,0xB768,0xB769,0xB76A,0xB76B,0xB76C,0xB76D,0xB76E,0xB76F, + 0xB770,0xB771,0xB772,0xB773,0xB774,0xB775,0xB776,0xB777,0xB778,0xB779,0xB77A,0xB77B,0xB77C,0xB77D,0xB77E,0xB77F, + 0xB780,0xB781,0xB782,0xB783,0xB784,0xB785,0xB786,0xB787,0xB788,0xB789,0xB78A,0xB78B,0xB78C,0xB78D,0xB78E,0xB78F, + 0xB790,0xB791,0xB792,0xB793,0xB794,0xB795,0xB796,0xB797,0xB798,0xB799,0xB79A,0xB79B,0xB79C,0xB79D,0xB79E,0xB79F, + 0xB7A0,0xB7A1,0xB7A2,0xB7A3,0xB7A4,0xB7A5,0xB7A6,0xB7A7,0xB7A8,0xB7A9,0xB7AA,0xB7AB,0xB7AC,0xB7AD,0xB7AE,0xB7AF, + 0xB7B0,0xB7B1,0xB7B2,0xB7B3,0xB7B4,0xB7B5,0xB7B6,0xB7B7,0xB7B8,0xB7B9,0xB7BA,0xB7BB,0xB7BC,0xB7BD,0xB7BE,0xB7BF, + 0xB7C0,0xB7C1,0xB7C2,0xB7C3,0xB7C4,0xB7C5,0xB7C6,0xB7C7,0xB7C8,0xB7C9,0xB7CA,0xB7CB,0xB7CC,0xB7CD,0xB7CE,0xB7CF, + 0xB7D0,0xB7D1,0xB7D2,0xB7D3,0xB7D4,0xB7D5,0xB7D6,0xB7D7,0xB7D8,0xB7D9,0xB7DA,0xB7DB,0xB7DC,0xB7DD,0xB7DE,0xB7DF, + 0xB7E0,0xB7E1,0xB7E2,0xB7E3,0xB7E4,0xB7E5,0xB7E6,0xB7E7,0xB7E8,0xB7E9,0xB7EA,0xB7EB,0xB7EC,0xB7ED,0xB7EE,0xB7EF, + 0xB7F0,0xB7F1,0xB7F2,0xB7F3,0xB7F4,0xB7F5,0xB7F6,0xB7F7,0xB7F8,0xB7F9,0xB7FA,0xB7FB,0xB7FC,0xB7FD,0xB7FE,0xB7FF, + 0xB800,0xB801,0xB802,0xB803,0xB804,0xB805,0xB806,0xB807,0xB808,0xB809,0xB80A,0xB80B,0xB80C,0xB80D,0xB80E,0xB80F, + 0xB810,0xB811,0xB812,0xB813,0xB814,0xB815,0xB816,0xB817,0xB818,0xB819,0xB81A,0xB81B,0xB81C,0xB81D,0xB81E,0xB81F, + 0xB820,0xB821,0xB822,0xB823,0xB824,0xB825,0xB826,0xB827,0xB828,0xB829,0xB82A,0xB82B,0xB82C,0xB82D,0xB82E,0xB82F, + 0xB830,0xB831,0xB832,0xB833,0xB834,0xB835,0xB836,0xB837,0xB838,0xB839,0xB83A,0xB83B,0xB83C,0xB83D,0xB83E,0xB83F, + 0xB840,0xB841,0xB842,0xB843,0xB844,0xB845,0xB846,0xB847,0xB848,0xB849,0xB84A,0xB84B,0xB84C,0xB84D,0xB84E,0xB84F, + 0xB850,0xB851,0xB852,0xB853,0xB854,0xB855,0xB856,0xB857,0xB858,0xB859,0xB85A,0xB85B,0xB85C,0xB85D,0xB85E,0xB85F, + 0xB860,0xB861,0xB862,0xB863,0xB864,0xB865,0xB866,0xB867,0xB868,0xB869,0xB86A,0xB86B,0xB86C,0xB86D,0xB86E,0xB86F, + 0xB870,0xB871,0xB872,0xB873,0xB874,0xB875,0xB876,0xB877,0xB878,0xB879,0xB87A,0xB87B,0xB87C,0xB87D,0xB87E,0xB87F, + 0xB880,0xB881,0xB882,0xB883,0xB884,0xB885,0xB886,0xB887,0xB888,0xB889,0xB88A,0xB88B,0xB88C,0xB88D,0xB88E,0xB88F, + 0xB890,0xB891,0xB892,0xB893,0xB894,0xB895,0xB896,0xB897,0xB898,0xB899,0xB89A,0xB89B,0xB89C,0xB89D,0xB89E,0xB89F, + 0xB8A0,0xB8A1,0xB8A2,0xB8A3,0xB8A4,0xB8A5,0xB8A6,0xB8A7,0xB8A8,0xB8A9,0xB8AA,0xB8AB,0xB8AC,0xB8AD,0xB8AE,0xB8AF, + 0xB8B0,0xB8B1,0xB8B2,0xB8B3,0xB8B4,0xB8B5,0xB8B6,0xB8B7,0xB8B8,0xB8B9,0xB8BA,0xB8BB,0xB8BC,0xB8BD,0xB8BE,0xB8BF, + 0xB8C0,0xB8C1,0xB8C2,0xB8C3,0xB8C4,0xB8C5,0xB8C6,0xB8C7,0xB8C8,0xB8C9,0xB8CA,0xB8CB,0xB8CC,0xB8CD,0xB8CE,0xB8CF, + 0xB8D0,0xB8D1,0xB8D2,0xB8D3,0xB8D4,0xB8D5,0xB8D6,0xB8D7,0xB8D8,0xB8D9,0xB8DA,0xB8DB,0xB8DC,0xB8DD,0xB8DE,0xB8DF, + 0xB8E0,0xB8E1,0xB8E2,0xB8E3,0xB8E4,0xB8E5,0xB8E6,0xB8E7,0xB8E8,0xB8E9,0xB8EA,0xB8EB,0xB8EC,0xB8ED,0xB8EE,0xB8EF, + 0xB8F0,0xB8F1,0xB8F2,0xB8F3,0xB8F4,0xB8F5,0xB8F6,0xB8F7,0xB8F8,0xB8F9,0xB8FA,0xB8FB,0xB8FC,0xB8FD,0xB8FE,0xB8FF, + 0xB900,0xB901,0xB902,0xB903,0xB904,0xB905,0xB906,0xB907,0xB908,0xB909,0xB90A,0xB90B,0xB90C,0xB90D,0xB90E,0xB90F, + 0xB910,0xB911,0xB912,0xB913,0xB914,0xB915,0xB916,0xB917,0xB918,0xB919,0xB91A,0xB91B,0xB91C,0xB91D,0xB91E,0xB91F, + 0xB920,0xB921,0xB922,0xB923,0xB924,0xB925,0xB926,0xB927,0xB928,0xB929,0xB92A,0xB92B,0xB92C,0xB92D,0xB92E,0xB92F, + 0xB930,0xB931,0xB932,0xB933,0xB934,0xB935,0xB936,0xB937,0xB938,0xB939,0xB93A,0xB93B,0xB93C,0xB93D,0xB93E,0xB93F, + 0xB940,0xB941,0xB942,0xB943,0xB944,0xB945,0xB946,0xB947,0xB948,0xB949,0xB94A,0xB94B,0xB94C,0xB94D,0xB94E,0xB94F, + 0xB950,0xB951,0xB952,0xB953,0xB954,0xB955,0xB956,0xB957,0xB958,0xB959,0xB95A,0xB95B,0xB95C,0xB95D,0xB95E,0xB95F, + 0xB960,0xB961,0xB962,0xB963,0xB964,0xB965,0xB966,0xB967,0xB968,0xB969,0xB96A,0xB96B,0xB96C,0xB96D,0xB96E,0xB96F, + 0xB970,0xB971,0xB972,0xB973,0xB974,0xB975,0xB976,0xB977,0xB978,0xB979,0xB97A,0xB97B,0xB97C,0xB97D,0xB97E,0xB97F, + 0xB980,0xB981,0xB982,0xB983,0xB984,0xB985,0xB986,0xB987,0xB988,0xB989,0xB98A,0xB98B,0xB98C,0xB98D,0xB98E,0xB98F, + 0xB990,0xB991,0xB992,0xB993,0xB994,0xB995,0xB996,0xB997,0xB998,0xB999,0xB99A,0xB99B,0xB99C,0xB99D,0xB99E,0xB99F, + 0xB9A0,0xB9A1,0xB9A2,0xB9A3,0xB9A4,0xB9A5,0xB9A6,0xB9A7,0xB9A8,0xB9A9,0xB9AA,0xB9AB,0xB9AC,0xB9AD,0xB9AE,0xB9AF, + 0xB9B0,0xB9B1,0xB9B2,0xB9B3,0xB9B4,0xB9B5,0xB9B6,0xB9B7,0xB9B8,0xB9B9,0xB9BA,0xB9BB,0xB9BC,0xB9BD,0xB9BE,0xB9BF, + 0xB9C0,0xB9C1,0xB9C2,0xB9C3,0xB9C4,0xB9C5,0xB9C6,0xB9C7,0xB9C8,0xB9C9,0xB9CA,0xB9CB,0xB9CC,0xB9CD,0xB9CE,0xB9CF, + 0xB9D0,0xB9D1,0xB9D2,0xB9D3,0xB9D4,0xB9D5,0xB9D6,0xB9D7,0xB9D8,0xB9D9,0xB9DA,0xB9DB,0xB9DC,0xB9DD,0xB9DE,0xB9DF, + 0xB9E0,0xB9E1,0xB9E2,0xB9E3,0xB9E4,0xB9E5,0xB9E6,0xB9E7,0xB9E8,0xB9E9,0xB9EA,0xB9EB,0xB9EC,0xB9ED,0xB9EE,0xB9EF, + 0xB9F0,0xB9F1,0xB9F2,0xB9F3,0xB9F4,0xB9F5,0xB9F6,0xB9F7,0xB9F8,0xB9F9,0xB9FA,0xB9FB,0xB9FC,0xB9FD,0xB9FE,0xB9FF, + 0xBA00,0xBA01,0xBA02,0xBA03,0xBA04,0xBA05,0xBA06,0xBA07,0xBA08,0xBA09,0xBA0A,0xBA0B,0xBA0C,0xBA0D,0xBA0E,0xBA0F, + 0xBA10,0xBA11,0xBA12,0xBA13,0xBA14,0xBA15,0xBA16,0xBA17,0xBA18,0xBA19,0xBA1A,0xBA1B,0xBA1C,0xBA1D,0xBA1E,0xBA1F, + 0xBA20,0xBA21,0xBA22,0xBA23,0xBA24,0xBA25,0xBA26,0xBA27,0xBA28,0xBA29,0xBA2A,0xBA2B,0xBA2C,0xBA2D,0xBA2E,0xBA2F, + 0xBA30,0xBA31,0xBA32,0xBA33,0xBA34,0xBA35,0xBA36,0xBA37,0xBA38,0xBA39,0xBA3A,0xBA3B,0xBA3C,0xBA3D,0xBA3E,0xBA3F, + 0xBA40,0xBA41,0xBA42,0xBA43,0xBA44,0xBA45,0xBA46,0xBA47,0xBA48,0xBA49,0xBA4A,0xBA4B,0xBA4C,0xBA4D,0xBA4E,0xBA4F, + 0xBA50,0xBA51,0xBA52,0xBA53,0xBA54,0xBA55,0xBA56,0xBA57,0xBA58,0xBA59,0xBA5A,0xBA5B,0xBA5C,0xBA5D,0xBA5E,0xBA5F, + 0xBA60,0xBA61,0xBA62,0xBA63,0xBA64,0xBA65,0xBA66,0xBA67,0xBA68,0xBA69,0xBA6A,0xBA6B,0xBA6C,0xBA6D,0xBA6E,0xBA6F, + 0xBA70,0xBA71,0xBA72,0xBA73,0xBA74,0xBA75,0xBA76,0xBA77,0xBA78,0xBA79,0xBA7A,0xBA7B,0xBA7C,0xBA7D,0xBA7E,0xBA7F, + 0xBA80,0xBA81,0xBA82,0xBA83,0xBA84,0xBA85,0xBA86,0xBA87,0xBA88,0xBA89,0xBA8A,0xBA8B,0xBA8C,0xBA8D,0xBA8E,0xBA8F, + 0xBA90,0xBA91,0xBA92,0xBA93,0xBA94,0xBA95,0xBA96,0xBA97,0xBA98,0xBA99,0xBA9A,0xBA9B,0xBA9C,0xBA9D,0xBA9E,0xBA9F, + 0xBAA0,0xBAA1,0xBAA2,0xBAA3,0xBAA4,0xBAA5,0xBAA6,0xBAA7,0xBAA8,0xBAA9,0xBAAA,0xBAAB,0xBAAC,0xBAAD,0xBAAE,0xBAAF, + 0xBAB0,0xBAB1,0xBAB2,0xBAB3,0xBAB4,0xBAB5,0xBAB6,0xBAB7,0xBAB8,0xBAB9,0xBABA,0xBABB,0xBABC,0xBABD,0xBABE,0xBABF, + 0xBAC0,0xBAC1,0xBAC2,0xBAC3,0xBAC4,0xBAC5,0xBAC6,0xBAC7,0xBAC8,0xBAC9,0xBACA,0xBACB,0xBACC,0xBACD,0xBACE,0xBACF, + 0xBAD0,0xBAD1,0xBAD2,0xBAD3,0xBAD4,0xBAD5,0xBAD6,0xBAD7,0xBAD8,0xBAD9,0xBADA,0xBADB,0xBADC,0xBADD,0xBADE,0xBADF, + 0xBAE0,0xBAE1,0xBAE2,0xBAE3,0xBAE4,0xBAE5,0xBAE6,0xBAE7,0xBAE8,0xBAE9,0xBAEA,0xBAEB,0xBAEC,0xBAED,0xBAEE,0xBAEF, + 0xBAF0,0xBAF1,0xBAF2,0xBAF3,0xBAF4,0xBAF5,0xBAF6,0xBAF7,0xBAF8,0xBAF9,0xBAFA,0xBAFB,0xBAFC,0xBAFD,0xBAFE,0xBAFF, + 0xBB00,0xBB01,0xBB02,0xBB03,0xBB04,0xBB05,0xBB06,0xBB07,0xBB08,0xBB09,0xBB0A,0xBB0B,0xBB0C,0xBB0D,0xBB0E,0xBB0F, + 0xBB10,0xBB11,0xBB12,0xBB13,0xBB14,0xBB15,0xBB16,0xBB17,0xBB18,0xBB19,0xBB1A,0xBB1B,0xBB1C,0xBB1D,0xBB1E,0xBB1F, + 0xBB20,0xBB21,0xBB22,0xBB23,0xBB24,0xBB25,0xBB26,0xBB27,0xBB28,0xBB29,0xBB2A,0xBB2B,0xBB2C,0xBB2D,0xBB2E,0xBB2F, + 0xBB30,0xBB31,0xBB32,0xBB33,0xBB34,0xBB35,0xBB36,0xBB37,0xBB38,0xBB39,0xBB3A,0xBB3B,0xBB3C,0xBB3D,0xBB3E,0xBB3F, + 0xBB40,0xBB41,0xBB42,0xBB43,0xBB44,0xBB45,0xBB46,0xBB47,0xBB48,0xBB49,0xBB4A,0xBB4B,0xBB4C,0xBB4D,0xBB4E,0xBB4F, + 0xBB50,0xBB51,0xBB52,0xBB53,0xBB54,0xBB55,0xBB56,0xBB57,0xBB58,0xBB59,0xBB5A,0xBB5B,0xBB5C,0xBB5D,0xBB5E,0xBB5F, + 0xBB60,0xBB61,0xBB62,0xBB63,0xBB64,0xBB65,0xBB66,0xBB67,0xBB68,0xBB69,0xBB6A,0xBB6B,0xBB6C,0xBB6D,0xBB6E,0xBB6F, + 0xBB70,0xBB71,0xBB72,0xBB73,0xBB74,0xBB75,0xBB76,0xBB77,0xBB78,0xBB79,0xBB7A,0xBB7B,0xBB7C,0xBB7D,0xBB7E,0xBB7F, + 0xBB80,0xBB81,0xBB82,0xBB83,0xBB84,0xBB85,0xBB86,0xBB87,0xBB88,0xBB89,0xBB8A,0xBB8B,0xBB8C,0xBB8D,0xBB8E,0xBB8F, + 0xBB90,0xBB91,0xBB92,0xBB93,0xBB94,0xBB95,0xBB96,0xBB97,0xBB98,0xBB99,0xBB9A,0xBB9B,0xBB9C,0xBB9D,0xBB9E,0xBB9F, + 0xBBA0,0xBBA1,0xBBA2,0xBBA3,0xBBA4,0xBBA5,0xBBA6,0xBBA7,0xBBA8,0xBBA9,0xBBAA,0xBBAB,0xBBAC,0xBBAD,0xBBAE,0xBBAF, + 0xBBB0,0xBBB1,0xBBB2,0xBBB3,0xBBB4,0xBBB5,0xBBB6,0xBBB7,0xBBB8,0xBBB9,0xBBBA,0xBBBB,0xBBBC,0xBBBD,0xBBBE,0xBBBF, + 0xBBC0,0xBBC1,0xBBC2,0xBBC3,0xBBC4,0xBBC5,0xBBC6,0xBBC7,0xBBC8,0xBBC9,0xBBCA,0xBBCB,0xBBCC,0xBBCD,0xBBCE,0xBBCF, + 0xBBD0,0xBBD1,0xBBD2,0xBBD3,0xBBD4,0xBBD5,0xBBD6,0xBBD7,0xBBD8,0xBBD9,0xBBDA,0xBBDB,0xBBDC,0xBBDD,0xBBDE,0xBBDF, + 0xBBE0,0xBBE1,0xBBE2,0xBBE3,0xBBE4,0xBBE5,0xBBE6,0xBBE7,0xBBE8,0xBBE9,0xBBEA,0xBBEB,0xBBEC,0xBBED,0xBBEE,0xBBEF, + 0xBBF0,0xBBF1,0xBBF2,0xBBF3,0xBBF4,0xBBF5,0xBBF6,0xBBF7,0xBBF8,0xBBF9,0xBBFA,0xBBFB,0xBBFC,0xBBFD,0xBBFE,0xBBFF, + 0xBC00,0xBC01,0xBC02,0xBC03,0xBC04,0xBC05,0xBC06,0xBC07,0xBC08,0xBC09,0xBC0A,0xBC0B,0xBC0C,0xBC0D,0xBC0E,0xBC0F, + 0xBC10,0xBC11,0xBC12,0xBC13,0xBC14,0xBC15,0xBC16,0xBC17,0xBC18,0xBC19,0xBC1A,0xBC1B,0xBC1C,0xBC1D,0xBC1E,0xBC1F, + 0xBC20,0xBC21,0xBC22,0xBC23,0xBC24,0xBC25,0xBC26,0xBC27,0xBC28,0xBC29,0xBC2A,0xBC2B,0xBC2C,0xBC2D,0xBC2E,0xBC2F, + 0xBC30,0xBC31,0xBC32,0xBC33,0xBC34,0xBC35,0xBC36,0xBC37,0xBC38,0xBC39,0xBC3A,0xBC3B,0xBC3C,0xBC3D,0xBC3E,0xBC3F, + 0xBC40,0xBC41,0xBC42,0xBC43,0xBC44,0xBC45,0xBC46,0xBC47,0xBC48,0xBC49,0xBC4A,0xBC4B,0xBC4C,0xBC4D,0xBC4E,0xBC4F, + 0xBC50,0xBC51,0xBC52,0xBC53,0xBC54,0xBC55,0xBC56,0xBC57,0xBC58,0xBC59,0xBC5A,0xBC5B,0xBC5C,0xBC5D,0xBC5E,0xBC5F, + 0xBC60,0xBC61,0xBC62,0xBC63,0xBC64,0xBC65,0xBC66,0xBC67,0xBC68,0xBC69,0xBC6A,0xBC6B,0xBC6C,0xBC6D,0xBC6E,0xBC6F, + 0xBC70,0xBC71,0xBC72,0xBC73,0xBC74,0xBC75,0xBC76,0xBC77,0xBC78,0xBC79,0xBC7A,0xBC7B,0xBC7C,0xBC7D,0xBC7E,0xBC7F, + 0xBC80,0xBC81,0xBC82,0xBC83,0xBC84,0xBC85,0xBC86,0xBC87,0xBC88,0xBC89,0xBC8A,0xBC8B,0xBC8C,0xBC8D,0xBC8E,0xBC8F, + 0xBC90,0xBC91,0xBC92,0xBC93,0xBC94,0xBC95,0xBC96,0xBC97,0xBC98,0xBC99,0xBC9A,0xBC9B,0xBC9C,0xBC9D,0xBC9E,0xBC9F, + 0xBCA0,0xBCA1,0xBCA2,0xBCA3,0xBCA4,0xBCA5,0xBCA6,0xBCA7,0xBCA8,0xBCA9,0xBCAA,0xBCAB,0xBCAC,0xBCAD,0xBCAE,0xBCAF, + 0xBCB0,0xBCB1,0xBCB2,0xBCB3,0xBCB4,0xBCB5,0xBCB6,0xBCB7,0xBCB8,0xBCB9,0xBCBA,0xBCBB,0xBCBC,0xBCBD,0xBCBE,0xBCBF, + 0xBCC0,0xBCC1,0xBCC2,0xBCC3,0xBCC4,0xBCC5,0xBCC6,0xBCC7,0xBCC8,0xBCC9,0xBCCA,0xBCCB,0xBCCC,0xBCCD,0xBCCE,0xBCCF, + 0xBCD0,0xBCD1,0xBCD2,0xBCD3,0xBCD4,0xBCD5,0xBCD6,0xBCD7,0xBCD8,0xBCD9,0xBCDA,0xBCDB,0xBCDC,0xBCDD,0xBCDE,0xBCDF, + 0xBCE0,0xBCE1,0xBCE2,0xBCE3,0xBCE4,0xBCE5,0xBCE6,0xBCE7,0xBCE8,0xBCE9,0xBCEA,0xBCEB,0xBCEC,0xBCED,0xBCEE,0xBCEF, + 0xBCF0,0xBCF1,0xBCF2,0xBCF3,0xBCF4,0xBCF5,0xBCF6,0xBCF7,0xBCF8,0xBCF9,0xBCFA,0xBCFB,0xBCFC,0xBCFD,0xBCFE,0xBCFF, + 0xBD00,0xBD01,0xBD02,0xBD03,0xBD04,0xBD05,0xBD06,0xBD07,0xBD08,0xBD09,0xBD0A,0xBD0B,0xBD0C,0xBD0D,0xBD0E,0xBD0F, + 0xBD10,0xBD11,0xBD12,0xBD13,0xBD14,0xBD15,0xBD16,0xBD17,0xBD18,0xBD19,0xBD1A,0xBD1B,0xBD1C,0xBD1D,0xBD1E,0xBD1F, + 0xBD20,0xBD21,0xBD22,0xBD23,0xBD24,0xBD25,0xBD26,0xBD27,0xBD28,0xBD29,0xBD2A,0xBD2B,0xBD2C,0xBD2D,0xBD2E,0xBD2F, + 0xBD30,0xBD31,0xBD32,0xBD33,0xBD34,0xBD35,0xBD36,0xBD37,0xBD38,0xBD39,0xBD3A,0xBD3B,0xBD3C,0xBD3D,0xBD3E,0xBD3F, + 0xBD40,0xBD41,0xBD42,0xBD43,0xBD44,0xBD45,0xBD46,0xBD47,0xBD48,0xBD49,0xBD4A,0xBD4B,0xBD4C,0xBD4D,0xBD4E,0xBD4F, + 0xBD50,0xBD51,0xBD52,0xBD53,0xBD54,0xBD55,0xBD56,0xBD57,0xBD58,0xBD59,0xBD5A,0xBD5B,0xBD5C,0xBD5D,0xBD5E,0xBD5F, + 0xBD60,0xBD61,0xBD62,0xBD63,0xBD64,0xBD65,0xBD66,0xBD67,0xBD68,0xBD69,0xBD6A,0xBD6B,0xBD6C,0xBD6D,0xBD6E,0xBD6F, + 0xBD70,0xBD71,0xBD72,0xBD73,0xBD74,0xBD75,0xBD76,0xBD77,0xBD78,0xBD79,0xBD7A,0xBD7B,0xBD7C,0xBD7D,0xBD7E,0xBD7F, + 0xBD80,0xBD81,0xBD82,0xBD83,0xBD84,0xBD85,0xBD86,0xBD87,0xBD88,0xBD89,0xBD8A,0xBD8B,0xBD8C,0xBD8D,0xBD8E,0xBD8F, + 0xBD90,0xBD91,0xBD92,0xBD93,0xBD94,0xBD95,0xBD96,0xBD97,0xBD98,0xBD99,0xBD9A,0xBD9B,0xBD9C,0xBD9D,0xBD9E,0xBD9F, + 0xBDA0,0xBDA1,0xBDA2,0xBDA3,0xBDA4,0xBDA5,0xBDA6,0xBDA7,0xBDA8,0xBDA9,0xBDAA,0xBDAB,0xBDAC,0xBDAD,0xBDAE,0xBDAF, + 0xBDB0,0xBDB1,0xBDB2,0xBDB3,0xBDB4,0xBDB5,0xBDB6,0xBDB7,0xBDB8,0xBDB9,0xBDBA,0xBDBB,0xBDBC,0xBDBD,0xBDBE,0xBDBF, + 0xBDC0,0xBDC1,0xBDC2,0xBDC3,0xBDC4,0xBDC5,0xBDC6,0xBDC7,0xBDC8,0xBDC9,0xBDCA,0xBDCB,0xBDCC,0xBDCD,0xBDCE,0xBDCF, + 0xBDD0,0xBDD1,0xBDD2,0xBDD3,0xBDD4,0xBDD5,0xBDD6,0xBDD7,0xBDD8,0xBDD9,0xBDDA,0xBDDB,0xBDDC,0xBDDD,0xBDDE,0xBDDF, + 0xBDE0,0xBDE1,0xBDE2,0xBDE3,0xBDE4,0xBDE5,0xBDE6,0xBDE7,0xBDE8,0xBDE9,0xBDEA,0xBDEB,0xBDEC,0xBDED,0xBDEE,0xBDEF, + 0xBDF0,0xBDF1,0xBDF2,0xBDF3,0xBDF4,0xBDF5,0xBDF6,0xBDF7,0xBDF8,0xBDF9,0xBDFA,0xBDFB,0xBDFC,0xBDFD,0xBDFE,0xBDFF, + 0xBE00,0xBE01,0xBE02,0xBE03,0xBE04,0xBE05,0xBE06,0xBE07,0xBE08,0xBE09,0xBE0A,0xBE0B,0xBE0C,0xBE0D,0xBE0E,0xBE0F, + 0xBE10,0xBE11,0xBE12,0xBE13,0xBE14,0xBE15,0xBE16,0xBE17,0xBE18,0xBE19,0xBE1A,0xBE1B,0xBE1C,0xBE1D,0xBE1E,0xBE1F, + 0xBE20,0xBE21,0xBE22,0xBE23,0xBE24,0xBE25,0xBE26,0xBE27,0xBE28,0xBE29,0xBE2A,0xBE2B,0xBE2C,0xBE2D,0xBE2E,0xBE2F, + 0xBE30,0xBE31,0xBE32,0xBE33,0xBE34,0xBE35,0xBE36,0xBE37,0xBE38,0xBE39,0xBE3A,0xBE3B,0xBE3C,0xBE3D,0xBE3E,0xBE3F, + 0xBE40,0xBE41,0xBE42,0xBE43,0xBE44,0xBE45,0xBE46,0xBE47,0xBE48,0xBE49,0xBE4A,0xBE4B,0xBE4C,0xBE4D,0xBE4E,0xBE4F, + 0xBE50,0xBE51,0xBE52,0xBE53,0xBE54,0xBE55,0xBE56,0xBE57,0xBE58,0xBE59,0xBE5A,0xBE5B,0xBE5C,0xBE5D,0xBE5E,0xBE5F, + 0xBE60,0xBE61,0xBE62,0xBE63,0xBE64,0xBE65,0xBE66,0xBE67,0xBE68,0xBE69,0xBE6A,0xBE6B,0xBE6C,0xBE6D,0xBE6E,0xBE6F, + 0xBE70,0xBE71,0xBE72,0xBE73,0xBE74,0xBE75,0xBE76,0xBE77,0xBE78,0xBE79,0xBE7A,0xBE7B,0xBE7C,0xBE7D,0xBE7E,0xBE7F, + 0xBE80,0xBE81,0xBE82,0xBE83,0xBE84,0xBE85,0xBE86,0xBE87,0xBE88,0xBE89,0xBE8A,0xBE8B,0xBE8C,0xBE8D,0xBE8E,0xBE8F, + 0xBE90,0xBE91,0xBE92,0xBE93,0xBE94,0xBE95,0xBE96,0xBE97,0xBE98,0xBE99,0xBE9A,0xBE9B,0xBE9C,0xBE9D,0xBE9E,0xBE9F, + 0xBEA0,0xBEA1,0xBEA2,0xBEA3,0xBEA4,0xBEA5,0xBEA6,0xBEA7,0xBEA8,0xBEA9,0xBEAA,0xBEAB,0xBEAC,0xBEAD,0xBEAE,0xBEAF, + 0xBEB0,0xBEB1,0xBEB2,0xBEB3,0xBEB4,0xBEB5,0xBEB6,0xBEB7,0xBEB8,0xBEB9,0xBEBA,0xBEBB,0xBEBC,0xBEBD,0xBEBE,0xBEBF, + 0xBEC0,0xBEC1,0xBEC2,0xBEC3,0xBEC4,0xBEC5,0xBEC6,0xBEC7,0xBEC8,0xBEC9,0xBECA,0xBECB,0xBECC,0xBECD,0xBECE,0xBECF, + 0xBED0,0xBED1,0xBED2,0xBED3,0xBED4,0xBED5,0xBED6,0xBED7,0xBED8,0xBED9,0xBEDA,0xBEDB,0xBEDC,0xBEDD,0xBEDE,0xBEDF, + 0xBEE0,0xBEE1,0xBEE2,0xBEE3,0xBEE4,0xBEE5,0xBEE6,0xBEE7,0xBEE8,0xBEE9,0xBEEA,0xBEEB,0xBEEC,0xBEED,0xBEEE,0xBEEF, + 0xBEF0,0xBEF1,0xBEF2,0xBEF3,0xBEF4,0xBEF5,0xBEF6,0xBEF7,0xBEF8,0xBEF9,0xBEFA,0xBEFB,0xBEFC,0xBEFD,0xBEFE,0xBEFF, + 0xBF00,0xBF01,0xBF02,0xBF03,0xBF04,0xBF05,0xBF06,0xBF07,0xBF08,0xBF09,0xBF0A,0xBF0B,0xBF0C,0xBF0D,0xBF0E,0xBF0F, + 0xBF10,0xBF11,0xBF12,0xBF13,0xBF14,0xBF15,0xBF16,0xBF17,0xBF18,0xBF19,0xBF1A,0xBF1B,0xBF1C,0xBF1D,0xBF1E,0xBF1F, + 0xBF20,0xBF21,0xBF22,0xBF23,0xBF24,0xBF25,0xBF26,0xBF27,0xBF28,0xBF29,0xBF2A,0xBF2B,0xBF2C,0xBF2D,0xBF2E,0xBF2F, + 0xBF30,0xBF31,0xBF32,0xBF33,0xBF34,0xBF35,0xBF36,0xBF37,0xBF38,0xBF39,0xBF3A,0xBF3B,0xBF3C,0xBF3D,0xBF3E,0xBF3F, + 0xBF40,0xBF41,0xBF42,0xBF43,0xBF44,0xBF45,0xBF46,0xBF47,0xBF48,0xBF49,0xBF4A,0xBF4B,0xBF4C,0xBF4D,0xBF4E,0xBF4F, + 0xBF50,0xBF51,0xBF52,0xBF53,0xBF54,0xBF55,0xBF56,0xBF57,0xBF58,0xBF59,0xBF5A,0xBF5B,0xBF5C,0xBF5D,0xBF5E,0xBF5F, + 0xBF60,0xBF61,0xBF62,0xBF63,0xBF64,0xBF65,0xBF66,0xBF67,0xBF68,0xBF69,0xBF6A,0xBF6B,0xBF6C,0xBF6D,0xBF6E,0xBF6F, + 0xBF70,0xBF71,0xBF72,0xBF73,0xBF74,0xBF75,0xBF76,0xBF77,0xBF78,0xBF79,0xBF7A,0xBF7B,0xBF7C,0xBF7D,0xBF7E,0xBF7F, + 0xBF80,0xBF81,0xBF82,0xBF83,0xBF84,0xBF85,0xBF86,0xBF87,0xBF88,0xBF89,0xBF8A,0xBF8B,0xBF8C,0xBF8D,0xBF8E,0xBF8F, + 0xBF90,0xBF91,0xBF92,0xBF93,0xBF94,0xBF95,0xBF96,0xBF97,0xBF98,0xBF99,0xBF9A,0xBF9B,0xBF9C,0xBF9D,0xBF9E,0xBF9F, + 0xBFA0,0xBFA1,0xBFA2,0xBFA3,0xBFA4,0xBFA5,0xBFA6,0xBFA7,0xBFA8,0xBFA9,0xBFAA,0xBFAB,0xBFAC,0xBFAD,0xBFAE,0xBFAF, + 0xBFB0,0xBFB1,0xBFB2,0xBFB3,0xBFB4,0xBFB5,0xBFB6,0xBFB7,0xBFB8,0xBFB9,0xBFBA,0xBFBB,0xBFBC,0xBFBD,0xBFBE,0xBFBF, + 0xBFC0,0xBFC1,0xBFC2,0xBFC3,0xBFC4,0xBFC5,0xBFC6,0xBFC7,0xBFC8,0xBFC9,0xBFCA,0xBFCB,0xBFCC,0xBFCD,0xBFCE,0xBFCF, + 0xBFD0,0xBFD1,0xBFD2,0xBFD3,0xBFD4,0xBFD5,0xBFD6,0xBFD7,0xBFD8,0xBFD9,0xBFDA,0xBFDB,0xBFDC,0xBFDD,0xBFDE,0xBFDF, + 0xBFE0,0xBFE1,0xBFE2,0xBFE3,0xBFE4,0xBFE5,0xBFE6,0xBFE7,0xBFE8,0xBFE9,0xBFEA,0xBFEB,0xBFEC,0xBFED,0xBFEE,0xBFEF, + 0xBFF0,0xBFF1,0xBFF2,0xBFF3,0xBFF4,0xBFF5,0xBFF6,0xBFF7,0xBFF8,0xBFF9,0xBFFA,0xBFFB,0xBFFC,0xBFFD,0xBFFE,0xBFFF, + 0xC000,0xC001,0xC002,0xC003,0xC004,0xC005,0xC006,0xC007,0xC008,0xC009,0xC00A,0xC00B,0xC00C,0xC00D,0xC00E,0xC00F, + 0xC010,0xC011,0xC012,0xC013,0xC014,0xC015,0xC016,0xC017,0xC018,0xC019,0xC01A,0xC01B,0xC01C,0xC01D,0xC01E,0xC01F, + 0xC020,0xC021,0xC022,0xC023,0xC024,0xC025,0xC026,0xC027,0xC028,0xC029,0xC02A,0xC02B,0xC02C,0xC02D,0xC02E,0xC02F, + 0xC030,0xC031,0xC032,0xC033,0xC034,0xC035,0xC036,0xC037,0xC038,0xC039,0xC03A,0xC03B,0xC03C,0xC03D,0xC03E,0xC03F, + 0xC040,0xC041,0xC042,0xC043,0xC044,0xC045,0xC046,0xC047,0xC048,0xC049,0xC04A,0xC04B,0xC04C,0xC04D,0xC04E,0xC04F, + 0xC050,0xC051,0xC052,0xC053,0xC054,0xC055,0xC056,0xC057,0xC058,0xC059,0xC05A,0xC05B,0xC05C,0xC05D,0xC05E,0xC05F, + 0xC060,0xC061,0xC062,0xC063,0xC064,0xC065,0xC066,0xC067,0xC068,0xC069,0xC06A,0xC06B,0xC06C,0xC06D,0xC06E,0xC06F, + 0xC070,0xC071,0xC072,0xC073,0xC074,0xC075,0xC076,0xC077,0xC078,0xC079,0xC07A,0xC07B,0xC07C,0xC07D,0xC07E,0xC07F, + 0xC080,0xC081,0xC082,0xC083,0xC084,0xC085,0xC086,0xC087,0xC088,0xC089,0xC08A,0xC08B,0xC08C,0xC08D,0xC08E,0xC08F, + 0xC090,0xC091,0xC092,0xC093,0xC094,0xC095,0xC096,0xC097,0xC098,0xC099,0xC09A,0xC09B,0xC09C,0xC09D,0xC09E,0xC09F, + 0xC0A0,0xC0A1,0xC0A2,0xC0A3,0xC0A4,0xC0A5,0xC0A6,0xC0A7,0xC0A8,0xC0A9,0xC0AA,0xC0AB,0xC0AC,0xC0AD,0xC0AE,0xC0AF, + 0xC0B0,0xC0B1,0xC0B2,0xC0B3,0xC0B4,0xC0B5,0xC0B6,0xC0B7,0xC0B8,0xC0B9,0xC0BA,0xC0BB,0xC0BC,0xC0BD,0xC0BE,0xC0BF, + 0xC0C0,0xC0C1,0xC0C2,0xC0C3,0xC0C4,0xC0C5,0xC0C6,0xC0C7,0xC0C8,0xC0C9,0xC0CA,0xC0CB,0xC0CC,0xC0CD,0xC0CE,0xC0CF, + 0xC0D0,0xC0D1,0xC0D2,0xC0D3,0xC0D4,0xC0D5,0xC0D6,0xC0D7,0xC0D8,0xC0D9,0xC0DA,0xC0DB,0xC0DC,0xC0DD,0xC0DE,0xC0DF, + 0xC0E0,0xC0E1,0xC0E2,0xC0E3,0xC0E4,0xC0E5,0xC0E6,0xC0E7,0xC0E8,0xC0E9,0xC0EA,0xC0EB,0xC0EC,0xC0ED,0xC0EE,0xC0EF, + 0xC0F0,0xC0F1,0xC0F2,0xC0F3,0xC0F4,0xC0F5,0xC0F6,0xC0F7,0xC0F8,0xC0F9,0xC0FA,0xC0FB,0xC0FC,0xC0FD,0xC0FE,0xC0FF, + 0xC100,0xC101,0xC102,0xC103,0xC104,0xC105,0xC106,0xC107,0xC108,0xC109,0xC10A,0xC10B,0xC10C,0xC10D,0xC10E,0xC10F, + 0xC110,0xC111,0xC112,0xC113,0xC114,0xC115,0xC116,0xC117,0xC118,0xC119,0xC11A,0xC11B,0xC11C,0xC11D,0xC11E,0xC11F, + 0xC120,0xC121,0xC122,0xC123,0xC124,0xC125,0xC126,0xC127,0xC128,0xC129,0xC12A,0xC12B,0xC12C,0xC12D,0xC12E,0xC12F, + 0xC130,0xC131,0xC132,0xC133,0xC134,0xC135,0xC136,0xC137,0xC138,0xC139,0xC13A,0xC13B,0xC13C,0xC13D,0xC13E,0xC13F, + 0xC140,0xC141,0xC142,0xC143,0xC144,0xC145,0xC146,0xC147,0xC148,0xC149,0xC14A,0xC14B,0xC14C,0xC14D,0xC14E,0xC14F, + 0xC150,0xC151,0xC152,0xC153,0xC154,0xC155,0xC156,0xC157,0xC158,0xC159,0xC15A,0xC15B,0xC15C,0xC15D,0xC15E,0xC15F, + 0xC160,0xC161,0xC162,0xC163,0xC164,0xC165,0xC166,0xC167,0xC168,0xC169,0xC16A,0xC16B,0xC16C,0xC16D,0xC16E,0xC16F, + 0xC170,0xC171,0xC172,0xC173,0xC174,0xC175,0xC176,0xC177,0xC178,0xC179,0xC17A,0xC17B,0xC17C,0xC17D,0xC17E,0xC17F, + 0xC180,0xC181,0xC182,0xC183,0xC184,0xC185,0xC186,0xC187,0xC188,0xC189,0xC18A,0xC18B,0xC18C,0xC18D,0xC18E,0xC18F, + 0xC190,0xC191,0xC192,0xC193,0xC194,0xC195,0xC196,0xC197,0xC198,0xC199,0xC19A,0xC19B,0xC19C,0xC19D,0xC19E,0xC19F, + 0xC1A0,0xC1A1,0xC1A2,0xC1A3,0xC1A4,0xC1A5,0xC1A6,0xC1A7,0xC1A8,0xC1A9,0xC1AA,0xC1AB,0xC1AC,0xC1AD,0xC1AE,0xC1AF, + 0xC1B0,0xC1B1,0xC1B2,0xC1B3,0xC1B4,0xC1B5,0xC1B6,0xC1B7,0xC1B8,0xC1B9,0xC1BA,0xC1BB,0xC1BC,0xC1BD,0xC1BE,0xC1BF, + 0xC1C0,0xC1C1,0xC1C2,0xC1C3,0xC1C4,0xC1C5,0xC1C6,0xC1C7,0xC1C8,0xC1C9,0xC1CA,0xC1CB,0xC1CC,0xC1CD,0xC1CE,0xC1CF, + 0xC1D0,0xC1D1,0xC1D2,0xC1D3,0xC1D4,0xC1D5,0xC1D6,0xC1D7,0xC1D8,0xC1D9,0xC1DA,0xC1DB,0xC1DC,0xC1DD,0xC1DE,0xC1DF, + 0xC1E0,0xC1E1,0xC1E2,0xC1E3,0xC1E4,0xC1E5,0xC1E6,0xC1E7,0xC1E8,0xC1E9,0xC1EA,0xC1EB,0xC1EC,0xC1ED,0xC1EE,0xC1EF, + 0xC1F0,0xC1F1,0xC1F2,0xC1F3,0xC1F4,0xC1F5,0xC1F6,0xC1F7,0xC1F8,0xC1F9,0xC1FA,0xC1FB,0xC1FC,0xC1FD,0xC1FE,0xC1FF, + 0xC200,0xC201,0xC202,0xC203,0xC204,0xC205,0xC206,0xC207,0xC208,0xC209,0xC20A,0xC20B,0xC20C,0xC20D,0xC20E,0xC20F, + 0xC210,0xC211,0xC212,0xC213,0xC214,0xC215,0xC216,0xC217,0xC218,0xC219,0xC21A,0xC21B,0xC21C,0xC21D,0xC21E,0xC21F, + 0xC220,0xC221,0xC222,0xC223,0xC224,0xC225,0xC226,0xC227,0xC228,0xC229,0xC22A,0xC22B,0xC22C,0xC22D,0xC22E,0xC22F, + 0xC230,0xC231,0xC232,0xC233,0xC234,0xC235,0xC236,0xC237,0xC238,0xC239,0xC23A,0xC23B,0xC23C,0xC23D,0xC23E,0xC23F, + 0xC240,0xC241,0xC242,0xC243,0xC244,0xC245,0xC246,0xC247,0xC248,0xC249,0xC24A,0xC24B,0xC24C,0xC24D,0xC24E,0xC24F, + 0xC250,0xC251,0xC252,0xC253,0xC254,0xC255,0xC256,0xC257,0xC258,0xC259,0xC25A,0xC25B,0xC25C,0xC25D,0xC25E,0xC25F, + 0xC260,0xC261,0xC262,0xC263,0xC264,0xC265,0xC266,0xC267,0xC268,0xC269,0xC26A,0xC26B,0xC26C,0xC26D,0xC26E,0xC26F, + 0xC270,0xC271,0xC272,0xC273,0xC274,0xC275,0xC276,0xC277,0xC278,0xC279,0xC27A,0xC27B,0xC27C,0xC27D,0xC27E,0xC27F, + 0xC280,0xC281,0xC282,0xC283,0xC284,0xC285,0xC286,0xC287,0xC288,0xC289,0xC28A,0xC28B,0xC28C,0xC28D,0xC28E,0xC28F, + 0xC290,0xC291,0xC292,0xC293,0xC294,0xC295,0xC296,0xC297,0xC298,0xC299,0xC29A,0xC29B,0xC29C,0xC29D,0xC29E,0xC29F, + 0xC2A0,0xC2A1,0xC2A2,0xC2A3,0xC2A4,0xC2A5,0xC2A6,0xC2A7,0xC2A8,0xC2A9,0xC2AA,0xC2AB,0xC2AC,0xC2AD,0xC2AE,0xC2AF, + 0xC2B0,0xC2B1,0xC2B2,0xC2B3,0xC2B4,0xC2B5,0xC2B6,0xC2B7,0xC2B8,0xC2B9,0xC2BA,0xC2BB,0xC2BC,0xC2BD,0xC2BE,0xC2BF, + 0xC2C0,0xC2C1,0xC2C2,0xC2C3,0xC2C4,0xC2C5,0xC2C6,0xC2C7,0xC2C8,0xC2C9,0xC2CA,0xC2CB,0xC2CC,0xC2CD,0xC2CE,0xC2CF, + 0xC2D0,0xC2D1,0xC2D2,0xC2D3,0xC2D4,0xC2D5,0xC2D6,0xC2D7,0xC2D8,0xC2D9,0xC2DA,0xC2DB,0xC2DC,0xC2DD,0xC2DE,0xC2DF, + 0xC2E0,0xC2E1,0xC2E2,0xC2E3,0xC2E4,0xC2E5,0xC2E6,0xC2E7,0xC2E8,0xC2E9,0xC2EA,0xC2EB,0xC2EC,0xC2ED,0xC2EE,0xC2EF, + 0xC2F0,0xC2F1,0xC2F2,0xC2F3,0xC2F4,0xC2F5,0xC2F6,0xC2F7,0xC2F8,0xC2F9,0xC2FA,0xC2FB,0xC2FC,0xC2FD,0xC2FE,0xC2FF, + 0xC300,0xC301,0xC302,0xC303,0xC304,0xC305,0xC306,0xC307,0xC308,0xC309,0xC30A,0xC30B,0xC30C,0xC30D,0xC30E,0xC30F, + 0xC310,0xC311,0xC312,0xC313,0xC314,0xC315,0xC316,0xC317,0xC318,0xC319,0xC31A,0xC31B,0xC31C,0xC31D,0xC31E,0xC31F, + 0xC320,0xC321,0xC322,0xC323,0xC324,0xC325,0xC326,0xC327,0xC328,0xC329,0xC32A,0xC32B,0xC32C,0xC32D,0xC32E,0xC32F, + 0xC330,0xC331,0xC332,0xC333,0xC334,0xC335,0xC336,0xC337,0xC338,0xC339,0xC33A,0xC33B,0xC33C,0xC33D,0xC33E,0xC33F, + 0xC340,0xC341,0xC342,0xC343,0xC344,0xC345,0xC346,0xC347,0xC348,0xC349,0xC34A,0xC34B,0xC34C,0xC34D,0xC34E,0xC34F, + 0xC350,0xC351,0xC352,0xC353,0xC354,0xC355,0xC356,0xC357,0xC358,0xC359,0xC35A,0xC35B,0xC35C,0xC35D,0xC35E,0xC35F, + 0xC360,0xC361,0xC362,0xC363,0xC364,0xC365,0xC366,0xC367,0xC368,0xC369,0xC36A,0xC36B,0xC36C,0xC36D,0xC36E,0xC36F, + 0xC370,0xC371,0xC372,0xC373,0xC374,0xC375,0xC376,0xC377,0xC378,0xC379,0xC37A,0xC37B,0xC37C,0xC37D,0xC37E,0xC37F, + 0xC380,0xC381,0xC382,0xC383,0xC384,0xC385,0xC386,0xC387,0xC388,0xC389,0xC38A,0xC38B,0xC38C,0xC38D,0xC38E,0xC38F, + 0xC390,0xC391,0xC392,0xC393,0xC394,0xC395,0xC396,0xC397,0xC398,0xC399,0xC39A,0xC39B,0xC39C,0xC39D,0xC39E,0xC39F, + 0xC3A0,0xC3A1,0xC3A2,0xC3A3,0xC3A4,0xC3A5,0xC3A6,0xC3A7,0xC3A8,0xC3A9,0xC3AA,0xC3AB,0xC3AC,0xC3AD,0xC3AE,0xC3AF, + 0xC3B0,0xC3B1,0xC3B2,0xC3B3,0xC3B4,0xC3B5,0xC3B6,0xC3B7,0xC3B8,0xC3B9,0xC3BA,0xC3BB,0xC3BC,0xC3BD,0xC3BE,0xC3BF, + 0xC3C0,0xC3C1,0xC3C2,0xC3C3,0xC3C4,0xC3C5,0xC3C6,0xC3C7,0xC3C8,0xC3C9,0xC3CA,0xC3CB,0xC3CC,0xC3CD,0xC3CE,0xC3CF, + 0xC3D0,0xC3D1,0xC3D2,0xC3D3,0xC3D4,0xC3D5,0xC3D6,0xC3D7,0xC3D8,0xC3D9,0xC3DA,0xC3DB,0xC3DC,0xC3DD,0xC3DE,0xC3DF, + 0xC3E0,0xC3E1,0xC3E2,0xC3E3,0xC3E4,0xC3E5,0xC3E6,0xC3E7,0xC3E8,0xC3E9,0xC3EA,0xC3EB,0xC3EC,0xC3ED,0xC3EE,0xC3EF, + 0xC3F0,0xC3F1,0xC3F2,0xC3F3,0xC3F4,0xC3F5,0xC3F6,0xC3F7,0xC3F8,0xC3F9,0xC3FA,0xC3FB,0xC3FC,0xC3FD,0xC3FE,0xC3FF, + 0xC400,0xC401,0xC402,0xC403,0xC404,0xC405,0xC406,0xC407,0xC408,0xC409,0xC40A,0xC40B,0xC40C,0xC40D,0xC40E,0xC40F, + 0xC410,0xC411,0xC412,0xC413,0xC414,0xC415,0xC416,0xC417,0xC418,0xC419,0xC41A,0xC41B,0xC41C,0xC41D,0xC41E,0xC41F, + 0xC420,0xC421,0xC422,0xC423,0xC424,0xC425,0xC426,0xC427,0xC428,0xC429,0xC42A,0xC42B,0xC42C,0xC42D,0xC42E,0xC42F, + 0xC430,0xC431,0xC432,0xC433,0xC434,0xC435,0xC436,0xC437,0xC438,0xC439,0xC43A,0xC43B,0xC43C,0xC43D,0xC43E,0xC43F, + 0xC440,0xC441,0xC442,0xC443,0xC444,0xC445,0xC446,0xC447,0xC448,0xC449,0xC44A,0xC44B,0xC44C,0xC44D,0xC44E,0xC44F, + 0xC450,0xC451,0xC452,0xC453,0xC454,0xC455,0xC456,0xC457,0xC458,0xC459,0xC45A,0xC45B,0xC45C,0xC45D,0xC45E,0xC45F, + 0xC460,0xC461,0xC462,0xC463,0xC464,0xC465,0xC466,0xC467,0xC468,0xC469,0xC46A,0xC46B,0xC46C,0xC46D,0xC46E,0xC46F, + 0xC470,0xC471,0xC472,0xC473,0xC474,0xC475,0xC476,0xC477,0xC478,0xC479,0xC47A,0xC47B,0xC47C,0xC47D,0xC47E,0xC47F, + 0xC480,0xC481,0xC482,0xC483,0xC484,0xC485,0xC486,0xC487,0xC488,0xC489,0xC48A,0xC48B,0xC48C,0xC48D,0xC48E,0xC48F, + 0xC490,0xC491,0xC492,0xC493,0xC494,0xC495,0xC496,0xC497,0xC498,0xC499,0xC49A,0xC49B,0xC49C,0xC49D,0xC49E,0xC49F, + 0xC4A0,0xC4A1,0xC4A2,0xC4A3,0xC4A4,0xC4A5,0xC4A6,0xC4A7,0xC4A8,0xC4A9,0xC4AA,0xC4AB,0xC4AC,0xC4AD,0xC4AE,0xC4AF, + 0xC4B0,0xC4B1,0xC4B2,0xC4B3,0xC4B4,0xC4B5,0xC4B6,0xC4B7,0xC4B8,0xC4B9,0xC4BA,0xC4BB,0xC4BC,0xC4BD,0xC4BE,0xC4BF, + 0xC4C0,0xC4C1,0xC4C2,0xC4C3,0xC4C4,0xC4C5,0xC4C6,0xC4C7,0xC4C8,0xC4C9,0xC4CA,0xC4CB,0xC4CC,0xC4CD,0xC4CE,0xC4CF, + 0xC4D0,0xC4D1,0xC4D2,0xC4D3,0xC4D4,0xC4D5,0xC4D6,0xC4D7,0xC4D8,0xC4D9,0xC4DA,0xC4DB,0xC4DC,0xC4DD,0xC4DE,0xC4DF, + 0xC4E0,0xC4E1,0xC4E2,0xC4E3,0xC4E4,0xC4E5,0xC4E6,0xC4E7,0xC4E8,0xC4E9,0xC4EA,0xC4EB,0xC4EC,0xC4ED,0xC4EE,0xC4EF, + 0xC4F0,0xC4F1,0xC4F2,0xC4F3,0xC4F4,0xC4F5,0xC4F6,0xC4F7,0xC4F8,0xC4F9,0xC4FA,0xC4FB,0xC4FC,0xC4FD,0xC4FE,0xC4FF, + 0xC500,0xC501,0xC502,0xC503,0xC504,0xC505,0xC506,0xC507,0xC508,0xC509,0xC50A,0xC50B,0xC50C,0xC50D,0xC50E,0xC50F, + 0xC510,0xC511,0xC512,0xC513,0xC514,0xC515,0xC516,0xC517,0xC518,0xC519,0xC51A,0xC51B,0xC51C,0xC51D,0xC51E,0xC51F, + 0xC520,0xC521,0xC522,0xC523,0xC524,0xC525,0xC526,0xC527,0xC528,0xC529,0xC52A,0xC52B,0xC52C,0xC52D,0xC52E,0xC52F, + 0xC530,0xC531,0xC532,0xC533,0xC534,0xC535,0xC536,0xC537,0xC538,0xC539,0xC53A,0xC53B,0xC53C,0xC53D,0xC53E,0xC53F, + 0xC540,0xC541,0xC542,0xC543,0xC544,0xC545,0xC546,0xC547,0xC548,0xC549,0xC54A,0xC54B,0xC54C,0xC54D,0xC54E,0xC54F, + 0xC550,0xC551,0xC552,0xC553,0xC554,0xC555,0xC556,0xC557,0xC558,0xC559,0xC55A,0xC55B,0xC55C,0xC55D,0xC55E,0xC55F, + 0xC560,0xC561,0xC562,0xC563,0xC564,0xC565,0xC566,0xC567,0xC568,0xC569,0xC56A,0xC56B,0xC56C,0xC56D,0xC56E,0xC56F, + 0xC570,0xC571,0xC572,0xC573,0xC574,0xC575,0xC576,0xC577,0xC578,0xC579,0xC57A,0xC57B,0xC57C,0xC57D,0xC57E,0xC57F, + 0xC580,0xC581,0xC582,0xC583,0xC584,0xC585,0xC586,0xC587,0xC588,0xC589,0xC58A,0xC58B,0xC58C,0xC58D,0xC58E,0xC58F, + 0xC590,0xC591,0xC592,0xC593,0xC594,0xC595,0xC596,0xC597,0xC598,0xC599,0xC59A,0xC59B,0xC59C,0xC59D,0xC59E,0xC59F, + 0xC5A0,0xC5A1,0xC5A2,0xC5A3,0xC5A4,0xC5A5,0xC5A6,0xC5A7,0xC5A8,0xC5A9,0xC5AA,0xC5AB,0xC5AC,0xC5AD,0xC5AE,0xC5AF, + 0xC5B0,0xC5B1,0xC5B2,0xC5B3,0xC5B4,0xC5B5,0xC5B6,0xC5B7,0xC5B8,0xC5B9,0xC5BA,0xC5BB,0xC5BC,0xC5BD,0xC5BE,0xC5BF, + 0xC5C0,0xC5C1,0xC5C2,0xC5C3,0xC5C4,0xC5C5,0xC5C6,0xC5C7,0xC5C8,0xC5C9,0xC5CA,0xC5CB,0xC5CC,0xC5CD,0xC5CE,0xC5CF, + 0xC5D0,0xC5D1,0xC5D2,0xC5D3,0xC5D4,0xC5D5,0xC5D6,0xC5D7,0xC5D8,0xC5D9,0xC5DA,0xC5DB,0xC5DC,0xC5DD,0xC5DE,0xC5DF, + 0xC5E0,0xC5E1,0xC5E2,0xC5E3,0xC5E4,0xC5E5,0xC5E6,0xC5E7,0xC5E8,0xC5E9,0xC5EA,0xC5EB,0xC5EC,0xC5ED,0xC5EE,0xC5EF, + 0xC5F0,0xC5F1,0xC5F2,0xC5F3,0xC5F4,0xC5F5,0xC5F6,0xC5F7,0xC5F8,0xC5F9,0xC5FA,0xC5FB,0xC5FC,0xC5FD,0xC5FE,0xC5FF, + 0xC600,0xC601,0xC602,0xC603,0xC604,0xC605,0xC606,0xC607,0xC608,0xC609,0xC60A,0xC60B,0xC60C,0xC60D,0xC60E,0xC60F, + 0xC610,0xC611,0xC612,0xC613,0xC614,0xC615,0xC616,0xC617,0xC618,0xC619,0xC61A,0xC61B,0xC61C,0xC61D,0xC61E,0xC61F, + 0xC620,0xC621,0xC622,0xC623,0xC624,0xC625,0xC626,0xC627,0xC628,0xC629,0xC62A,0xC62B,0xC62C,0xC62D,0xC62E,0xC62F, + 0xC630,0xC631,0xC632,0xC633,0xC634,0xC635,0xC636,0xC637,0xC638,0xC639,0xC63A,0xC63B,0xC63C,0xC63D,0xC63E,0xC63F, + 0xC640,0xC641,0xC642,0xC643,0xC644,0xC645,0xC646,0xC647,0xC648,0xC649,0xC64A,0xC64B,0xC64C,0xC64D,0xC64E,0xC64F, + 0xC650,0xC651,0xC652,0xC653,0xC654,0xC655,0xC656,0xC657,0xC658,0xC659,0xC65A,0xC65B,0xC65C,0xC65D,0xC65E,0xC65F, + 0xC660,0xC661,0xC662,0xC663,0xC664,0xC665,0xC666,0xC667,0xC668,0xC669,0xC66A,0xC66B,0xC66C,0xC66D,0xC66E,0xC66F, + 0xC670,0xC671,0xC672,0xC673,0xC674,0xC675,0xC676,0xC677,0xC678,0xC679,0xC67A,0xC67B,0xC67C,0xC67D,0xC67E,0xC67F, + 0xC680,0xC681,0xC682,0xC683,0xC684,0xC685,0xC686,0xC687,0xC688,0xC689,0xC68A,0xC68B,0xC68C,0xC68D,0xC68E,0xC68F, + 0xC690,0xC691,0xC692,0xC693,0xC694,0xC695,0xC696,0xC697,0xC698,0xC699,0xC69A,0xC69B,0xC69C,0xC69D,0xC69E,0xC69F, + 0xC6A0,0xC6A1,0xC6A2,0xC6A3,0xC6A4,0xC6A5,0xC6A6,0xC6A7,0xC6A8,0xC6A9,0xC6AA,0xC6AB,0xC6AC,0xC6AD,0xC6AE,0xC6AF, + 0xC6B0,0xC6B1,0xC6B2,0xC6B3,0xC6B4,0xC6B5,0xC6B6,0xC6B7,0xC6B8,0xC6B9,0xC6BA,0xC6BB,0xC6BC,0xC6BD,0xC6BE,0xC6BF, + 0xC6C0,0xC6C1,0xC6C2,0xC6C3,0xC6C4,0xC6C5,0xC6C6,0xC6C7,0xC6C8,0xC6C9,0xC6CA,0xC6CB,0xC6CC,0xC6CD,0xC6CE,0xC6CF, + 0xC6D0,0xC6D1,0xC6D2,0xC6D3,0xC6D4,0xC6D5,0xC6D6,0xC6D7,0xC6D8,0xC6D9,0xC6DA,0xC6DB,0xC6DC,0xC6DD,0xC6DE,0xC6DF, + 0xC6E0,0xC6E1,0xC6E2,0xC6E3,0xC6E4,0xC6E5,0xC6E6,0xC6E7,0xC6E8,0xC6E9,0xC6EA,0xC6EB,0xC6EC,0xC6ED,0xC6EE,0xC6EF, + 0xC6F0,0xC6F1,0xC6F2,0xC6F3,0xC6F4,0xC6F5,0xC6F6,0xC6F7,0xC6F8,0xC6F9,0xC6FA,0xC6FB,0xC6FC,0xC6FD,0xC6FE,0xC6FF, + 0xC700,0xC701,0xC702,0xC703,0xC704,0xC705,0xC706,0xC707,0xC708,0xC709,0xC70A,0xC70B,0xC70C,0xC70D,0xC70E,0xC70F, + 0xC710,0xC711,0xC712,0xC713,0xC714,0xC715,0xC716,0xC717,0xC718,0xC719,0xC71A,0xC71B,0xC71C,0xC71D,0xC71E,0xC71F, + 0xC720,0xC721,0xC722,0xC723,0xC724,0xC725,0xC726,0xC727,0xC728,0xC729,0xC72A,0xC72B,0xC72C,0xC72D,0xC72E,0xC72F, + 0xC730,0xC731,0xC732,0xC733,0xC734,0xC735,0xC736,0xC737,0xC738,0xC739,0xC73A,0xC73B,0xC73C,0xC73D,0xC73E,0xC73F, + 0xC740,0xC741,0xC742,0xC743,0xC744,0xC745,0xC746,0xC747,0xC748,0xC749,0xC74A,0xC74B,0xC74C,0xC74D,0xC74E,0xC74F, + 0xC750,0xC751,0xC752,0xC753,0xC754,0xC755,0xC756,0xC757,0xC758,0xC759,0xC75A,0xC75B,0xC75C,0xC75D,0xC75E,0xC75F, + 0xC760,0xC761,0xC762,0xC763,0xC764,0xC765,0xC766,0xC767,0xC768,0xC769,0xC76A,0xC76B,0xC76C,0xC76D,0xC76E,0xC76F, + 0xC770,0xC771,0xC772,0xC773,0xC774,0xC775,0xC776,0xC777,0xC778,0xC779,0xC77A,0xC77B,0xC77C,0xC77D,0xC77E,0xC77F, + 0xC780,0xC781,0xC782,0xC783,0xC784,0xC785,0xC786,0xC787,0xC788,0xC789,0xC78A,0xC78B,0xC78C,0xC78D,0xC78E,0xC78F, + 0xC790,0xC791,0xC792,0xC793,0xC794,0xC795,0xC796,0xC797,0xC798,0xC799,0xC79A,0xC79B,0xC79C,0xC79D,0xC79E,0xC79F, + 0xC7A0,0xC7A1,0xC7A2,0xC7A3,0xC7A4,0xC7A5,0xC7A6,0xC7A7,0xC7A8,0xC7A9,0xC7AA,0xC7AB,0xC7AC,0xC7AD,0xC7AE,0xC7AF, + 0xC7B0,0xC7B1,0xC7B2,0xC7B3,0xC7B4,0xC7B5,0xC7B6,0xC7B7,0xC7B8,0xC7B9,0xC7BA,0xC7BB,0xC7BC,0xC7BD,0xC7BE,0xC7BF, + 0xC7C0,0xC7C1,0xC7C2,0xC7C3,0xC7C4,0xC7C5,0xC7C6,0xC7C7,0xC7C8,0xC7C9,0xC7CA,0xC7CB,0xC7CC,0xC7CD,0xC7CE,0xC7CF, + 0xC7D0,0xC7D1,0xC7D2,0xC7D3,0xC7D4,0xC7D5,0xC7D6,0xC7D7,0xC7D8,0xC7D9,0xC7DA,0xC7DB,0xC7DC,0xC7DD,0xC7DE,0xC7DF, + 0xC7E0,0xC7E1,0xC7E2,0xC7E3,0xC7E4,0xC7E5,0xC7E6,0xC7E7,0xC7E8,0xC7E9,0xC7EA,0xC7EB,0xC7EC,0xC7ED,0xC7EE,0xC7EF, + 0xC7F0,0xC7F1,0xC7F2,0xC7F3,0xC7F4,0xC7F5,0xC7F6,0xC7F7,0xC7F8,0xC7F9,0xC7FA,0xC7FB,0xC7FC,0xC7FD,0xC7FE,0xC7FF, + 0xC800,0xC801,0xC802,0xC803,0xC804,0xC805,0xC806,0xC807,0xC808,0xC809,0xC80A,0xC80B,0xC80C,0xC80D,0xC80E,0xC80F, + 0xC810,0xC811,0xC812,0xC813,0xC814,0xC815,0xC816,0xC817,0xC818,0xC819,0xC81A,0xC81B,0xC81C,0xC81D,0xC81E,0xC81F, + 0xC820,0xC821,0xC822,0xC823,0xC824,0xC825,0xC826,0xC827,0xC828,0xC829,0xC82A,0xC82B,0xC82C,0xC82D,0xC82E,0xC82F, + 0xC830,0xC831,0xC832,0xC833,0xC834,0xC835,0xC836,0xC837,0xC838,0xC839,0xC83A,0xC83B,0xC83C,0xC83D,0xC83E,0xC83F, + 0xC840,0xC841,0xC842,0xC843,0xC844,0xC845,0xC846,0xC847,0xC848,0xC849,0xC84A,0xC84B,0xC84C,0xC84D,0xC84E,0xC84F, + 0xC850,0xC851,0xC852,0xC853,0xC854,0xC855,0xC856,0xC857,0xC858,0xC859,0xC85A,0xC85B,0xC85C,0xC85D,0xC85E,0xC85F, + 0xC860,0xC861,0xC862,0xC863,0xC864,0xC865,0xC866,0xC867,0xC868,0xC869,0xC86A,0xC86B,0xC86C,0xC86D,0xC86E,0xC86F, + 0xC870,0xC871,0xC872,0xC873,0xC874,0xC875,0xC876,0xC877,0xC878,0xC879,0xC87A,0xC87B,0xC87C,0xC87D,0xC87E,0xC87F, + 0xC880,0xC881,0xC882,0xC883,0xC884,0xC885,0xC886,0xC887,0xC888,0xC889,0xC88A,0xC88B,0xC88C,0xC88D,0xC88E,0xC88F, + 0xC890,0xC891,0xC892,0xC893,0xC894,0xC895,0xC896,0xC897,0xC898,0xC899,0xC89A,0xC89B,0xC89C,0xC89D,0xC89E,0xC89F, + 0xC8A0,0xC8A1,0xC8A2,0xC8A3,0xC8A4,0xC8A5,0xC8A6,0xC8A7,0xC8A8,0xC8A9,0xC8AA,0xC8AB,0xC8AC,0xC8AD,0xC8AE,0xC8AF, + 0xC8B0,0xC8B1,0xC8B2,0xC8B3,0xC8B4,0xC8B5,0xC8B6,0xC8B7,0xC8B8,0xC8B9,0xC8BA,0xC8BB,0xC8BC,0xC8BD,0xC8BE,0xC8BF, + 0xC8C0,0xC8C1,0xC8C2,0xC8C3,0xC8C4,0xC8C5,0xC8C6,0xC8C7,0xC8C8,0xC8C9,0xC8CA,0xC8CB,0xC8CC,0xC8CD,0xC8CE,0xC8CF, + 0xC8D0,0xC8D1,0xC8D2,0xC8D3,0xC8D4,0xC8D5,0xC8D6,0xC8D7,0xC8D8,0xC8D9,0xC8DA,0xC8DB,0xC8DC,0xC8DD,0xC8DE,0xC8DF, + 0xC8E0,0xC8E1,0xC8E2,0xC8E3,0xC8E4,0xC8E5,0xC8E6,0xC8E7,0xC8E8,0xC8E9,0xC8EA,0xC8EB,0xC8EC,0xC8ED,0xC8EE,0xC8EF, + 0xC8F0,0xC8F1,0xC8F2,0xC8F3,0xC8F4,0xC8F5,0xC8F6,0xC8F7,0xC8F8,0xC8F9,0xC8FA,0xC8FB,0xC8FC,0xC8FD,0xC8FE,0xC8FF, + 0xC900,0xC901,0xC902,0xC903,0xC904,0xC905,0xC906,0xC907,0xC908,0xC909,0xC90A,0xC90B,0xC90C,0xC90D,0xC90E,0xC90F, + 0xC910,0xC911,0xC912,0xC913,0xC914,0xC915,0xC916,0xC917,0xC918,0xC919,0xC91A,0xC91B,0xC91C,0xC91D,0xC91E,0xC91F, + 0xC920,0xC921,0xC922,0xC923,0xC924,0xC925,0xC926,0xC927,0xC928,0xC929,0xC92A,0xC92B,0xC92C,0xC92D,0xC92E,0xC92F, + 0xC930,0xC931,0xC932,0xC933,0xC934,0xC935,0xC936,0xC937,0xC938,0xC939,0xC93A,0xC93B,0xC93C,0xC93D,0xC93E,0xC93F, + 0xC940,0xC941,0xC942,0xC943,0xC944,0xC945,0xC946,0xC947,0xC948,0xC949,0xC94A,0xC94B,0xC94C,0xC94D,0xC94E,0xC94F, + 0xC950,0xC951,0xC952,0xC953,0xC954,0xC955,0xC956,0xC957,0xC958,0xC959,0xC95A,0xC95B,0xC95C,0xC95D,0xC95E,0xC95F, + 0xC960,0xC961,0xC962,0xC963,0xC964,0xC965,0xC966,0xC967,0xC968,0xC969,0xC96A,0xC96B,0xC96C,0xC96D,0xC96E,0xC96F, + 0xC970,0xC971,0xC972,0xC973,0xC974,0xC975,0xC976,0xC977,0xC978,0xC979,0xC97A,0xC97B,0xC97C,0xC97D,0xC97E,0xC97F, + 0xC980,0xC981,0xC982,0xC983,0xC984,0xC985,0xC986,0xC987,0xC988,0xC989,0xC98A,0xC98B,0xC98C,0xC98D,0xC98E,0xC98F, + 0xC990,0xC991,0xC992,0xC993,0xC994,0xC995,0xC996,0xC997,0xC998,0xC999,0xC99A,0xC99B,0xC99C,0xC99D,0xC99E,0xC99F, + 0xC9A0,0xC9A1,0xC9A2,0xC9A3,0xC9A4,0xC9A5,0xC9A6,0xC9A7,0xC9A8,0xC9A9,0xC9AA,0xC9AB,0xC9AC,0xC9AD,0xC9AE,0xC9AF, + 0xC9B0,0xC9B1,0xC9B2,0xC9B3,0xC9B4,0xC9B5,0xC9B6,0xC9B7,0xC9B8,0xC9B9,0xC9BA,0xC9BB,0xC9BC,0xC9BD,0xC9BE,0xC9BF, + 0xC9C0,0xC9C1,0xC9C2,0xC9C3,0xC9C4,0xC9C5,0xC9C6,0xC9C7,0xC9C8,0xC9C9,0xC9CA,0xC9CB,0xC9CC,0xC9CD,0xC9CE,0xC9CF, + 0xC9D0,0xC9D1,0xC9D2,0xC9D3,0xC9D4,0xC9D5,0xC9D6,0xC9D7,0xC9D8,0xC9D9,0xC9DA,0xC9DB,0xC9DC,0xC9DD,0xC9DE,0xC9DF, + 0xC9E0,0xC9E1,0xC9E2,0xC9E3,0xC9E4,0xC9E5,0xC9E6,0xC9E7,0xC9E8,0xC9E9,0xC9EA,0xC9EB,0xC9EC,0xC9ED,0xC9EE,0xC9EF, + 0xC9F0,0xC9F1,0xC9F2,0xC9F3,0xC9F4,0xC9F5,0xC9F6,0xC9F7,0xC9F8,0xC9F9,0xC9FA,0xC9FB,0xC9FC,0xC9FD,0xC9FE,0xC9FF, + 0xCA00,0xCA01,0xCA02,0xCA03,0xCA04,0xCA05,0xCA06,0xCA07,0xCA08,0xCA09,0xCA0A,0xCA0B,0xCA0C,0xCA0D,0xCA0E,0xCA0F, + 0xCA10,0xCA11,0xCA12,0xCA13,0xCA14,0xCA15,0xCA16,0xCA17,0xCA18,0xCA19,0xCA1A,0xCA1B,0xCA1C,0xCA1D,0xCA1E,0xCA1F, + 0xCA20,0xCA21,0xCA22,0xCA23,0xCA24,0xCA25,0xCA26,0xCA27,0xCA28,0xCA29,0xCA2A,0xCA2B,0xCA2C,0xCA2D,0xCA2E,0xCA2F, + 0xCA30,0xCA31,0xCA32,0xCA33,0xCA34,0xCA35,0xCA36,0xCA37,0xCA38,0xCA39,0xCA3A,0xCA3B,0xCA3C,0xCA3D,0xCA3E,0xCA3F, + 0xCA40,0xCA41,0xCA42,0xCA43,0xCA44,0xCA45,0xCA46,0xCA47,0xCA48,0xCA49,0xCA4A,0xCA4B,0xCA4C,0xCA4D,0xCA4E,0xCA4F, + 0xCA50,0xCA51,0xCA52,0xCA53,0xCA54,0xCA55,0xCA56,0xCA57,0xCA58,0xCA59,0xCA5A,0xCA5B,0xCA5C,0xCA5D,0xCA5E,0xCA5F, + 0xCA60,0xCA61,0xCA62,0xCA63,0xCA64,0xCA65,0xCA66,0xCA67,0xCA68,0xCA69,0xCA6A,0xCA6B,0xCA6C,0xCA6D,0xCA6E,0xCA6F, + 0xCA70,0xCA71,0xCA72,0xCA73,0xCA74,0xCA75,0xCA76,0xCA77,0xCA78,0xCA79,0xCA7A,0xCA7B,0xCA7C,0xCA7D,0xCA7E,0xCA7F, + 0xCA80,0xCA81,0xCA82,0xCA83,0xCA84,0xCA85,0xCA86,0xCA87,0xCA88,0xCA89,0xCA8A,0xCA8B,0xCA8C,0xCA8D,0xCA8E,0xCA8F, + 0xCA90,0xCA91,0xCA92,0xCA93,0xCA94,0xCA95,0xCA96,0xCA97,0xCA98,0xCA99,0xCA9A,0xCA9B,0xCA9C,0xCA9D,0xCA9E,0xCA9F, + 0xCAA0,0xCAA1,0xCAA2,0xCAA3,0xCAA4,0xCAA5,0xCAA6,0xCAA7,0xCAA8,0xCAA9,0xCAAA,0xCAAB,0xCAAC,0xCAAD,0xCAAE,0xCAAF, + 0xCAB0,0xCAB1,0xCAB2,0xCAB3,0xCAB4,0xCAB5,0xCAB6,0xCAB7,0xCAB8,0xCAB9,0xCABA,0xCABB,0xCABC,0xCABD,0xCABE,0xCABF, + 0xCAC0,0xCAC1,0xCAC2,0xCAC3,0xCAC4,0xCAC5,0xCAC6,0xCAC7,0xCAC8,0xCAC9,0xCACA,0xCACB,0xCACC,0xCACD,0xCACE,0xCACF, + 0xCAD0,0xCAD1,0xCAD2,0xCAD3,0xCAD4,0xCAD5,0xCAD6,0xCAD7,0xCAD8,0xCAD9,0xCADA,0xCADB,0xCADC,0xCADD,0xCADE,0xCADF, + 0xCAE0,0xCAE1,0xCAE2,0xCAE3,0xCAE4,0xCAE5,0xCAE6,0xCAE7,0xCAE8,0xCAE9,0xCAEA,0xCAEB,0xCAEC,0xCAED,0xCAEE,0xCAEF, + 0xCAF0,0xCAF1,0xCAF2,0xCAF3,0xCAF4,0xCAF5,0xCAF6,0xCAF7,0xCAF8,0xCAF9,0xCAFA,0xCAFB,0xCAFC,0xCAFD,0xCAFE,0xCAFF, + 0xCB00,0xCB01,0xCB02,0xCB03,0xCB04,0xCB05,0xCB06,0xCB07,0xCB08,0xCB09,0xCB0A,0xCB0B,0xCB0C,0xCB0D,0xCB0E,0xCB0F, + 0xCB10,0xCB11,0xCB12,0xCB13,0xCB14,0xCB15,0xCB16,0xCB17,0xCB18,0xCB19,0xCB1A,0xCB1B,0xCB1C,0xCB1D,0xCB1E,0xCB1F, + 0xCB20,0xCB21,0xCB22,0xCB23,0xCB24,0xCB25,0xCB26,0xCB27,0xCB28,0xCB29,0xCB2A,0xCB2B,0xCB2C,0xCB2D,0xCB2E,0xCB2F, + 0xCB30,0xCB31,0xCB32,0xCB33,0xCB34,0xCB35,0xCB36,0xCB37,0xCB38,0xCB39,0xCB3A,0xCB3B,0xCB3C,0xCB3D,0xCB3E,0xCB3F, + 0xCB40,0xCB41,0xCB42,0xCB43,0xCB44,0xCB45,0xCB46,0xCB47,0xCB48,0xCB49,0xCB4A,0xCB4B,0xCB4C,0xCB4D,0xCB4E,0xCB4F, + 0xCB50,0xCB51,0xCB52,0xCB53,0xCB54,0xCB55,0xCB56,0xCB57,0xCB58,0xCB59,0xCB5A,0xCB5B,0xCB5C,0xCB5D,0xCB5E,0xCB5F, + 0xCB60,0xCB61,0xCB62,0xCB63,0xCB64,0xCB65,0xCB66,0xCB67,0xCB68,0xCB69,0xCB6A,0xCB6B,0xCB6C,0xCB6D,0xCB6E,0xCB6F, + 0xCB70,0xCB71,0xCB72,0xCB73,0xCB74,0xCB75,0xCB76,0xCB77,0xCB78,0xCB79,0xCB7A,0xCB7B,0xCB7C,0xCB7D,0xCB7E,0xCB7F, + 0xCB80,0xCB81,0xCB82,0xCB83,0xCB84,0xCB85,0xCB86,0xCB87,0xCB88,0xCB89,0xCB8A,0xCB8B,0xCB8C,0xCB8D,0xCB8E,0xCB8F, + 0xCB90,0xCB91,0xCB92,0xCB93,0xCB94,0xCB95,0xCB96,0xCB97,0xCB98,0xCB99,0xCB9A,0xCB9B,0xCB9C,0xCB9D,0xCB9E,0xCB9F, + 0xCBA0,0xCBA1,0xCBA2,0xCBA3,0xCBA4,0xCBA5,0xCBA6,0xCBA7,0xCBA8,0xCBA9,0xCBAA,0xCBAB,0xCBAC,0xCBAD,0xCBAE,0xCBAF, + 0xCBB0,0xCBB1,0xCBB2,0xCBB3,0xCBB4,0xCBB5,0xCBB6,0xCBB7,0xCBB8,0xCBB9,0xCBBA,0xCBBB,0xCBBC,0xCBBD,0xCBBE,0xCBBF, + 0xCBC0,0xCBC1,0xCBC2,0xCBC3,0xCBC4,0xCBC5,0xCBC6,0xCBC7,0xCBC8,0xCBC9,0xCBCA,0xCBCB,0xCBCC,0xCBCD,0xCBCE,0xCBCF, + 0xCBD0,0xCBD1,0xCBD2,0xCBD3,0xCBD4,0xCBD5,0xCBD6,0xCBD7,0xCBD8,0xCBD9,0xCBDA,0xCBDB,0xCBDC,0xCBDD,0xCBDE,0xCBDF, + 0xCBE0,0xCBE1,0xCBE2,0xCBE3,0xCBE4,0xCBE5,0xCBE6,0xCBE7,0xCBE8,0xCBE9,0xCBEA,0xCBEB,0xCBEC,0xCBED,0xCBEE,0xCBEF, + 0xCBF0,0xCBF1,0xCBF2,0xCBF3,0xCBF4,0xCBF5,0xCBF6,0xCBF7,0xCBF8,0xCBF9,0xCBFA,0xCBFB,0xCBFC,0xCBFD,0xCBFE,0xCBFF, + 0xCC00,0xCC01,0xCC02,0xCC03,0xCC04,0xCC05,0xCC06,0xCC07,0xCC08,0xCC09,0xCC0A,0xCC0B,0xCC0C,0xCC0D,0xCC0E,0xCC0F, + 0xCC10,0xCC11,0xCC12,0xCC13,0xCC14,0xCC15,0xCC16,0xCC17,0xCC18,0xCC19,0xCC1A,0xCC1B,0xCC1C,0xCC1D,0xCC1E,0xCC1F, + 0xCC20,0xCC21,0xCC22,0xCC23,0xCC24,0xCC25,0xCC26,0xCC27,0xCC28,0xCC29,0xCC2A,0xCC2B,0xCC2C,0xCC2D,0xCC2E,0xCC2F, + 0xCC30,0xCC31,0xCC32,0xCC33,0xCC34,0xCC35,0xCC36,0xCC37,0xCC38,0xCC39,0xCC3A,0xCC3B,0xCC3C,0xCC3D,0xCC3E,0xCC3F, + 0xCC40,0xCC41,0xCC42,0xCC43,0xCC44,0xCC45,0xCC46,0xCC47,0xCC48,0xCC49,0xCC4A,0xCC4B,0xCC4C,0xCC4D,0xCC4E,0xCC4F, + 0xCC50,0xCC51,0xCC52,0xCC53,0xCC54,0xCC55,0xCC56,0xCC57,0xCC58,0xCC59,0xCC5A,0xCC5B,0xCC5C,0xCC5D,0xCC5E,0xCC5F, + 0xCC60,0xCC61,0xCC62,0xCC63,0xCC64,0xCC65,0xCC66,0xCC67,0xCC68,0xCC69,0xCC6A,0xCC6B,0xCC6C,0xCC6D,0xCC6E,0xCC6F, + 0xCC70,0xCC71,0xCC72,0xCC73,0xCC74,0xCC75,0xCC76,0xCC77,0xCC78,0xCC79,0xCC7A,0xCC7B,0xCC7C,0xCC7D,0xCC7E,0xCC7F, + 0xCC80,0xCC81,0xCC82,0xCC83,0xCC84,0xCC85,0xCC86,0xCC87,0xCC88,0xCC89,0xCC8A,0xCC8B,0xCC8C,0xCC8D,0xCC8E,0xCC8F, + 0xCC90,0xCC91,0xCC92,0xCC93,0xCC94,0xCC95,0xCC96,0xCC97,0xCC98,0xCC99,0xCC9A,0xCC9B,0xCC9C,0xCC9D,0xCC9E,0xCC9F, + 0xCCA0,0xCCA1,0xCCA2,0xCCA3,0xCCA4,0xCCA5,0xCCA6,0xCCA7,0xCCA8,0xCCA9,0xCCAA,0xCCAB,0xCCAC,0xCCAD,0xCCAE,0xCCAF, + 0xCCB0,0xCCB1,0xCCB2,0xCCB3,0xCCB4,0xCCB5,0xCCB6,0xCCB7,0xCCB8,0xCCB9,0xCCBA,0xCCBB,0xCCBC,0xCCBD,0xCCBE,0xCCBF, + 0xCCC0,0xCCC1,0xCCC2,0xCCC3,0xCCC4,0xCCC5,0xCCC6,0xCCC7,0xCCC8,0xCCC9,0xCCCA,0xCCCB,0xCCCC,0xCCCD,0xCCCE,0xCCCF, + 0xCCD0,0xCCD1,0xCCD2,0xCCD3,0xCCD4,0xCCD5,0xCCD6,0xCCD7,0xCCD8,0xCCD9,0xCCDA,0xCCDB,0xCCDC,0xCCDD,0xCCDE,0xCCDF, + 0xCCE0,0xCCE1,0xCCE2,0xCCE3,0xCCE4,0xCCE5,0xCCE6,0xCCE7,0xCCE8,0xCCE9,0xCCEA,0xCCEB,0xCCEC,0xCCED,0xCCEE,0xCCEF, + 0xCCF0,0xCCF1,0xCCF2,0xCCF3,0xCCF4,0xCCF5,0xCCF6,0xCCF7,0xCCF8,0xCCF9,0xCCFA,0xCCFB,0xCCFC,0xCCFD,0xCCFE,0xCCFF, + 0xCD00,0xCD01,0xCD02,0xCD03,0xCD04,0xCD05,0xCD06,0xCD07,0xCD08,0xCD09,0xCD0A,0xCD0B,0xCD0C,0xCD0D,0xCD0E,0xCD0F, + 0xCD10,0xCD11,0xCD12,0xCD13,0xCD14,0xCD15,0xCD16,0xCD17,0xCD18,0xCD19,0xCD1A,0xCD1B,0xCD1C,0xCD1D,0xCD1E,0xCD1F, + 0xCD20,0xCD21,0xCD22,0xCD23,0xCD24,0xCD25,0xCD26,0xCD27,0xCD28,0xCD29,0xCD2A,0xCD2B,0xCD2C,0xCD2D,0xCD2E,0xCD2F, + 0xCD30,0xCD31,0xCD32,0xCD33,0xCD34,0xCD35,0xCD36,0xCD37,0xCD38,0xCD39,0xCD3A,0xCD3B,0xCD3C,0xCD3D,0xCD3E,0xCD3F, + 0xCD40,0xCD41,0xCD42,0xCD43,0xCD44,0xCD45,0xCD46,0xCD47,0xCD48,0xCD49,0xCD4A,0xCD4B,0xCD4C,0xCD4D,0xCD4E,0xCD4F, + 0xCD50,0xCD51,0xCD52,0xCD53,0xCD54,0xCD55,0xCD56,0xCD57,0xCD58,0xCD59,0xCD5A,0xCD5B,0xCD5C,0xCD5D,0xCD5E,0xCD5F, + 0xCD60,0xCD61,0xCD62,0xCD63,0xCD64,0xCD65,0xCD66,0xCD67,0xCD68,0xCD69,0xCD6A,0xCD6B,0xCD6C,0xCD6D,0xCD6E,0xCD6F, + 0xCD70,0xCD71,0xCD72,0xCD73,0xCD74,0xCD75,0xCD76,0xCD77,0xCD78,0xCD79,0xCD7A,0xCD7B,0xCD7C,0xCD7D,0xCD7E,0xCD7F, + 0xCD80,0xCD81,0xCD82,0xCD83,0xCD84,0xCD85,0xCD86,0xCD87,0xCD88,0xCD89,0xCD8A,0xCD8B,0xCD8C,0xCD8D,0xCD8E,0xCD8F, + 0xCD90,0xCD91,0xCD92,0xCD93,0xCD94,0xCD95,0xCD96,0xCD97,0xCD98,0xCD99,0xCD9A,0xCD9B,0xCD9C,0xCD9D,0xCD9E,0xCD9F, + 0xCDA0,0xCDA1,0xCDA2,0xCDA3,0xCDA4,0xCDA5,0xCDA6,0xCDA7,0xCDA8,0xCDA9,0xCDAA,0xCDAB,0xCDAC,0xCDAD,0xCDAE,0xCDAF, + 0xCDB0,0xCDB1,0xCDB2,0xCDB3,0xCDB4,0xCDB5,0xCDB6,0xCDB7,0xCDB8,0xCDB9,0xCDBA,0xCDBB,0xCDBC,0xCDBD,0xCDBE,0xCDBF, + 0xCDC0,0xCDC1,0xCDC2,0xCDC3,0xCDC4,0xCDC5,0xCDC6,0xCDC7,0xCDC8,0xCDC9,0xCDCA,0xCDCB,0xCDCC,0xCDCD,0xCDCE,0xCDCF, + 0xCDD0,0xCDD1,0xCDD2,0xCDD3,0xCDD4,0xCDD5,0xCDD6,0xCDD7,0xCDD8,0xCDD9,0xCDDA,0xCDDB,0xCDDC,0xCDDD,0xCDDE,0xCDDF, + 0xCDE0,0xCDE1,0xCDE2,0xCDE3,0xCDE4,0xCDE5,0xCDE6,0xCDE7,0xCDE8,0xCDE9,0xCDEA,0xCDEB,0xCDEC,0xCDED,0xCDEE,0xCDEF, + 0xCDF0,0xCDF1,0xCDF2,0xCDF3,0xCDF4,0xCDF5,0xCDF6,0xCDF7,0xCDF8,0xCDF9,0xCDFA,0xCDFB,0xCDFC,0xCDFD,0xCDFE,0xCDFF, + 0xCE00,0xCE01,0xCE02,0xCE03,0xCE04,0xCE05,0xCE06,0xCE07,0xCE08,0xCE09,0xCE0A,0xCE0B,0xCE0C,0xCE0D,0xCE0E,0xCE0F, + 0xCE10,0xCE11,0xCE12,0xCE13,0xCE14,0xCE15,0xCE16,0xCE17,0xCE18,0xCE19,0xCE1A,0xCE1B,0xCE1C,0xCE1D,0xCE1E,0xCE1F, + 0xCE20,0xCE21,0xCE22,0xCE23,0xCE24,0xCE25,0xCE26,0xCE27,0xCE28,0xCE29,0xCE2A,0xCE2B,0xCE2C,0xCE2D,0xCE2E,0xCE2F, + 0xCE30,0xCE31,0xCE32,0xCE33,0xCE34,0xCE35,0xCE36,0xCE37,0xCE38,0xCE39,0xCE3A,0xCE3B,0xCE3C,0xCE3D,0xCE3E,0xCE3F, + 0xCE40,0xCE41,0xCE42,0xCE43,0xCE44,0xCE45,0xCE46,0xCE47,0xCE48,0xCE49,0xCE4A,0xCE4B,0xCE4C,0xCE4D,0xCE4E,0xCE4F, + 0xCE50,0xCE51,0xCE52,0xCE53,0xCE54,0xCE55,0xCE56,0xCE57,0xCE58,0xCE59,0xCE5A,0xCE5B,0xCE5C,0xCE5D,0xCE5E,0xCE5F, + 0xCE60,0xCE61,0xCE62,0xCE63,0xCE64,0xCE65,0xCE66,0xCE67,0xCE68,0xCE69,0xCE6A,0xCE6B,0xCE6C,0xCE6D,0xCE6E,0xCE6F, + 0xCE70,0xCE71,0xCE72,0xCE73,0xCE74,0xCE75,0xCE76,0xCE77,0xCE78,0xCE79,0xCE7A,0xCE7B,0xCE7C,0xCE7D,0xCE7E,0xCE7F, + 0xCE80,0xCE81,0xCE82,0xCE83,0xCE84,0xCE85,0xCE86,0xCE87,0xCE88,0xCE89,0xCE8A,0xCE8B,0xCE8C,0xCE8D,0xCE8E,0xCE8F, + 0xCE90,0xCE91,0xCE92,0xCE93,0xCE94,0xCE95,0xCE96,0xCE97,0xCE98,0xCE99,0xCE9A,0xCE9B,0xCE9C,0xCE9D,0xCE9E,0xCE9F, + 0xCEA0,0xCEA1,0xCEA2,0xCEA3,0xCEA4,0xCEA5,0xCEA6,0xCEA7,0xCEA8,0xCEA9,0xCEAA,0xCEAB,0xCEAC,0xCEAD,0xCEAE,0xCEAF, + 0xCEB0,0xCEB1,0xCEB2,0xCEB3,0xCEB4,0xCEB5,0xCEB6,0xCEB7,0xCEB8,0xCEB9,0xCEBA,0xCEBB,0xCEBC,0xCEBD,0xCEBE,0xCEBF, + 0xCEC0,0xCEC1,0xCEC2,0xCEC3,0xCEC4,0xCEC5,0xCEC6,0xCEC7,0xCEC8,0xCEC9,0xCECA,0xCECB,0xCECC,0xCECD,0xCECE,0xCECF, + 0xCED0,0xCED1,0xCED2,0xCED3,0xCED4,0xCED5,0xCED6,0xCED7,0xCED8,0xCED9,0xCEDA,0xCEDB,0xCEDC,0xCEDD,0xCEDE,0xCEDF, + 0xCEE0,0xCEE1,0xCEE2,0xCEE3,0xCEE4,0xCEE5,0xCEE6,0xCEE7,0xCEE8,0xCEE9,0xCEEA,0xCEEB,0xCEEC,0xCEED,0xCEEE,0xCEEF, + 0xCEF0,0xCEF1,0xCEF2,0xCEF3,0xCEF4,0xCEF5,0xCEF6,0xCEF7,0xCEF8,0xCEF9,0xCEFA,0xCEFB,0xCEFC,0xCEFD,0xCEFE,0xCEFF, + 0xCF00,0xCF01,0xCF02,0xCF03,0xCF04,0xCF05,0xCF06,0xCF07,0xCF08,0xCF09,0xCF0A,0xCF0B,0xCF0C,0xCF0D,0xCF0E,0xCF0F, + 0xCF10,0xCF11,0xCF12,0xCF13,0xCF14,0xCF15,0xCF16,0xCF17,0xCF18,0xCF19,0xCF1A,0xCF1B,0xCF1C,0xCF1D,0xCF1E,0xCF1F, + 0xCF20,0xCF21,0xCF22,0xCF23,0xCF24,0xCF25,0xCF26,0xCF27,0xCF28,0xCF29,0xCF2A,0xCF2B,0xCF2C,0xCF2D,0xCF2E,0xCF2F, + 0xCF30,0xCF31,0xCF32,0xCF33,0xCF34,0xCF35,0xCF36,0xCF37,0xCF38,0xCF39,0xCF3A,0xCF3B,0xCF3C,0xCF3D,0xCF3E,0xCF3F, + 0xCF40,0xCF41,0xCF42,0xCF43,0xCF44,0xCF45,0xCF46,0xCF47,0xCF48,0xCF49,0xCF4A,0xCF4B,0xCF4C,0xCF4D,0xCF4E,0xCF4F, + 0xCF50,0xCF51,0xCF52,0xCF53,0xCF54,0xCF55,0xCF56,0xCF57,0xCF58,0xCF59,0xCF5A,0xCF5B,0xCF5C,0xCF5D,0xCF5E,0xCF5F, + 0xCF60,0xCF61,0xCF62,0xCF63,0xCF64,0xCF65,0xCF66,0xCF67,0xCF68,0xCF69,0xCF6A,0xCF6B,0xCF6C,0xCF6D,0xCF6E,0xCF6F, + 0xCF70,0xCF71,0xCF72,0xCF73,0xCF74,0xCF75,0xCF76,0xCF77,0xCF78,0xCF79,0xCF7A,0xCF7B,0xCF7C,0xCF7D,0xCF7E,0xCF7F, + 0xCF80,0xCF81,0xCF82,0xCF83,0xCF84,0xCF85,0xCF86,0xCF87,0xCF88,0xCF89,0xCF8A,0xCF8B,0xCF8C,0xCF8D,0xCF8E,0xCF8F, + 0xCF90,0xCF91,0xCF92,0xCF93,0xCF94,0xCF95,0xCF96,0xCF97,0xCF98,0xCF99,0xCF9A,0xCF9B,0xCF9C,0xCF9D,0xCF9E,0xCF9F, + 0xCFA0,0xCFA1,0xCFA2,0xCFA3,0xCFA4,0xCFA5,0xCFA6,0xCFA7,0xCFA8,0xCFA9,0xCFAA,0xCFAB,0xCFAC,0xCFAD,0xCFAE,0xCFAF, + 0xCFB0,0xCFB1,0xCFB2,0xCFB3,0xCFB4,0xCFB5,0xCFB6,0xCFB7,0xCFB8,0xCFB9,0xCFBA,0xCFBB,0xCFBC,0xCFBD,0xCFBE,0xCFBF, + 0xCFC0,0xCFC1,0xCFC2,0xCFC3,0xCFC4,0xCFC5,0xCFC6,0xCFC7,0xCFC8,0xCFC9,0xCFCA,0xCFCB,0xCFCC,0xCFCD,0xCFCE,0xCFCF, + 0xCFD0,0xCFD1,0xCFD2,0xCFD3,0xCFD4,0xCFD5,0xCFD6,0xCFD7,0xCFD8,0xCFD9,0xCFDA,0xCFDB,0xCFDC,0xCFDD,0xCFDE,0xCFDF, + 0xCFE0,0xCFE1,0xCFE2,0xCFE3,0xCFE4,0xCFE5,0xCFE6,0xCFE7,0xCFE8,0xCFE9,0xCFEA,0xCFEB,0xCFEC,0xCFED,0xCFEE,0xCFEF, + 0xCFF0,0xCFF1,0xCFF2,0xCFF3,0xCFF4,0xCFF5,0xCFF6,0xCFF7,0xCFF8,0xCFF9,0xCFFA,0xCFFB,0xCFFC,0xCFFD,0xCFFE,0xCFFF, + 0xD000,0xD001,0xD002,0xD003,0xD004,0xD005,0xD006,0xD007,0xD008,0xD009,0xD00A,0xD00B,0xD00C,0xD00D,0xD00E,0xD00F, + 0xD010,0xD011,0xD012,0xD013,0xD014,0xD015,0xD016,0xD017,0xD018,0xD019,0xD01A,0xD01B,0xD01C,0xD01D,0xD01E,0xD01F, + 0xD020,0xD021,0xD022,0xD023,0xD024,0xD025,0xD026,0xD027,0xD028,0xD029,0xD02A,0xD02B,0xD02C,0xD02D,0xD02E,0xD02F, + 0xD030,0xD031,0xD032,0xD033,0xD034,0xD035,0xD036,0xD037,0xD038,0xD039,0xD03A,0xD03B,0xD03C,0xD03D,0xD03E,0xD03F, + 0xD040,0xD041,0xD042,0xD043,0xD044,0xD045,0xD046,0xD047,0xD048,0xD049,0xD04A,0xD04B,0xD04C,0xD04D,0xD04E,0xD04F, + 0xD050,0xD051,0xD052,0xD053,0xD054,0xD055,0xD056,0xD057,0xD058,0xD059,0xD05A,0xD05B,0xD05C,0xD05D,0xD05E,0xD05F, + 0xD060,0xD061,0xD062,0xD063,0xD064,0xD065,0xD066,0xD067,0xD068,0xD069,0xD06A,0xD06B,0xD06C,0xD06D,0xD06E,0xD06F, + 0xD070,0xD071,0xD072,0xD073,0xD074,0xD075,0xD076,0xD077,0xD078,0xD079,0xD07A,0xD07B,0xD07C,0xD07D,0xD07E,0xD07F, + 0xD080,0xD081,0xD082,0xD083,0xD084,0xD085,0xD086,0xD087,0xD088,0xD089,0xD08A,0xD08B,0xD08C,0xD08D,0xD08E,0xD08F, + 0xD090,0xD091,0xD092,0xD093,0xD094,0xD095,0xD096,0xD097,0xD098,0xD099,0xD09A,0xD09B,0xD09C,0xD09D,0xD09E,0xD09F, + 0xD0A0,0xD0A1,0xD0A2,0xD0A3,0xD0A4,0xD0A5,0xD0A6,0xD0A7,0xD0A8,0xD0A9,0xD0AA,0xD0AB,0xD0AC,0xD0AD,0xD0AE,0xD0AF, + 0xD0B0,0xD0B1,0xD0B2,0xD0B3,0xD0B4,0xD0B5,0xD0B6,0xD0B7,0xD0B8,0xD0B9,0xD0BA,0xD0BB,0xD0BC,0xD0BD,0xD0BE,0xD0BF, + 0xD0C0,0xD0C1,0xD0C2,0xD0C3,0xD0C4,0xD0C5,0xD0C6,0xD0C7,0xD0C8,0xD0C9,0xD0CA,0xD0CB,0xD0CC,0xD0CD,0xD0CE,0xD0CF, + 0xD0D0,0xD0D1,0xD0D2,0xD0D3,0xD0D4,0xD0D5,0xD0D6,0xD0D7,0xD0D8,0xD0D9,0xD0DA,0xD0DB,0xD0DC,0xD0DD,0xD0DE,0xD0DF, + 0xD0E0,0xD0E1,0xD0E2,0xD0E3,0xD0E4,0xD0E5,0xD0E6,0xD0E7,0xD0E8,0xD0E9,0xD0EA,0xD0EB,0xD0EC,0xD0ED,0xD0EE,0xD0EF, + 0xD0F0,0xD0F1,0xD0F2,0xD0F3,0xD0F4,0xD0F5,0xD0F6,0xD0F7,0xD0F8,0xD0F9,0xD0FA,0xD0FB,0xD0FC,0xD0FD,0xD0FE,0xD0FF, + 0xD100,0xD101,0xD102,0xD103,0xD104,0xD105,0xD106,0xD107,0xD108,0xD109,0xD10A,0xD10B,0xD10C,0xD10D,0xD10E,0xD10F, + 0xD110,0xD111,0xD112,0xD113,0xD114,0xD115,0xD116,0xD117,0xD118,0xD119,0xD11A,0xD11B,0xD11C,0xD11D,0xD11E,0xD11F, + 0xD120,0xD121,0xD122,0xD123,0xD124,0xD125,0xD126,0xD127,0xD128,0xD129,0xD12A,0xD12B,0xD12C,0xD12D,0xD12E,0xD12F, + 0xD130,0xD131,0xD132,0xD133,0xD134,0xD135,0xD136,0xD137,0xD138,0xD139,0xD13A,0xD13B,0xD13C,0xD13D,0xD13E,0xD13F, + 0xD140,0xD141,0xD142,0xD143,0xD144,0xD145,0xD146,0xD147,0xD148,0xD149,0xD14A,0xD14B,0xD14C,0xD14D,0xD14E,0xD14F, + 0xD150,0xD151,0xD152,0xD153,0xD154,0xD155,0xD156,0xD157,0xD158,0xD159,0xD15A,0xD15B,0xD15C,0xD15D,0xD15E,0xD15F, + 0xD160,0xD161,0xD162,0xD163,0xD164,0xD165,0xD166,0xD167,0xD168,0xD169,0xD16A,0xD16B,0xD16C,0xD16D,0xD16E,0xD16F, + 0xD170,0xD171,0xD172,0xD173,0xD174,0xD175,0xD176,0xD177,0xD178,0xD179,0xD17A,0xD17B,0xD17C,0xD17D,0xD17E,0xD17F, + 0xD180,0xD181,0xD182,0xD183,0xD184,0xD185,0xD186,0xD187,0xD188,0xD189,0xD18A,0xD18B,0xD18C,0xD18D,0xD18E,0xD18F, + 0xD190,0xD191,0xD192,0xD193,0xD194,0xD195,0xD196,0xD197,0xD198,0xD199,0xD19A,0xD19B,0xD19C,0xD19D,0xD19E,0xD19F, + 0xD1A0,0xD1A1,0xD1A2,0xD1A3,0xD1A4,0xD1A5,0xD1A6,0xD1A7,0xD1A8,0xD1A9,0xD1AA,0xD1AB,0xD1AC,0xD1AD,0xD1AE,0xD1AF, + 0xD1B0,0xD1B1,0xD1B2,0xD1B3,0xD1B4,0xD1B5,0xD1B6,0xD1B7,0xD1B8,0xD1B9,0xD1BA,0xD1BB,0xD1BC,0xD1BD,0xD1BE,0xD1BF, + 0xD1C0,0xD1C1,0xD1C2,0xD1C3,0xD1C4,0xD1C5,0xD1C6,0xD1C7,0xD1C8,0xD1C9,0xD1CA,0xD1CB,0xD1CC,0xD1CD,0xD1CE,0xD1CF, + 0xD1D0,0xD1D1,0xD1D2,0xD1D3,0xD1D4,0xD1D5,0xD1D6,0xD1D7,0xD1D8,0xD1D9,0xD1DA,0xD1DB,0xD1DC,0xD1DD,0xD1DE,0xD1DF, + 0xD1E0,0xD1E1,0xD1E2,0xD1E3,0xD1E4,0xD1E5,0xD1E6,0xD1E7,0xD1E8,0xD1E9,0xD1EA,0xD1EB,0xD1EC,0xD1ED,0xD1EE,0xD1EF, + 0xD1F0,0xD1F1,0xD1F2,0xD1F3,0xD1F4,0xD1F5,0xD1F6,0xD1F7,0xD1F8,0xD1F9,0xD1FA,0xD1FB,0xD1FC,0xD1FD,0xD1FE,0xD1FF, + 0xD200,0xD201,0xD202,0xD203,0xD204,0xD205,0xD206,0xD207,0xD208,0xD209,0xD20A,0xD20B,0xD20C,0xD20D,0xD20E,0xD20F, + 0xD210,0xD211,0xD212,0xD213,0xD214,0xD215,0xD216,0xD217,0xD218,0xD219,0xD21A,0xD21B,0xD21C,0xD21D,0xD21E,0xD21F, + 0xD220,0xD221,0xD222,0xD223,0xD224,0xD225,0xD226,0xD227,0xD228,0xD229,0xD22A,0xD22B,0xD22C,0xD22D,0xD22E,0xD22F, + 0xD230,0xD231,0xD232,0xD233,0xD234,0xD235,0xD236,0xD237,0xD238,0xD239,0xD23A,0xD23B,0xD23C,0xD23D,0xD23E,0xD23F, + 0xD240,0xD241,0xD242,0xD243,0xD244,0xD245,0xD246,0xD247,0xD248,0xD249,0xD24A,0xD24B,0xD24C,0xD24D,0xD24E,0xD24F, + 0xD250,0xD251,0xD252,0xD253,0xD254,0xD255,0xD256,0xD257,0xD258,0xD259,0xD25A,0xD25B,0xD25C,0xD25D,0xD25E,0xD25F, + 0xD260,0xD261,0xD262,0xD263,0xD264,0xD265,0xD266,0xD267,0xD268,0xD269,0xD26A,0xD26B,0xD26C,0xD26D,0xD26E,0xD26F, + 0xD270,0xD271,0xD272,0xD273,0xD274,0xD275,0xD276,0xD277,0xD278,0xD279,0xD27A,0xD27B,0xD27C,0xD27D,0xD27E,0xD27F, + 0xD280,0xD281,0xD282,0xD283,0xD284,0xD285,0xD286,0xD287,0xD288,0xD289,0xD28A,0xD28B,0xD28C,0xD28D,0xD28E,0xD28F, + 0xD290,0xD291,0xD292,0xD293,0xD294,0xD295,0xD296,0xD297,0xD298,0xD299,0xD29A,0xD29B,0xD29C,0xD29D,0xD29E,0xD29F, + 0xD2A0,0xD2A1,0xD2A2,0xD2A3,0xD2A4,0xD2A5,0xD2A6,0xD2A7,0xD2A8,0xD2A9,0xD2AA,0xD2AB,0xD2AC,0xD2AD,0xD2AE,0xD2AF, + 0xD2B0,0xD2B1,0xD2B2,0xD2B3,0xD2B4,0xD2B5,0xD2B6,0xD2B7,0xD2B8,0xD2B9,0xD2BA,0xD2BB,0xD2BC,0xD2BD,0xD2BE,0xD2BF, + 0xD2C0,0xD2C1,0xD2C2,0xD2C3,0xD2C4,0xD2C5,0xD2C6,0xD2C7,0xD2C8,0xD2C9,0xD2CA,0xD2CB,0xD2CC,0xD2CD,0xD2CE,0xD2CF, + 0xD2D0,0xD2D1,0xD2D2,0xD2D3,0xD2D4,0xD2D5,0xD2D6,0xD2D7,0xD2D8,0xD2D9,0xD2DA,0xD2DB,0xD2DC,0xD2DD,0xD2DE,0xD2DF, + 0xD2E0,0xD2E1,0xD2E2,0xD2E3,0xD2E4,0xD2E5,0xD2E6,0xD2E7,0xD2E8,0xD2E9,0xD2EA,0xD2EB,0xD2EC,0xD2ED,0xD2EE,0xD2EF, + 0xD2F0,0xD2F1,0xD2F2,0xD2F3,0xD2F4,0xD2F5,0xD2F6,0xD2F7,0xD2F8,0xD2F9,0xD2FA,0xD2FB,0xD2FC,0xD2FD,0xD2FE,0xD2FF, + 0xD300,0xD301,0xD302,0xD303,0xD304,0xD305,0xD306,0xD307,0xD308,0xD309,0xD30A,0xD30B,0xD30C,0xD30D,0xD30E,0xD30F, + 0xD310,0xD311,0xD312,0xD313,0xD314,0xD315,0xD316,0xD317,0xD318,0xD319,0xD31A,0xD31B,0xD31C,0xD31D,0xD31E,0xD31F, + 0xD320,0xD321,0xD322,0xD323,0xD324,0xD325,0xD326,0xD327,0xD328,0xD329,0xD32A,0xD32B,0xD32C,0xD32D,0xD32E,0xD32F, + 0xD330,0xD331,0xD332,0xD333,0xD334,0xD335,0xD336,0xD337,0xD338,0xD339,0xD33A,0xD33B,0xD33C,0xD33D,0xD33E,0xD33F, + 0xD340,0xD341,0xD342,0xD343,0xD344,0xD345,0xD346,0xD347,0xD348,0xD349,0xD34A,0xD34B,0xD34C,0xD34D,0xD34E,0xD34F, + 0xD350,0xD351,0xD352,0xD353,0xD354,0xD355,0xD356,0xD357,0xD358,0xD359,0xD35A,0xD35B,0xD35C,0xD35D,0xD35E,0xD35F, + 0xD360,0xD361,0xD362,0xD363,0xD364,0xD365,0xD366,0xD367,0xD368,0xD369,0xD36A,0xD36B,0xD36C,0xD36D,0xD36E,0xD36F, + 0xD370,0xD371,0xD372,0xD373,0xD374,0xD375,0xD376,0xD377,0xD378,0xD379,0xD37A,0xD37B,0xD37C,0xD37D,0xD37E,0xD37F, + 0xD380,0xD381,0xD382,0xD383,0xD384,0xD385,0xD386,0xD387,0xD388,0xD389,0xD38A,0xD38B,0xD38C,0xD38D,0xD38E,0xD38F, + 0xD390,0xD391,0xD392,0xD393,0xD394,0xD395,0xD396,0xD397,0xD398,0xD399,0xD39A,0xD39B,0xD39C,0xD39D,0xD39E,0xD39F, + 0xD3A0,0xD3A1,0xD3A2,0xD3A3,0xD3A4,0xD3A5,0xD3A6,0xD3A7,0xD3A8,0xD3A9,0xD3AA,0xD3AB,0xD3AC,0xD3AD,0xD3AE,0xD3AF, + 0xD3B0,0xD3B1,0xD3B2,0xD3B3,0xD3B4,0xD3B5,0xD3B6,0xD3B7,0xD3B8,0xD3B9,0xD3BA,0xD3BB,0xD3BC,0xD3BD,0xD3BE,0xD3BF, + 0xD3C0,0xD3C1,0xD3C2,0xD3C3,0xD3C4,0xD3C5,0xD3C6,0xD3C7,0xD3C8,0xD3C9,0xD3CA,0xD3CB,0xD3CC,0xD3CD,0xD3CE,0xD3CF, + 0xD3D0,0xD3D1,0xD3D2,0xD3D3,0xD3D4,0xD3D5,0xD3D6,0xD3D7,0xD3D8,0xD3D9,0xD3DA,0xD3DB,0xD3DC,0xD3DD,0xD3DE,0xD3DF, + 0xD3E0,0xD3E1,0xD3E2,0xD3E3,0xD3E4,0xD3E5,0xD3E6,0xD3E7,0xD3E8,0xD3E9,0xD3EA,0xD3EB,0xD3EC,0xD3ED,0xD3EE,0xD3EF, + 0xD3F0,0xD3F1,0xD3F2,0xD3F3,0xD3F4,0xD3F5,0xD3F6,0xD3F7,0xD3F8,0xD3F9,0xD3FA,0xD3FB,0xD3FC,0xD3FD,0xD3FE,0xD3FF, + 0xD400,0xD401,0xD402,0xD403,0xD404,0xD405,0xD406,0xD407,0xD408,0xD409,0xD40A,0xD40B,0xD40C,0xD40D,0xD40E,0xD40F, + 0xD410,0xD411,0xD412,0xD413,0xD414,0xD415,0xD416,0xD417,0xD418,0xD419,0xD41A,0xD41B,0xD41C,0xD41D,0xD41E,0xD41F, + 0xD420,0xD421,0xD422,0xD423,0xD424,0xD425,0xD426,0xD427,0xD428,0xD429,0xD42A,0xD42B,0xD42C,0xD42D,0xD42E,0xD42F, + 0xD430,0xD431,0xD432,0xD433,0xD434,0xD435,0xD436,0xD437,0xD438,0xD439,0xD43A,0xD43B,0xD43C,0xD43D,0xD43E,0xD43F, + 0xD440,0xD441,0xD442,0xD443,0xD444,0xD445,0xD446,0xD447,0xD448,0xD449,0xD44A,0xD44B,0xD44C,0xD44D,0xD44E,0xD44F, + 0xD450,0xD451,0xD452,0xD453,0xD454,0xD455,0xD456,0xD457,0xD458,0xD459,0xD45A,0xD45B,0xD45C,0xD45D,0xD45E,0xD45F, + 0xD460,0xD461,0xD462,0xD463,0xD464,0xD465,0xD466,0xD467,0xD468,0xD469,0xD46A,0xD46B,0xD46C,0xD46D,0xD46E,0xD46F, + 0xD470,0xD471,0xD472,0xD473,0xD474,0xD475,0xD476,0xD477,0xD478,0xD479,0xD47A,0xD47B,0xD47C,0xD47D,0xD47E,0xD47F, + 0xD480,0xD481,0xD482,0xD483,0xD484,0xD485,0xD486,0xD487,0xD488,0xD489,0xD48A,0xD48B,0xD48C,0xD48D,0xD48E,0xD48F, + 0xD490,0xD491,0xD492,0xD493,0xD494,0xD495,0xD496,0xD497,0xD498,0xD499,0xD49A,0xD49B,0xD49C,0xD49D,0xD49E,0xD49F, + 0xD4A0,0xD4A1,0xD4A2,0xD4A3,0xD4A4,0xD4A5,0xD4A6,0xD4A7,0xD4A8,0xD4A9,0xD4AA,0xD4AB,0xD4AC,0xD4AD,0xD4AE,0xD4AF, + 0xD4B0,0xD4B1,0xD4B2,0xD4B3,0xD4B4,0xD4B5,0xD4B6,0xD4B7,0xD4B8,0xD4B9,0xD4BA,0xD4BB,0xD4BC,0xD4BD,0xD4BE,0xD4BF, + 0xD4C0,0xD4C1,0xD4C2,0xD4C3,0xD4C4,0xD4C5,0xD4C6,0xD4C7,0xD4C8,0xD4C9,0xD4CA,0xD4CB,0xD4CC,0xD4CD,0xD4CE,0xD4CF, + 0xD4D0,0xD4D1,0xD4D2,0xD4D3,0xD4D4,0xD4D5,0xD4D6,0xD4D7,0xD4D8,0xD4D9,0xD4DA,0xD4DB,0xD4DC,0xD4DD,0xD4DE,0xD4DF, + 0xD4E0,0xD4E1,0xD4E2,0xD4E3,0xD4E4,0xD4E5,0xD4E6,0xD4E7,0xD4E8,0xD4E9,0xD4EA,0xD4EB,0xD4EC,0xD4ED,0xD4EE,0xD4EF, + 0xD4F0,0xD4F1,0xD4F2,0xD4F3,0xD4F4,0xD4F5,0xD4F6,0xD4F7,0xD4F8,0xD4F9,0xD4FA,0xD4FB,0xD4FC,0xD4FD,0xD4FE,0xD4FF, + 0xD500,0xD501,0xD502,0xD503,0xD504,0xD505,0xD506,0xD507,0xD508,0xD509,0xD50A,0xD50B,0xD50C,0xD50D,0xD50E,0xD50F, + 0xD510,0xD511,0xD512,0xD513,0xD514,0xD515,0xD516,0xD517,0xD518,0xD519,0xD51A,0xD51B,0xD51C,0xD51D,0xD51E,0xD51F, + 0xD520,0xD521,0xD522,0xD523,0xD524,0xD525,0xD526,0xD527,0xD528,0xD529,0xD52A,0xD52B,0xD52C,0xD52D,0xD52E,0xD52F, + 0xD530,0xD531,0xD532,0xD533,0xD534,0xD535,0xD536,0xD537,0xD538,0xD539,0xD53A,0xD53B,0xD53C,0xD53D,0xD53E,0xD53F, + 0xD540,0xD541,0xD542,0xD543,0xD544,0xD545,0xD546,0xD547,0xD548,0xD549,0xD54A,0xD54B,0xD54C,0xD54D,0xD54E,0xD54F, + 0xD550,0xD551,0xD552,0xD553,0xD554,0xD555,0xD556,0xD557,0xD558,0xD559,0xD55A,0xD55B,0xD55C,0xD55D,0xD55E,0xD55F, + 0xD560,0xD561,0xD562,0xD563,0xD564,0xD565,0xD566,0xD567,0xD568,0xD569,0xD56A,0xD56B,0xD56C,0xD56D,0xD56E,0xD56F, + 0xD570,0xD571,0xD572,0xD573,0xD574,0xD575,0xD576,0xD577,0xD578,0xD579,0xD57A,0xD57B,0xD57C,0xD57D,0xD57E,0xD57F, + 0xD580,0xD581,0xD582,0xD583,0xD584,0xD585,0xD586,0xD587,0xD588,0xD589,0xD58A,0xD58B,0xD58C,0xD58D,0xD58E,0xD58F, + 0xD590,0xD591,0xD592,0xD593,0xD594,0xD595,0xD596,0xD597,0xD598,0xD599,0xD59A,0xD59B,0xD59C,0xD59D,0xD59E,0xD59F, + 0xD5A0,0xD5A1,0xD5A2,0xD5A3,0xD5A4,0xD5A5,0xD5A6,0xD5A7,0xD5A8,0xD5A9,0xD5AA,0xD5AB,0xD5AC,0xD5AD,0xD5AE,0xD5AF, + 0xD5B0,0xD5B1,0xD5B2,0xD5B3,0xD5B4,0xD5B5,0xD5B6,0xD5B7,0xD5B8,0xD5B9,0xD5BA,0xD5BB,0xD5BC,0xD5BD,0xD5BE,0xD5BF, + 0xD5C0,0xD5C1,0xD5C2,0xD5C3,0xD5C4,0xD5C5,0xD5C6,0xD5C7,0xD5C8,0xD5C9,0xD5CA,0xD5CB,0xD5CC,0xD5CD,0xD5CE,0xD5CF, + 0xD5D0,0xD5D1,0xD5D2,0xD5D3,0xD5D4,0xD5D5,0xD5D6,0xD5D7,0xD5D8,0xD5D9,0xD5DA,0xD5DB,0xD5DC,0xD5DD,0xD5DE,0xD5DF, + 0xD5E0,0xD5E1,0xD5E2,0xD5E3,0xD5E4,0xD5E5,0xD5E6,0xD5E7,0xD5E8,0xD5E9,0xD5EA,0xD5EB,0xD5EC,0xD5ED,0xD5EE,0xD5EF, + 0xD5F0,0xD5F1,0xD5F2,0xD5F3,0xD5F4,0xD5F5,0xD5F6,0xD5F7,0xD5F8,0xD5F9,0xD5FA,0xD5FB,0xD5FC,0xD5FD,0xD5FE,0xD5FF, + 0xD600,0xD601,0xD602,0xD603,0xD604,0xD605,0xD606,0xD607,0xD608,0xD609,0xD60A,0xD60B,0xD60C,0xD60D,0xD60E,0xD60F, + 0xD610,0xD611,0xD612,0xD613,0xD614,0xD615,0xD616,0xD617,0xD618,0xD619,0xD61A,0xD61B,0xD61C,0xD61D,0xD61E,0xD61F, + 0xD620,0xD621,0xD622,0xD623,0xD624,0xD625,0xD626,0xD627,0xD628,0xD629,0xD62A,0xD62B,0xD62C,0xD62D,0xD62E,0xD62F, + 0xD630,0xD631,0xD632,0xD633,0xD634,0xD635,0xD636,0xD637,0xD638,0xD639,0xD63A,0xD63B,0xD63C,0xD63D,0xD63E,0xD63F, + 0xD640,0xD641,0xD642,0xD643,0xD644,0xD645,0xD646,0xD647,0xD648,0xD649,0xD64A,0xD64B,0xD64C,0xD64D,0xD64E,0xD64F, + 0xD650,0xD651,0xD652,0xD653,0xD654,0xD655,0xD656,0xD657,0xD658,0xD659,0xD65A,0xD65B,0xD65C,0xD65D,0xD65E,0xD65F, + 0xD660,0xD661,0xD662,0xD663,0xD664,0xD665,0xD666,0xD667,0xD668,0xD669,0xD66A,0xD66B,0xD66C,0xD66D,0xD66E,0xD66F, + 0xD670,0xD671,0xD672,0xD673,0xD674,0xD675,0xD676,0xD677,0xD678,0xD679,0xD67A,0xD67B,0xD67C,0xD67D,0xD67E,0xD67F, + 0xD680,0xD681,0xD682,0xD683,0xD684,0xD685,0xD686,0xD687,0xD688,0xD689,0xD68A,0xD68B,0xD68C,0xD68D,0xD68E,0xD68F, + 0xD690,0xD691,0xD692,0xD693,0xD694,0xD695,0xD696,0xD697,0xD698,0xD699,0xD69A,0xD69B,0xD69C,0xD69D,0xD69E,0xD69F, + 0xD6A0,0xD6A1,0xD6A2,0xD6A3,0xD6A4,0xD6A5,0xD6A6,0xD6A7,0xD6A8,0xD6A9,0xD6AA,0xD6AB,0xD6AC,0xD6AD,0xD6AE,0xD6AF, + 0xD6B0,0xD6B1,0xD6B2,0xD6B3,0xD6B4,0xD6B5,0xD6B6,0xD6B7,0xD6B8,0xD6B9,0xD6BA,0xD6BB,0xD6BC,0xD6BD,0xD6BE,0xD6BF, + 0xD6C0,0xD6C1,0xD6C2,0xD6C3,0xD6C4,0xD6C5,0xD6C6,0xD6C7,0xD6C8,0xD6C9,0xD6CA,0xD6CB,0xD6CC,0xD6CD,0xD6CE,0xD6CF, + 0xD6D0,0xD6D1,0xD6D2,0xD6D3,0xD6D4,0xD6D5,0xD6D6,0xD6D7,0xD6D8,0xD6D9,0xD6DA,0xD6DB,0xD6DC,0xD6DD,0xD6DE,0xD6DF, + 0xD6E0,0xD6E1,0xD6E2,0xD6E3,0xD6E4,0xD6E5,0xD6E6,0xD6E7,0xD6E8,0xD6E9,0xD6EA,0xD6EB,0xD6EC,0xD6ED,0xD6EE,0xD6EF, + 0xD6F0,0xD6F1,0xD6F2,0xD6F3,0xD6F4,0xD6F5,0xD6F6,0xD6F7,0xD6F8,0xD6F9,0xD6FA,0xD6FB,0xD6FC,0xD6FD,0xD6FE,0xD6FF, + 0xD700,0xD701,0xD702,0xD703,0xD704,0xD705,0xD706,0xD707,0xD708,0xD709,0xD70A,0xD70B,0xD70C,0xD70D,0xD70E,0xD70F, + 0xD710,0xD711,0xD712,0xD713,0xD714,0xD715,0xD716,0xD717,0xD718,0xD719,0xD71A,0xD71B,0xD71C,0xD71D,0xD71E,0xD71F, + 0xD720,0xD721,0xD722,0xD723,0xD724,0xD725,0xD726,0xD727,0xD728,0xD729,0xD72A,0xD72B,0xD72C,0xD72D,0xD72E,0xD72F, + 0xD730,0xD731,0xD732,0xD733,0xD734,0xD735,0xD736,0xD737,0xD738,0xD739,0xD73A,0xD73B,0xD73C,0xD73D,0xD73E,0xD73F, + 0xD740,0xD741,0xD742,0xD743,0xD744,0xD745,0xD746,0xD747,0xD748,0xD749,0xD74A,0xD74B,0xD74C,0xD74D,0xD74E,0xD74F, + 0xD750,0xD751,0xD752,0xD753,0xD754,0xD755,0xD756,0xD757,0xD758,0xD759,0xD75A,0xD75B,0xD75C,0xD75D,0xD75E,0xD75F, + 0xD760,0xD761,0xD762,0xD763,0xD764,0xD765,0xD766,0xD767,0xD768,0xD769,0xD76A,0xD76B,0xD76C,0xD76D,0xD76E,0xD76F, + 0xD770,0xD771,0xD772,0xD773,0xD774,0xD775,0xD776,0xD777,0xD778,0xD779,0xD77A,0xD77B,0xD77C,0xD77D,0xD77E,0xD77F, + 0xD780,0xD781,0xD782,0xD783,0xD784,0xD785,0xD786,0xD787,0xD788,0xD789,0xD78A,0xD78B,0xD78C,0xD78D,0xD78E,0xD78F, + 0xD790,0xD791,0xD792,0xD793,0xD794,0xD795,0xD796,0xD797,0xD798,0xD799,0xD79A,0xD79B,0xD79C,0xD79D,0xD79E,0xD79F, + 0xD7A0,0xD7A1,0xD7A2,0xD7A3,0xD7A4,0xD7A5,0xD7A6,0xD7A7,0xD7A8,0xD7A9,0xD7AA,0xD7AB,0xD7AC,0xD7AD,0xD7AE,0xD7AF, + 0xD7B0,0xD7B1,0xD7B2,0xD7B3,0xD7B4,0xD7B5,0xD7B6,0xD7B7,0xD7B8,0xD7B9,0xD7BA,0xD7BB,0xD7BC,0xD7BD,0xD7BE,0xD7BF, + 0xD7C0,0xD7C1,0xD7C2,0xD7C3,0xD7C4,0xD7C5,0xD7C6,0xD7C7,0xD7C8,0xD7C9,0xD7CA,0xD7CB,0xD7CC,0xD7CD,0xD7CE,0xD7CF, + 0xD7D0,0xD7D1,0xD7D2,0xD7D3,0xD7D4,0xD7D5,0xD7D6,0xD7D7,0xD7D8,0xD7D9,0xD7DA,0xD7DB,0xD7DC,0xD7DD,0xD7DE,0xD7DF, + 0xD7E0,0xD7E1,0xD7E2,0xD7E3,0xD7E4,0xD7E5,0xD7E6,0xD7E7,0xD7E8,0xD7E9,0xD7EA,0xD7EB,0xD7EC,0xD7ED,0xD7EE,0xD7EF, + 0xD7F0,0xD7F1,0xD7F2,0xD7F3,0xD7F4,0xD7F5,0xD7F6,0xD7F7,0xD7F8,0xD7F9,0xD7FA,0xD7FB,0xD7FC,0xD7FD,0xD7FE,0xD7FF, + 0xD800,0xD801,0xD802,0xD803,0xD804,0xD805,0xD806,0xD807,0xD808,0xD809,0xD80A,0xD80B,0xD80C,0xD80D,0xD80E,0xD80F, + 0xD810,0xD811,0xD812,0xD813,0xD814,0xD815,0xD816,0xD817,0xD818,0xD819,0xD81A,0xD81B,0xD81C,0xD81D,0xD81E,0xD81F, + 0xD820,0xD821,0xD822,0xD823,0xD824,0xD825,0xD826,0xD827,0xD828,0xD829,0xD82A,0xD82B,0xD82C,0xD82D,0xD82E,0xD82F, + 0xD830,0xD831,0xD832,0xD833,0xD834,0xD835,0xD836,0xD837,0xD838,0xD839,0xD83A,0xD83B,0xD83C,0xD83D,0xD83E,0xD83F, + 0xD840,0xD841,0xD842,0xD843,0xD844,0xD845,0xD846,0xD847,0xD848,0xD849,0xD84A,0xD84B,0xD84C,0xD84D,0xD84E,0xD84F, + 0xD850,0xD851,0xD852,0xD853,0xD854,0xD855,0xD856,0xD857,0xD858,0xD859,0xD85A,0xD85B,0xD85C,0xD85D,0xD85E,0xD85F, + 0xD860,0xD861,0xD862,0xD863,0xD864,0xD865,0xD866,0xD867,0xD868,0xD869,0xD86A,0xD86B,0xD86C,0xD86D,0xD86E,0xD86F, + 0xD870,0xD871,0xD872,0xD873,0xD874,0xD875,0xD876,0xD877,0xD878,0xD879,0xD87A,0xD87B,0xD87C,0xD87D,0xD87E,0xD87F, + 0xD880,0xD881,0xD882,0xD883,0xD884,0xD885,0xD886,0xD887,0xD888,0xD889,0xD88A,0xD88B,0xD88C,0xD88D,0xD88E,0xD88F, + 0xD890,0xD891,0xD892,0xD893,0xD894,0xD895,0xD896,0xD897,0xD898,0xD899,0xD89A,0xD89B,0xD89C,0xD89D,0xD89E,0xD89F, + 0xD8A0,0xD8A1,0xD8A2,0xD8A3,0xD8A4,0xD8A5,0xD8A6,0xD8A7,0xD8A8,0xD8A9,0xD8AA,0xD8AB,0xD8AC,0xD8AD,0xD8AE,0xD8AF, + 0xD8B0,0xD8B1,0xD8B2,0xD8B3,0xD8B4,0xD8B5,0xD8B6,0xD8B7,0xD8B8,0xD8B9,0xD8BA,0xD8BB,0xD8BC,0xD8BD,0xD8BE,0xD8BF, + 0xD8C0,0xD8C1,0xD8C2,0xD8C3,0xD8C4,0xD8C5,0xD8C6,0xD8C7,0xD8C8,0xD8C9,0xD8CA,0xD8CB,0xD8CC,0xD8CD,0xD8CE,0xD8CF, + 0xD8D0,0xD8D1,0xD8D2,0xD8D3,0xD8D4,0xD8D5,0xD8D6,0xD8D7,0xD8D8,0xD8D9,0xD8DA,0xD8DB,0xD8DC,0xD8DD,0xD8DE,0xD8DF, + 0xD8E0,0xD8E1,0xD8E2,0xD8E3,0xD8E4,0xD8E5,0xD8E6,0xD8E7,0xD8E8,0xD8E9,0xD8EA,0xD8EB,0xD8EC,0xD8ED,0xD8EE,0xD8EF, + 0xD8F0,0xD8F1,0xD8F2,0xD8F3,0xD8F4,0xD8F5,0xD8F6,0xD8F7,0xD8F8,0xD8F9,0xD8FA,0xD8FB,0xD8FC,0xD8FD,0xD8FE,0xD8FF, + 0xD900,0xD901,0xD902,0xD903,0xD904,0xD905,0xD906,0xD907,0xD908,0xD909,0xD90A,0xD90B,0xD90C,0xD90D,0xD90E,0xD90F, + 0xD910,0xD911,0xD912,0xD913,0xD914,0xD915,0xD916,0xD917,0xD918,0xD919,0xD91A,0xD91B,0xD91C,0xD91D,0xD91E,0xD91F, + 0xD920,0xD921,0xD922,0xD923,0xD924,0xD925,0xD926,0xD927,0xD928,0xD929,0xD92A,0xD92B,0xD92C,0xD92D,0xD92E,0xD92F, + 0xD930,0xD931,0xD932,0xD933,0xD934,0xD935,0xD936,0xD937,0xD938,0xD939,0xD93A,0xD93B,0xD93C,0xD93D,0xD93E,0xD93F, + 0xD940,0xD941,0xD942,0xD943,0xD944,0xD945,0xD946,0xD947,0xD948,0xD949,0xD94A,0xD94B,0xD94C,0xD94D,0xD94E,0xD94F, + 0xD950,0xD951,0xD952,0xD953,0xD954,0xD955,0xD956,0xD957,0xD958,0xD959,0xD95A,0xD95B,0xD95C,0xD95D,0xD95E,0xD95F, + 0xD960,0xD961,0xD962,0xD963,0xD964,0xD965,0xD966,0xD967,0xD968,0xD969,0xD96A,0xD96B,0xD96C,0xD96D,0xD96E,0xD96F, + 0xD970,0xD971,0xD972,0xD973,0xD974,0xD975,0xD976,0xD977,0xD978,0xD979,0xD97A,0xD97B,0xD97C,0xD97D,0xD97E,0xD97F, + 0xD980,0xD981,0xD982,0xD983,0xD984,0xD985,0xD986,0xD987,0xD988,0xD989,0xD98A,0xD98B,0xD98C,0xD98D,0xD98E,0xD98F, + 0xD990,0xD991,0xD992,0xD993,0xD994,0xD995,0xD996,0xD997,0xD998,0xD999,0xD99A,0xD99B,0xD99C,0xD99D,0xD99E,0xD99F, + 0xD9A0,0xD9A1,0xD9A2,0xD9A3,0xD9A4,0xD9A5,0xD9A6,0xD9A7,0xD9A8,0xD9A9,0xD9AA,0xD9AB,0xD9AC,0xD9AD,0xD9AE,0xD9AF, + 0xD9B0,0xD9B1,0xD9B2,0xD9B3,0xD9B4,0xD9B5,0xD9B6,0xD9B7,0xD9B8,0xD9B9,0xD9BA,0xD9BB,0xD9BC,0xD9BD,0xD9BE,0xD9BF, + 0xD9C0,0xD9C1,0xD9C2,0xD9C3,0xD9C4,0xD9C5,0xD9C6,0xD9C7,0xD9C8,0xD9C9,0xD9CA,0xD9CB,0xD9CC,0xD9CD,0xD9CE,0xD9CF, + 0xD9D0,0xD9D1,0xD9D2,0xD9D3,0xD9D4,0xD9D5,0xD9D6,0xD9D7,0xD9D8,0xD9D9,0xD9DA,0xD9DB,0xD9DC,0xD9DD,0xD9DE,0xD9DF, + 0xD9E0,0xD9E1,0xD9E2,0xD9E3,0xD9E4,0xD9E5,0xD9E6,0xD9E7,0xD9E8,0xD9E9,0xD9EA,0xD9EB,0xD9EC,0xD9ED,0xD9EE,0xD9EF, + 0xD9F0,0xD9F1,0xD9F2,0xD9F3,0xD9F4,0xD9F5,0xD9F6,0xD9F7,0xD9F8,0xD9F9,0xD9FA,0xD9FB,0xD9FC,0xD9FD,0xD9FE,0xD9FF, + 0xDA00,0xDA01,0xDA02,0xDA03,0xDA04,0xDA05,0xDA06,0xDA07,0xDA08,0xDA09,0xDA0A,0xDA0B,0xDA0C,0xDA0D,0xDA0E,0xDA0F, + 0xDA10,0xDA11,0xDA12,0xDA13,0xDA14,0xDA15,0xDA16,0xDA17,0xDA18,0xDA19,0xDA1A,0xDA1B,0xDA1C,0xDA1D,0xDA1E,0xDA1F, + 0xDA20,0xDA21,0xDA22,0xDA23,0xDA24,0xDA25,0xDA26,0xDA27,0xDA28,0xDA29,0xDA2A,0xDA2B,0xDA2C,0xDA2D,0xDA2E,0xDA2F, + 0xDA30,0xDA31,0xDA32,0xDA33,0xDA34,0xDA35,0xDA36,0xDA37,0xDA38,0xDA39,0xDA3A,0xDA3B,0xDA3C,0xDA3D,0xDA3E,0xDA3F, + 0xDA40,0xDA41,0xDA42,0xDA43,0xDA44,0xDA45,0xDA46,0xDA47,0xDA48,0xDA49,0xDA4A,0xDA4B,0xDA4C,0xDA4D,0xDA4E,0xDA4F, + 0xDA50,0xDA51,0xDA52,0xDA53,0xDA54,0xDA55,0xDA56,0xDA57,0xDA58,0xDA59,0xDA5A,0xDA5B,0xDA5C,0xDA5D,0xDA5E,0xDA5F, + 0xDA60,0xDA61,0xDA62,0xDA63,0xDA64,0xDA65,0xDA66,0xDA67,0xDA68,0xDA69,0xDA6A,0xDA6B,0xDA6C,0xDA6D,0xDA6E,0xDA6F, + 0xDA70,0xDA71,0xDA72,0xDA73,0xDA74,0xDA75,0xDA76,0xDA77,0xDA78,0xDA79,0xDA7A,0xDA7B,0xDA7C,0xDA7D,0xDA7E,0xDA7F, + 0xDA80,0xDA81,0xDA82,0xDA83,0xDA84,0xDA85,0xDA86,0xDA87,0xDA88,0xDA89,0xDA8A,0xDA8B,0xDA8C,0xDA8D,0xDA8E,0xDA8F, + 0xDA90,0xDA91,0xDA92,0xDA93,0xDA94,0xDA95,0xDA96,0xDA97,0xDA98,0xDA99,0xDA9A,0xDA9B,0xDA9C,0xDA9D,0xDA9E,0xDA9F, + 0xDAA0,0xDAA1,0xDAA2,0xDAA3,0xDAA4,0xDAA5,0xDAA6,0xDAA7,0xDAA8,0xDAA9,0xDAAA,0xDAAB,0xDAAC,0xDAAD,0xDAAE,0xDAAF, + 0xDAB0,0xDAB1,0xDAB2,0xDAB3,0xDAB4,0xDAB5,0xDAB6,0xDAB7,0xDAB8,0xDAB9,0xDABA,0xDABB,0xDABC,0xDABD,0xDABE,0xDABF, + 0xDAC0,0xDAC1,0xDAC2,0xDAC3,0xDAC4,0xDAC5,0xDAC6,0xDAC7,0xDAC8,0xDAC9,0xDACA,0xDACB,0xDACC,0xDACD,0xDACE,0xDACF, + 0xDAD0,0xDAD1,0xDAD2,0xDAD3,0xDAD4,0xDAD5,0xDAD6,0xDAD7,0xDAD8,0xDAD9,0xDADA,0xDADB,0xDADC,0xDADD,0xDADE,0xDADF, + 0xDAE0,0xDAE1,0xDAE2,0xDAE3,0xDAE4,0xDAE5,0xDAE6,0xDAE7,0xDAE8,0xDAE9,0xDAEA,0xDAEB,0xDAEC,0xDAED,0xDAEE,0xDAEF, + 0xDAF0,0xDAF1,0xDAF2,0xDAF3,0xDAF4,0xDAF5,0xDAF6,0xDAF7,0xDAF8,0xDAF9,0xDAFA,0xDAFB,0xDAFC,0xDAFD,0xDAFE,0xDAFF, + 0xDB00,0xDB01,0xDB02,0xDB03,0xDB04,0xDB05,0xDB06,0xDB07,0xDB08,0xDB09,0xDB0A,0xDB0B,0xDB0C,0xDB0D,0xDB0E,0xDB0F, + 0xDB10,0xDB11,0xDB12,0xDB13,0xDB14,0xDB15,0xDB16,0xDB17,0xDB18,0xDB19,0xDB1A,0xDB1B,0xDB1C,0xDB1D,0xDB1E,0xDB1F, + 0xDB20,0xDB21,0xDB22,0xDB23,0xDB24,0xDB25,0xDB26,0xDB27,0xDB28,0xDB29,0xDB2A,0xDB2B,0xDB2C,0xDB2D,0xDB2E,0xDB2F, + 0xDB30,0xDB31,0xDB32,0xDB33,0xDB34,0xDB35,0xDB36,0xDB37,0xDB38,0xDB39,0xDB3A,0xDB3B,0xDB3C,0xDB3D,0xDB3E,0xDB3F, + 0xDB40,0xDB41,0xDB42,0xDB43,0xDB44,0xDB45,0xDB46,0xDB47,0xDB48,0xDB49,0xDB4A,0xDB4B,0xDB4C,0xDB4D,0xDB4E,0xDB4F, + 0xDB50,0xDB51,0xDB52,0xDB53,0xDB54,0xDB55,0xDB56,0xDB57,0xDB58,0xDB59,0xDB5A,0xDB5B,0xDB5C,0xDB5D,0xDB5E,0xDB5F, + 0xDB60,0xDB61,0xDB62,0xDB63,0xDB64,0xDB65,0xDB66,0xDB67,0xDB68,0xDB69,0xDB6A,0xDB6B,0xDB6C,0xDB6D,0xDB6E,0xDB6F, + 0xDB70,0xDB71,0xDB72,0xDB73,0xDB74,0xDB75,0xDB76,0xDB77,0xDB78,0xDB79,0xDB7A,0xDB7B,0xDB7C,0xDB7D,0xDB7E,0xDB7F, + 0xDB80,0xDB81,0xDB82,0xDB83,0xDB84,0xDB85,0xDB86,0xDB87,0xDB88,0xDB89,0xDB8A,0xDB8B,0xDB8C,0xDB8D,0xDB8E,0xDB8F, + 0xDB90,0xDB91,0xDB92,0xDB93,0xDB94,0xDB95,0xDB96,0xDB97,0xDB98,0xDB99,0xDB9A,0xDB9B,0xDB9C,0xDB9D,0xDB9E,0xDB9F, + 0xDBA0,0xDBA1,0xDBA2,0xDBA3,0xDBA4,0xDBA5,0xDBA6,0xDBA7,0xDBA8,0xDBA9,0xDBAA,0xDBAB,0xDBAC,0xDBAD,0xDBAE,0xDBAF, + 0xDBB0,0xDBB1,0xDBB2,0xDBB3,0xDBB4,0xDBB5,0xDBB6,0xDBB7,0xDBB8,0xDBB9,0xDBBA,0xDBBB,0xDBBC,0xDBBD,0xDBBE,0xDBBF, + 0xDBC0,0xDBC1,0xDBC2,0xDBC3,0xDBC4,0xDBC5,0xDBC6,0xDBC7,0xDBC8,0xDBC9,0xDBCA,0xDBCB,0xDBCC,0xDBCD,0xDBCE,0xDBCF, + 0xDBD0,0xDBD1,0xDBD2,0xDBD3,0xDBD4,0xDBD5,0xDBD6,0xDBD7,0xDBD8,0xDBD9,0xDBDA,0xDBDB,0xDBDC,0xDBDD,0xDBDE,0xDBDF, + 0xDBE0,0xDBE1,0xDBE2,0xDBE3,0xDBE4,0xDBE5,0xDBE6,0xDBE7,0xDBE8,0xDBE9,0xDBEA,0xDBEB,0xDBEC,0xDBED,0xDBEE,0xDBEF, + 0xDBF0,0xDBF1,0xDBF2,0xDBF3,0xDBF4,0xDBF5,0xDBF6,0xDBF7,0xDBF8,0xDBF9,0xDBFA,0xDBFB,0xDBFC,0xDBFD,0xDBFE,0xDBFF, + 0xDC00,0xDC01,0xDC02,0xDC03,0xDC04,0xDC05,0xDC06,0xDC07,0xDC08,0xDC09,0xDC0A,0xDC0B,0xDC0C,0xDC0D,0xDC0E,0xDC0F, + 0xDC10,0xDC11,0xDC12,0xDC13,0xDC14,0xDC15,0xDC16,0xDC17,0xDC18,0xDC19,0xDC1A,0xDC1B,0xDC1C,0xDC1D,0xDC1E,0xDC1F, + 0xDC20,0xDC21,0xDC22,0xDC23,0xDC24,0xDC25,0xDC26,0xDC27,0xDC28,0xDC29,0xDC2A,0xDC2B,0xDC2C,0xDC2D,0xDC2E,0xDC2F, + 0xDC30,0xDC31,0xDC32,0xDC33,0xDC34,0xDC35,0xDC36,0xDC37,0xDC38,0xDC39,0xDC3A,0xDC3B,0xDC3C,0xDC3D,0xDC3E,0xDC3F, + 0xDC40,0xDC41,0xDC42,0xDC43,0xDC44,0xDC45,0xDC46,0xDC47,0xDC48,0xDC49,0xDC4A,0xDC4B,0xDC4C,0xDC4D,0xDC4E,0xDC4F, + 0xDC50,0xDC51,0xDC52,0xDC53,0xDC54,0xDC55,0xDC56,0xDC57,0xDC58,0xDC59,0xDC5A,0xDC5B,0xDC5C,0xDC5D,0xDC5E,0xDC5F, + 0xDC60,0xDC61,0xDC62,0xDC63,0xDC64,0xDC65,0xDC66,0xDC67,0xDC68,0xDC69,0xDC6A,0xDC6B,0xDC6C,0xDC6D,0xDC6E,0xDC6F, + 0xDC70,0xDC71,0xDC72,0xDC73,0xDC74,0xDC75,0xDC76,0xDC77,0xDC78,0xDC79,0xDC7A,0xDC7B,0xDC7C,0xDC7D,0xDC7E,0xDC7F, + 0xDC80,0xDC81,0xDC82,0xDC83,0xDC84,0xDC85,0xDC86,0xDC87,0xDC88,0xDC89,0xDC8A,0xDC8B,0xDC8C,0xDC8D,0xDC8E,0xDC8F, + 0xDC90,0xDC91,0xDC92,0xDC93,0xDC94,0xDC95,0xDC96,0xDC97,0xDC98,0xDC99,0xDC9A,0xDC9B,0xDC9C,0xDC9D,0xDC9E,0xDC9F, + 0xDCA0,0xDCA1,0xDCA2,0xDCA3,0xDCA4,0xDCA5,0xDCA6,0xDCA7,0xDCA8,0xDCA9,0xDCAA,0xDCAB,0xDCAC,0xDCAD,0xDCAE,0xDCAF, + 0xDCB0,0xDCB1,0xDCB2,0xDCB3,0xDCB4,0xDCB5,0xDCB6,0xDCB7,0xDCB8,0xDCB9,0xDCBA,0xDCBB,0xDCBC,0xDCBD,0xDCBE,0xDCBF, + 0xDCC0,0xDCC1,0xDCC2,0xDCC3,0xDCC4,0xDCC5,0xDCC6,0xDCC7,0xDCC8,0xDCC9,0xDCCA,0xDCCB,0xDCCC,0xDCCD,0xDCCE,0xDCCF, + 0xDCD0,0xDCD1,0xDCD2,0xDCD3,0xDCD4,0xDCD5,0xDCD6,0xDCD7,0xDCD8,0xDCD9,0xDCDA,0xDCDB,0xDCDC,0xDCDD,0xDCDE,0xDCDF, + 0xDCE0,0xDCE1,0xDCE2,0xDCE3,0xDCE4,0xDCE5,0xDCE6,0xDCE7,0xDCE8,0xDCE9,0xDCEA,0xDCEB,0xDCEC,0xDCED,0xDCEE,0xDCEF, + 0xDCF0,0xDCF1,0xDCF2,0xDCF3,0xDCF4,0xDCF5,0xDCF6,0xDCF7,0xDCF8,0xDCF9,0xDCFA,0xDCFB,0xDCFC,0xDCFD,0xDCFE,0xDCFF, + 0xDD00,0xDD01,0xDD02,0xDD03,0xDD04,0xDD05,0xDD06,0xDD07,0xDD08,0xDD09,0xDD0A,0xDD0B,0xDD0C,0xDD0D,0xDD0E,0xDD0F, + 0xDD10,0xDD11,0xDD12,0xDD13,0xDD14,0xDD15,0xDD16,0xDD17,0xDD18,0xDD19,0xDD1A,0xDD1B,0xDD1C,0xDD1D,0xDD1E,0xDD1F, + 0xDD20,0xDD21,0xDD22,0xDD23,0xDD24,0xDD25,0xDD26,0xDD27,0xDD28,0xDD29,0xDD2A,0xDD2B,0xDD2C,0xDD2D,0xDD2E,0xDD2F, + 0xDD30,0xDD31,0xDD32,0xDD33,0xDD34,0xDD35,0xDD36,0xDD37,0xDD38,0xDD39,0xDD3A,0xDD3B,0xDD3C,0xDD3D,0xDD3E,0xDD3F, + 0xDD40,0xDD41,0xDD42,0xDD43,0xDD44,0xDD45,0xDD46,0xDD47,0xDD48,0xDD49,0xDD4A,0xDD4B,0xDD4C,0xDD4D,0xDD4E,0xDD4F, + 0xDD50,0xDD51,0xDD52,0xDD53,0xDD54,0xDD55,0xDD56,0xDD57,0xDD58,0xDD59,0xDD5A,0xDD5B,0xDD5C,0xDD5D,0xDD5E,0xDD5F, + 0xDD60,0xDD61,0xDD62,0xDD63,0xDD64,0xDD65,0xDD66,0xDD67,0xDD68,0xDD69,0xDD6A,0xDD6B,0xDD6C,0xDD6D,0xDD6E,0xDD6F, + 0xDD70,0xDD71,0xDD72,0xDD73,0xDD74,0xDD75,0xDD76,0xDD77,0xDD78,0xDD79,0xDD7A,0xDD7B,0xDD7C,0xDD7D,0xDD7E,0xDD7F, + 0xDD80,0xDD81,0xDD82,0xDD83,0xDD84,0xDD85,0xDD86,0xDD87,0xDD88,0xDD89,0xDD8A,0xDD8B,0xDD8C,0xDD8D,0xDD8E,0xDD8F, + 0xDD90,0xDD91,0xDD92,0xDD93,0xDD94,0xDD95,0xDD96,0xDD97,0xDD98,0xDD99,0xDD9A,0xDD9B,0xDD9C,0xDD9D,0xDD9E,0xDD9F, + 0xDDA0,0xDDA1,0xDDA2,0xDDA3,0xDDA4,0xDDA5,0xDDA6,0xDDA7,0xDDA8,0xDDA9,0xDDAA,0xDDAB,0xDDAC,0xDDAD,0xDDAE,0xDDAF, + 0xDDB0,0xDDB1,0xDDB2,0xDDB3,0xDDB4,0xDDB5,0xDDB6,0xDDB7,0xDDB8,0xDDB9,0xDDBA,0xDDBB,0xDDBC,0xDDBD,0xDDBE,0xDDBF, + 0xDDC0,0xDDC1,0xDDC2,0xDDC3,0xDDC4,0xDDC5,0xDDC6,0xDDC7,0xDDC8,0xDDC9,0xDDCA,0xDDCB,0xDDCC,0xDDCD,0xDDCE,0xDDCF, + 0xDDD0,0xDDD1,0xDDD2,0xDDD3,0xDDD4,0xDDD5,0xDDD6,0xDDD7,0xDDD8,0xDDD9,0xDDDA,0xDDDB,0xDDDC,0xDDDD,0xDDDE,0xDDDF, + 0xDDE0,0xDDE1,0xDDE2,0xDDE3,0xDDE4,0xDDE5,0xDDE6,0xDDE7,0xDDE8,0xDDE9,0xDDEA,0xDDEB,0xDDEC,0xDDED,0xDDEE,0xDDEF, + 0xDDF0,0xDDF1,0xDDF2,0xDDF3,0xDDF4,0xDDF5,0xDDF6,0xDDF7,0xDDF8,0xDDF9,0xDDFA,0xDDFB,0xDDFC,0xDDFD,0xDDFE,0xDDFF, + 0xDE00,0xDE01,0xDE02,0xDE03,0xDE04,0xDE05,0xDE06,0xDE07,0xDE08,0xDE09,0xDE0A,0xDE0B,0xDE0C,0xDE0D,0xDE0E,0xDE0F, + 0xDE10,0xDE11,0xDE12,0xDE13,0xDE14,0xDE15,0xDE16,0xDE17,0xDE18,0xDE19,0xDE1A,0xDE1B,0xDE1C,0xDE1D,0xDE1E,0xDE1F, + 0xDE20,0xDE21,0xDE22,0xDE23,0xDE24,0xDE25,0xDE26,0xDE27,0xDE28,0xDE29,0xDE2A,0xDE2B,0xDE2C,0xDE2D,0xDE2E,0xDE2F, + 0xDE30,0xDE31,0xDE32,0xDE33,0xDE34,0xDE35,0xDE36,0xDE37,0xDE38,0xDE39,0xDE3A,0xDE3B,0xDE3C,0xDE3D,0xDE3E,0xDE3F, + 0xDE40,0xDE41,0xDE42,0xDE43,0xDE44,0xDE45,0xDE46,0xDE47,0xDE48,0xDE49,0xDE4A,0xDE4B,0xDE4C,0xDE4D,0xDE4E,0xDE4F, + 0xDE50,0xDE51,0xDE52,0xDE53,0xDE54,0xDE55,0xDE56,0xDE57,0xDE58,0xDE59,0xDE5A,0xDE5B,0xDE5C,0xDE5D,0xDE5E,0xDE5F, + 0xDE60,0xDE61,0xDE62,0xDE63,0xDE64,0xDE65,0xDE66,0xDE67,0xDE68,0xDE69,0xDE6A,0xDE6B,0xDE6C,0xDE6D,0xDE6E,0xDE6F, + 0xDE70,0xDE71,0xDE72,0xDE73,0xDE74,0xDE75,0xDE76,0xDE77,0xDE78,0xDE79,0xDE7A,0xDE7B,0xDE7C,0xDE7D,0xDE7E,0xDE7F, + 0xDE80,0xDE81,0xDE82,0xDE83,0xDE84,0xDE85,0xDE86,0xDE87,0xDE88,0xDE89,0xDE8A,0xDE8B,0xDE8C,0xDE8D,0xDE8E,0xDE8F, + 0xDE90,0xDE91,0xDE92,0xDE93,0xDE94,0xDE95,0xDE96,0xDE97,0xDE98,0xDE99,0xDE9A,0xDE9B,0xDE9C,0xDE9D,0xDE9E,0xDE9F, + 0xDEA0,0xDEA1,0xDEA2,0xDEA3,0xDEA4,0xDEA5,0xDEA6,0xDEA7,0xDEA8,0xDEA9,0xDEAA,0xDEAB,0xDEAC,0xDEAD,0xDEAE,0xDEAF, + 0xDEB0,0xDEB1,0xDEB2,0xDEB3,0xDEB4,0xDEB5,0xDEB6,0xDEB7,0xDEB8,0xDEB9,0xDEBA,0xDEBB,0xDEBC,0xDEBD,0xDEBE,0xDEBF, + 0xDEC0,0xDEC1,0xDEC2,0xDEC3,0xDEC4,0xDEC5,0xDEC6,0xDEC7,0xDEC8,0xDEC9,0xDECA,0xDECB,0xDECC,0xDECD,0xDECE,0xDECF, + 0xDED0,0xDED1,0xDED2,0xDED3,0xDED4,0xDED5,0xDED6,0xDED7,0xDED8,0xDED9,0xDEDA,0xDEDB,0xDEDC,0xDEDD,0xDEDE,0xDEDF, + 0xDEE0,0xDEE1,0xDEE2,0xDEE3,0xDEE4,0xDEE5,0xDEE6,0xDEE7,0xDEE8,0xDEE9,0xDEEA,0xDEEB,0xDEEC,0xDEED,0xDEEE,0xDEEF, + 0xDEF0,0xDEF1,0xDEF2,0xDEF3,0xDEF4,0xDEF5,0xDEF6,0xDEF7,0xDEF8,0xDEF9,0xDEFA,0xDEFB,0xDEFC,0xDEFD,0xDEFE,0xDEFF, + 0xDF00,0xDF01,0xDF02,0xDF03,0xDF04,0xDF05,0xDF06,0xDF07,0xDF08,0xDF09,0xDF0A,0xDF0B,0xDF0C,0xDF0D,0xDF0E,0xDF0F, + 0xDF10,0xDF11,0xDF12,0xDF13,0xDF14,0xDF15,0xDF16,0xDF17,0xDF18,0xDF19,0xDF1A,0xDF1B,0xDF1C,0xDF1D,0xDF1E,0xDF1F, + 0xDF20,0xDF21,0xDF22,0xDF23,0xDF24,0xDF25,0xDF26,0xDF27,0xDF28,0xDF29,0xDF2A,0xDF2B,0xDF2C,0xDF2D,0xDF2E,0xDF2F, + 0xDF30,0xDF31,0xDF32,0xDF33,0xDF34,0xDF35,0xDF36,0xDF37,0xDF38,0xDF39,0xDF3A,0xDF3B,0xDF3C,0xDF3D,0xDF3E,0xDF3F, + 0xDF40,0xDF41,0xDF42,0xDF43,0xDF44,0xDF45,0xDF46,0xDF47,0xDF48,0xDF49,0xDF4A,0xDF4B,0xDF4C,0xDF4D,0xDF4E,0xDF4F, + 0xDF50,0xDF51,0xDF52,0xDF53,0xDF54,0xDF55,0xDF56,0xDF57,0xDF58,0xDF59,0xDF5A,0xDF5B,0xDF5C,0xDF5D,0xDF5E,0xDF5F, + 0xDF60,0xDF61,0xDF62,0xDF63,0xDF64,0xDF65,0xDF66,0xDF67,0xDF68,0xDF69,0xDF6A,0xDF6B,0xDF6C,0xDF6D,0xDF6E,0xDF6F, + 0xDF70,0xDF71,0xDF72,0xDF73,0xDF74,0xDF75,0xDF76,0xDF77,0xDF78,0xDF79,0xDF7A,0xDF7B,0xDF7C,0xDF7D,0xDF7E,0xDF7F, + 0xDF80,0xDF81,0xDF82,0xDF83,0xDF84,0xDF85,0xDF86,0xDF87,0xDF88,0xDF89,0xDF8A,0xDF8B,0xDF8C,0xDF8D,0xDF8E,0xDF8F, + 0xDF90,0xDF91,0xDF92,0xDF93,0xDF94,0xDF95,0xDF96,0xDF97,0xDF98,0xDF99,0xDF9A,0xDF9B,0xDF9C,0xDF9D,0xDF9E,0xDF9F, + 0xDFA0,0xDFA1,0xDFA2,0xDFA3,0xDFA4,0xDFA5,0xDFA6,0xDFA7,0xDFA8,0xDFA9,0xDFAA,0xDFAB,0xDFAC,0xDFAD,0xDFAE,0xDFAF, + 0xDFB0,0xDFB1,0xDFB2,0xDFB3,0xDFB4,0xDFB5,0xDFB6,0xDFB7,0xDFB8,0xDFB9,0xDFBA,0xDFBB,0xDFBC,0xDFBD,0xDFBE,0xDFBF, + 0xDFC0,0xDFC1,0xDFC2,0xDFC3,0xDFC4,0xDFC5,0xDFC6,0xDFC7,0xDFC8,0xDFC9,0xDFCA,0xDFCB,0xDFCC,0xDFCD,0xDFCE,0xDFCF, + 0xDFD0,0xDFD1,0xDFD2,0xDFD3,0xDFD4,0xDFD5,0xDFD6,0xDFD7,0xDFD8,0xDFD9,0xDFDA,0xDFDB,0xDFDC,0xDFDD,0xDFDE,0xDFDF, + 0xDFE0,0xDFE1,0xDFE2,0xDFE3,0xDFE4,0xDFE5,0xDFE6,0xDFE7,0xDFE8,0xDFE9,0xDFEA,0xDFEB,0xDFEC,0xDFED,0xDFEE,0xDFEF, + 0xDFF0,0xDFF1,0xDFF2,0xDFF3,0xDFF4,0xDFF5,0xDFF6,0xDFF7,0xDFF8,0xDFF9,0xDFFA,0xDFFB,0xDFFC,0xDFFD,0xDFFE,0xDFFF, + 0xE000,0xE001,0xE002,0xE003,0xE004,0xE005,0xE006,0xE007,0xE008,0xE009,0xE00A,0xE00B,0xE00C,0xE00D,0xE00E,0xE00F, + 0xE010,0xE011,0xE012,0xE013,0xE014,0xE015,0xE016,0xE017,0xE018,0xE019,0xE01A,0xE01B,0xE01C,0xE01D,0xE01E,0xE01F, + 0xE020,0xE021,0xE022,0xE023,0xE024,0xE025,0xE026,0xE027,0xE028,0xE029,0xE02A,0xE02B,0xE02C,0xE02D,0xE02E,0xE02F, + 0xE030,0xE031,0xE032,0xE033,0xE034,0xE035,0xE036,0xE037,0xE038,0xE039,0xE03A,0xE03B,0xE03C,0xE03D,0xE03E,0xE03F, + 0xE040,0xE041,0xE042,0xE043,0xE044,0xE045,0xE046,0xE047,0xE048,0xE049,0xE04A,0xE04B,0xE04C,0xE04D,0xE04E,0xE04F, + 0xE050,0xE051,0xE052,0xE053,0xE054,0xE055,0xE056,0xE057,0xE058,0xE059,0xE05A,0xE05B,0xE05C,0xE05D,0xE05E,0xE05F, + 0xE060,0xE061,0xE062,0xE063,0xE064,0xE065,0xE066,0xE067,0xE068,0xE069,0xE06A,0xE06B,0xE06C,0xE06D,0xE06E,0xE06F, + 0xE070,0xE071,0xE072,0xE073,0xE074,0xE075,0xE076,0xE077,0xE078,0xE079,0xE07A,0xE07B,0xE07C,0xE07D,0xE07E,0xE07F, + 0xE080,0xE081,0xE082,0xE083,0xE084,0xE085,0xE086,0xE087,0xE088,0xE089,0xE08A,0xE08B,0xE08C,0xE08D,0xE08E,0xE08F, + 0xE090,0xE091,0xE092,0xE093,0xE094,0xE095,0xE096,0xE097,0xE098,0xE099,0xE09A,0xE09B,0xE09C,0xE09D,0xE09E,0xE09F, + 0xE0A0,0xE0A1,0xE0A2,0xE0A3,0xE0A4,0xE0A5,0xE0A6,0xE0A7,0xE0A8,0xE0A9,0xE0AA,0xE0AB,0xE0AC,0xE0AD,0xE0AE,0xE0AF, + 0xE0B0,0xE0B1,0xE0B2,0xE0B3,0xE0B4,0xE0B5,0xE0B6,0xE0B7,0xE0B8,0xE0B9,0xE0BA,0xE0BB,0xE0BC,0xE0BD,0xE0BE,0xE0BF, + 0xE0C0,0xE0C1,0xE0C2,0xE0C3,0xE0C4,0xE0C5,0xE0C6,0xE0C7,0xE0C8,0xE0C9,0xE0CA,0xE0CB,0xE0CC,0xE0CD,0xE0CE,0xE0CF, + 0xE0D0,0xE0D1,0xE0D2,0xE0D3,0xE0D4,0xE0D5,0xE0D6,0xE0D7,0xE0D8,0xE0D9,0xE0DA,0xE0DB,0xE0DC,0xE0DD,0xE0DE,0xE0DF, + 0xE0E0,0xE0E1,0xE0E2,0xE0E3,0xE0E4,0xE0E5,0xE0E6,0xE0E7,0xE0E8,0xE0E9,0xE0EA,0xE0EB,0xE0EC,0xE0ED,0xE0EE,0xE0EF, + 0xE0F0,0xE0F1,0xE0F2,0xE0F3,0xE0F4,0xE0F5,0xE0F6,0xE0F7,0xE0F8,0xE0F9,0xE0FA,0xE0FB,0xE0FC,0xE0FD,0xE0FE,0xE0FF, + 0xE100,0xE101,0xE102,0xE103,0xE104,0xE105,0xE106,0xE107,0xE108,0xE109,0xE10A,0xE10B,0xE10C,0xE10D,0xE10E,0xE10F, + 0xE110,0xE111,0xE112,0xE113,0xE114,0xE115,0xE116,0xE117,0xE118,0xE119,0xE11A,0xE11B,0xE11C,0xE11D,0xE11E,0xE11F, + 0xE120,0xE121,0xE122,0xE123,0xE124,0xE125,0xE126,0xE127,0xE128,0xE129,0xE12A,0xE12B,0xE12C,0xE12D,0xE12E,0xE12F, + 0xE130,0xE131,0xE132,0xE133,0xE134,0xE135,0xE136,0xE137,0xE138,0xE139,0xE13A,0xE13B,0xE13C,0xE13D,0xE13E,0xE13F, + 0xE140,0xE141,0xE142,0xE143,0xE144,0xE145,0xE146,0xE147,0xE148,0xE149,0xE14A,0xE14B,0xE14C,0xE14D,0xE14E,0xE14F, + 0xE150,0xE151,0xE152,0xE153,0xE154,0xE155,0xE156,0xE157,0xE158,0xE159,0xE15A,0xE15B,0xE15C,0xE15D,0xE15E,0xE15F, + 0xE160,0xE161,0xE162,0xE163,0xE164,0xE165,0xE166,0xE167,0xE168,0xE169,0xE16A,0xE16B,0xE16C,0xE16D,0xE16E,0xE16F, + 0xE170,0xE171,0xE172,0xE173,0xE174,0xE175,0xE176,0xE177,0xE178,0xE179,0xE17A,0xE17B,0xE17C,0xE17D,0xE17E,0xE17F, + 0xE180,0xE181,0xE182,0xE183,0xE184,0xE185,0xE186,0xE187,0xE188,0xE189,0xE18A,0xE18B,0xE18C,0xE18D,0xE18E,0xE18F, + 0xE190,0xE191,0xE192,0xE193,0xE194,0xE195,0xE196,0xE197,0xE198,0xE199,0xE19A,0xE19B,0xE19C,0xE19D,0xE19E,0xE19F, + 0xE1A0,0xE1A1,0xE1A2,0xE1A3,0xE1A4,0xE1A5,0xE1A6,0xE1A7,0xE1A8,0xE1A9,0xE1AA,0xE1AB,0xE1AC,0xE1AD,0xE1AE,0xE1AF, + 0xE1B0,0xE1B1,0xE1B2,0xE1B3,0xE1B4,0xE1B5,0xE1B6,0xE1B7,0xE1B8,0xE1B9,0xE1BA,0xE1BB,0xE1BC,0xE1BD,0xE1BE,0xE1BF, + 0xE1C0,0xE1C1,0xE1C2,0xE1C3,0xE1C4,0xE1C5,0xE1C6,0xE1C7,0xE1C8,0xE1C9,0xE1CA,0xE1CB,0xE1CC,0xE1CD,0xE1CE,0xE1CF, + 0xE1D0,0xE1D1,0xE1D2,0xE1D3,0xE1D4,0xE1D5,0xE1D6,0xE1D7,0xE1D8,0xE1D9,0xE1DA,0xE1DB,0xE1DC,0xE1DD,0xE1DE,0xE1DF, + 0xE1E0,0xE1E1,0xE1E2,0xE1E3,0xE1E4,0xE1E5,0xE1E6,0xE1E7,0xE1E8,0xE1E9,0xE1EA,0xE1EB,0xE1EC,0xE1ED,0xE1EE,0xE1EF, + 0xE1F0,0xE1F1,0xE1F2,0xE1F3,0xE1F4,0xE1F5,0xE1F6,0xE1F7,0xE1F8,0xE1F9,0xE1FA,0xE1FB,0xE1FC,0xE1FD,0xE1FE,0xE1FF, + 0xE200,0xE201,0xE202,0xE203,0xE204,0xE205,0xE206,0xE207,0xE208,0xE209,0xE20A,0xE20B,0xE20C,0xE20D,0xE20E,0xE20F, + 0xE210,0xE211,0xE212,0xE213,0xE214,0xE215,0xE216,0xE217,0xE218,0xE219,0xE21A,0xE21B,0xE21C,0xE21D,0xE21E,0xE21F, + 0xE220,0xE221,0xE222,0xE223,0xE224,0xE225,0xE226,0xE227,0xE228,0xE229,0xE22A,0xE22B,0xE22C,0xE22D,0xE22E,0xE22F, + 0xE230,0xE231,0xE232,0xE233,0xE234,0xE235,0xE236,0xE237,0xE238,0xE239,0xE23A,0xE23B,0xE23C,0xE23D,0xE23E,0xE23F, + 0xE240,0xE241,0xE242,0xE243,0xE244,0xE245,0xE246,0xE247,0xE248,0xE249,0xE24A,0xE24B,0xE24C,0xE24D,0xE24E,0xE24F, + 0xE250,0xE251,0xE252,0xE253,0xE254,0xE255,0xE256,0xE257,0xE258,0xE259,0xE25A,0xE25B,0xE25C,0xE25D,0xE25E,0xE25F, + 0xE260,0xE261,0xE262,0xE263,0xE264,0xE265,0xE266,0xE267,0xE268,0xE269,0xE26A,0xE26B,0xE26C,0xE26D,0xE26E,0xE26F, + 0xE270,0xE271,0xE272,0xE273,0xE274,0xE275,0xE276,0xE277,0xE278,0xE279,0xE27A,0xE27B,0xE27C,0xE27D,0xE27E,0xE27F, + 0xE280,0xE281,0xE282,0xE283,0xE284,0xE285,0xE286,0xE287,0xE288,0xE289,0xE28A,0xE28B,0xE28C,0xE28D,0xE28E,0xE28F, + 0xE290,0xE291,0xE292,0xE293,0xE294,0xE295,0xE296,0xE297,0xE298,0xE299,0xE29A,0xE29B,0xE29C,0xE29D,0xE29E,0xE29F, + 0xE2A0,0xE2A1,0xE2A2,0xE2A3,0xE2A4,0xE2A5,0xE2A6,0xE2A7,0xE2A8,0xE2A9,0xE2AA,0xE2AB,0xE2AC,0xE2AD,0xE2AE,0xE2AF, + 0xE2B0,0xE2B1,0xE2B2,0xE2B3,0xE2B4,0xE2B5,0xE2B6,0xE2B7,0xE2B8,0xE2B9,0xE2BA,0xE2BB,0xE2BC,0xE2BD,0xE2BE,0xE2BF, + 0xE2C0,0xE2C1,0xE2C2,0xE2C3,0xE2C4,0xE2C5,0xE2C6,0xE2C7,0xE2C8,0xE2C9,0xE2CA,0xE2CB,0xE2CC,0xE2CD,0xE2CE,0xE2CF, + 0xE2D0,0xE2D1,0xE2D2,0xE2D3,0xE2D4,0xE2D5,0xE2D6,0xE2D7,0xE2D8,0xE2D9,0xE2DA,0xE2DB,0xE2DC,0xE2DD,0xE2DE,0xE2DF, + 0xE2E0,0xE2E1,0xE2E2,0xE2E3,0xE2E4,0xE2E5,0xE2E6,0xE2E7,0xE2E8,0xE2E9,0xE2EA,0xE2EB,0xE2EC,0xE2ED,0xE2EE,0xE2EF, + 0xE2F0,0xE2F1,0xE2F2,0xE2F3,0xE2F4,0xE2F5,0xE2F6,0xE2F7,0xE2F8,0xE2F9,0xE2FA,0xE2FB,0xE2FC,0xE2FD,0xE2FE,0xE2FF, + 0xE300,0xE301,0xE302,0xE303,0xE304,0xE305,0xE306,0xE307,0xE308,0xE309,0xE30A,0xE30B,0xE30C,0xE30D,0xE30E,0xE30F, + 0xE310,0xE311,0xE312,0xE313,0xE314,0xE315,0xE316,0xE317,0xE318,0xE319,0xE31A,0xE31B,0xE31C,0xE31D,0xE31E,0xE31F, + 0xE320,0xE321,0xE322,0xE323,0xE324,0xE325,0xE326,0xE327,0xE328,0xE329,0xE32A,0xE32B,0xE32C,0xE32D,0xE32E,0xE32F, + 0xE330,0xE331,0xE332,0xE333,0xE334,0xE335,0xE336,0xE337,0xE338,0xE339,0xE33A,0xE33B,0xE33C,0xE33D,0xE33E,0xE33F, + 0xE340,0xE341,0xE342,0xE343,0xE344,0xE345,0xE346,0xE347,0xE348,0xE349,0xE34A,0xE34B,0xE34C,0xE34D,0xE34E,0xE34F, + 0xE350,0xE351,0xE352,0xE353,0xE354,0xE355,0xE356,0xE357,0xE358,0xE359,0xE35A,0xE35B,0xE35C,0xE35D,0xE35E,0xE35F, + 0xE360,0xE361,0xE362,0xE363,0xE364,0xE365,0xE366,0xE367,0xE368,0xE369,0xE36A,0xE36B,0xE36C,0xE36D,0xE36E,0xE36F, + 0xE370,0xE371,0xE372,0xE373,0xE374,0xE375,0xE376,0xE377,0xE378,0xE379,0xE37A,0xE37B,0xE37C,0xE37D,0xE37E,0xE37F, + 0xE380,0xE381,0xE382,0xE383,0xE384,0xE385,0xE386,0xE387,0xE388,0xE389,0xE38A,0xE38B,0xE38C,0xE38D,0xE38E,0xE38F, + 0xE390,0xE391,0xE392,0xE393,0xE394,0xE395,0xE396,0xE397,0xE398,0xE399,0xE39A,0xE39B,0xE39C,0xE39D,0xE39E,0xE39F, + 0xE3A0,0xE3A1,0xE3A2,0xE3A3,0xE3A4,0xE3A5,0xE3A6,0xE3A7,0xE3A8,0xE3A9,0xE3AA,0xE3AB,0xE3AC,0xE3AD,0xE3AE,0xE3AF, + 0xE3B0,0xE3B1,0xE3B2,0xE3B3,0xE3B4,0xE3B5,0xE3B6,0xE3B7,0xE3B8,0xE3B9,0xE3BA,0xE3BB,0xE3BC,0xE3BD,0xE3BE,0xE3BF, + 0xE3C0,0xE3C1,0xE3C2,0xE3C3,0xE3C4,0xE3C5,0xE3C6,0xE3C7,0xE3C8,0xE3C9,0xE3CA,0xE3CB,0xE3CC,0xE3CD,0xE3CE,0xE3CF, + 0xE3D0,0xE3D1,0xE3D2,0xE3D3,0xE3D4,0xE3D5,0xE3D6,0xE3D7,0xE3D8,0xE3D9,0xE3DA,0xE3DB,0xE3DC,0xE3DD,0xE3DE,0xE3DF, + 0xE3E0,0xE3E1,0xE3E2,0xE3E3,0xE3E4,0xE3E5,0xE3E6,0xE3E7,0xE3E8,0xE3E9,0xE3EA,0xE3EB,0xE3EC,0xE3ED,0xE3EE,0xE3EF, + 0xE3F0,0xE3F1,0xE3F2,0xE3F3,0xE3F4,0xE3F5,0xE3F6,0xE3F7,0xE3F8,0xE3F9,0xE3FA,0xE3FB,0xE3FC,0xE3FD,0xE3FE,0xE3FF, + 0xE400,0xE401,0xE402,0xE403,0xE404,0xE405,0xE406,0xE407,0xE408,0xE409,0xE40A,0xE40B,0xE40C,0xE40D,0xE40E,0xE40F, + 0xE410,0xE411,0xE412,0xE413,0xE414,0xE415,0xE416,0xE417,0xE418,0xE419,0xE41A,0xE41B,0xE41C,0xE41D,0xE41E,0xE41F, + 0xE420,0xE421,0xE422,0xE423,0xE424,0xE425,0xE426,0xE427,0xE428,0xE429,0xE42A,0xE42B,0xE42C,0xE42D,0xE42E,0xE42F, + 0xE430,0xE431,0xE432,0xE433,0xE434,0xE435,0xE436,0xE437,0xE438,0xE439,0xE43A,0xE43B,0xE43C,0xE43D,0xE43E,0xE43F, + 0xE440,0xE441,0xE442,0xE443,0xE444,0xE445,0xE446,0xE447,0xE448,0xE449,0xE44A,0xE44B,0xE44C,0xE44D,0xE44E,0xE44F, + 0xE450,0xE451,0xE452,0xE453,0xE454,0xE455,0xE456,0xE457,0xE458,0xE459,0xE45A,0xE45B,0xE45C,0xE45D,0xE45E,0xE45F, + 0xE460,0xE461,0xE462,0xE463,0xE464,0xE465,0xE466,0xE467,0xE468,0xE469,0xE46A,0xE46B,0xE46C,0xE46D,0xE46E,0xE46F, + 0xE470,0xE471,0xE472,0xE473,0xE474,0xE475,0xE476,0xE477,0xE478,0xE479,0xE47A,0xE47B,0xE47C,0xE47D,0xE47E,0xE47F, + 0xE480,0xE481,0xE482,0xE483,0xE484,0xE485,0xE486,0xE487,0xE488,0xE489,0xE48A,0xE48B,0xE48C,0xE48D,0xE48E,0xE48F, + 0xE490,0xE491,0xE492,0xE493,0xE494,0xE495,0xE496,0xE497,0xE498,0xE499,0xE49A,0xE49B,0xE49C,0xE49D,0xE49E,0xE49F, + 0xE4A0,0xE4A1,0xE4A2,0xE4A3,0xE4A4,0xE4A5,0xE4A6,0xE4A7,0xE4A8,0xE4A9,0xE4AA,0xE4AB,0xE4AC,0xE4AD,0xE4AE,0xE4AF, + 0xE4B0,0xE4B1,0xE4B2,0xE4B3,0xE4B4,0xE4B5,0xE4B6,0xE4B7,0xE4B8,0xE4B9,0xE4BA,0xE4BB,0xE4BC,0xE4BD,0xE4BE,0xE4BF, + 0xE4C0,0xE4C1,0xE4C2,0xE4C3,0xE4C4,0xE4C5,0xE4C6,0xE4C7,0xE4C8,0xE4C9,0xE4CA,0xE4CB,0xE4CC,0xE4CD,0xE4CE,0xE4CF, + 0xE4D0,0xE4D1,0xE4D2,0xE4D3,0xE4D4,0xE4D5,0xE4D6,0xE4D7,0xE4D8,0xE4D9,0xE4DA,0xE4DB,0xE4DC,0xE4DD,0xE4DE,0xE4DF, + 0xE4E0,0xE4E1,0xE4E2,0xE4E3,0xE4E4,0xE4E5,0xE4E6,0xE4E7,0xE4E8,0xE4E9,0xE4EA,0xE4EB,0xE4EC,0xE4ED,0xE4EE,0xE4EF, + 0xE4F0,0xE4F1,0xE4F2,0xE4F3,0xE4F4,0xE4F5,0xE4F6,0xE4F7,0xE4F8,0xE4F9,0xE4FA,0xE4FB,0xE4FC,0xE4FD,0xE4FE,0xE4FF, + 0xE500,0xE501,0xE502,0xE503,0xE504,0xE505,0xE506,0xE507,0xE508,0xE509,0xE50A,0xE50B,0xE50C,0xE50D,0xE50E,0xE50F, + 0xE510,0xE511,0xE512,0xE513,0xE514,0xE515,0xE516,0xE517,0xE518,0xE519,0xE51A,0xE51B,0xE51C,0xE51D,0xE51E,0xE51F, + 0xE520,0xE521,0xE522,0xE523,0xE524,0xE525,0xE526,0xE527,0xE528,0xE529,0xE52A,0xE52B,0xE52C,0xE52D,0xE52E,0xE52F, + 0xE530,0xE531,0xE532,0xE533,0xE534,0xE535,0xE536,0xE537,0xE538,0xE539,0xE53A,0xE53B,0xE53C,0xE53D,0xE53E,0xE53F, + 0xE540,0xE541,0xE542,0xE543,0xE544,0xE545,0xE546,0xE547,0xE548,0xE549,0xE54A,0xE54B,0xE54C,0xE54D,0xE54E,0xE54F, + 0xE550,0xE551,0xE552,0xE553,0xE554,0xE555,0xE556,0xE557,0xE558,0xE559,0xE55A,0xE55B,0xE55C,0xE55D,0xE55E,0xE55F, + 0xE560,0xE561,0xE562,0xE563,0xE564,0xE565,0xE566,0xE567,0xE568,0xE569,0xE56A,0xE56B,0xE56C,0xE56D,0xE56E,0xE56F, + 0xE570,0xE571,0xE572,0xE573,0xE574,0xE575,0xE576,0xE577,0xE578,0xE579,0xE57A,0xE57B,0xE57C,0xE57D,0xE57E,0xE57F, + 0xE580,0xE581,0xE582,0xE583,0xE584,0xE585,0xE586,0xE587,0xE588,0xE589,0xE58A,0xE58B,0xE58C,0xE58D,0xE58E,0xE58F, + 0xE590,0xE591,0xE592,0xE593,0xE594,0xE595,0xE596,0xE597,0xE598,0xE599,0xE59A,0xE59B,0xE59C,0xE59D,0xE59E,0xE59F, + 0xE5A0,0xE5A1,0xE5A2,0xE5A3,0xE5A4,0xE5A5,0xE5A6,0xE5A7,0xE5A8,0xE5A9,0xE5AA,0xE5AB,0xE5AC,0xE5AD,0xE5AE,0xE5AF, + 0xE5B0,0xE5B1,0xE5B2,0xE5B3,0xE5B4,0xE5B5,0xE5B6,0xE5B7,0xE5B8,0xE5B9,0xE5BA,0xE5BB,0xE5BC,0xE5BD,0xE5BE,0xE5BF, + 0xE5C0,0xE5C1,0xE5C2,0xE5C3,0xE5C4,0xE5C5,0xE5C6,0xE5C7,0xE5C8,0xE5C9,0xE5CA,0xE5CB,0xE5CC,0xE5CD,0xE5CE,0xE5CF, + 0xE5D0,0xE5D1,0xE5D2,0xE5D3,0xE5D4,0xE5D5,0xE5D6,0xE5D7,0xE5D8,0xE5D9,0xE5DA,0xE5DB,0xE5DC,0xE5DD,0xE5DE,0xE5DF, + 0xE5E0,0xE5E1,0xE5E2,0xE5E3,0xE5E4,0xE5E5,0xE5E6,0xE5E7,0xE5E8,0xE5E9,0xE5EA,0xE5EB,0xE5EC,0xE5ED,0xE5EE,0xE5EF, + 0xE5F0,0xE5F1,0xE5F2,0xE5F3,0xE5F4,0xE5F5,0xE5F6,0xE5F7,0xE5F8,0xE5F9,0xE5FA,0xE5FB,0xE5FC,0xE5FD,0xE5FE,0xE5FF, + 0xE600,0xE601,0xE602,0xE603,0xE604,0xE605,0xE606,0xE607,0xE608,0xE609,0xE60A,0xE60B,0xE60C,0xE60D,0xE60E,0xE60F, + 0xE610,0xE611,0xE612,0xE613,0xE614,0xE615,0xE616,0xE617,0xE618,0xE619,0xE61A,0xE61B,0xE61C,0xE61D,0xE61E,0xE61F, + 0xE620,0xE621,0xE622,0xE623,0xE624,0xE625,0xE626,0xE627,0xE628,0xE629,0xE62A,0xE62B,0xE62C,0xE62D,0xE62E,0xE62F, + 0xE630,0xE631,0xE632,0xE633,0xE634,0xE635,0xE636,0xE637,0xE638,0xE639,0xE63A,0xE63B,0xE63C,0xE63D,0xE63E,0xE63F, + 0xE640,0xE641,0xE642,0xE643,0xE644,0xE645,0xE646,0xE647,0xE648,0xE649,0xE64A,0xE64B,0xE64C,0xE64D,0xE64E,0xE64F, + 0xE650,0xE651,0xE652,0xE653,0xE654,0xE655,0xE656,0xE657,0xE658,0xE659,0xE65A,0xE65B,0xE65C,0xE65D,0xE65E,0xE65F, + 0xE660,0xE661,0xE662,0xE663,0xE664,0xE665,0xE666,0xE667,0xE668,0xE669,0xE66A,0xE66B,0xE66C,0xE66D,0xE66E,0xE66F, + 0xE670,0xE671,0xE672,0xE673,0xE674,0xE675,0xE676,0xE677,0xE678,0xE679,0xE67A,0xE67B,0xE67C,0xE67D,0xE67E,0xE67F, + 0xE680,0xE681,0xE682,0xE683,0xE684,0xE685,0xE686,0xE687,0xE688,0xE689,0xE68A,0xE68B,0xE68C,0xE68D,0xE68E,0xE68F, + 0xE690,0xE691,0xE692,0xE693,0xE694,0xE695,0xE696,0xE697,0xE698,0xE699,0xE69A,0xE69B,0xE69C,0xE69D,0xE69E,0xE69F, + 0xE6A0,0xE6A1,0xE6A2,0xE6A3,0xE6A4,0xE6A5,0xE6A6,0xE6A7,0xE6A8,0xE6A9,0xE6AA,0xE6AB,0xE6AC,0xE6AD,0xE6AE,0xE6AF, + 0xE6B0,0xE6B1,0xE6B2,0xE6B3,0xE6B4,0xE6B5,0xE6B6,0xE6B7,0xE6B8,0xE6B9,0xE6BA,0xE6BB,0xE6BC,0xE6BD,0xE6BE,0xE6BF, + 0xE6C0,0xE6C1,0xE6C2,0xE6C3,0xE6C4,0xE6C5,0xE6C6,0xE6C7,0xE6C8,0xE6C9,0xE6CA,0xE6CB,0xE6CC,0xE6CD,0xE6CE,0xE6CF, + 0xE6D0,0xE6D1,0xE6D2,0xE6D3,0xE6D4,0xE6D5,0xE6D6,0xE6D7,0xE6D8,0xE6D9,0xE6DA,0xE6DB,0xE6DC,0xE6DD,0xE6DE,0xE6DF, + 0xE6E0,0xE6E1,0xE6E2,0xE6E3,0xE6E4,0xE6E5,0xE6E6,0xE6E7,0xE6E8,0xE6E9,0xE6EA,0xE6EB,0xE6EC,0xE6ED,0xE6EE,0xE6EF, + 0xE6F0,0xE6F1,0xE6F2,0xE6F3,0xE6F4,0xE6F5,0xE6F6,0xE6F7,0xE6F8,0xE6F9,0xE6FA,0xE6FB,0xE6FC,0xE6FD,0xE6FE,0xE6FF, + 0xE700,0xE701,0xE702,0xE703,0xE704,0xE705,0xE706,0xE707,0xE708,0xE709,0xE70A,0xE70B,0xE70C,0xE70D,0xE70E,0xE70F, + 0xE710,0xE711,0xE712,0xE713,0xE714,0xE715,0xE716,0xE717,0xE718,0xE719,0xE71A,0xE71B,0xE71C,0xE71D,0xE71E,0xE71F, + 0xE720,0xE721,0xE722,0xE723,0xE724,0xE725,0xE726,0xE727,0xE728,0xE729,0xE72A,0xE72B,0xE72C,0xE72D,0xE72E,0xE72F, + 0xE730,0xE731,0xE732,0xE733,0xE734,0xE735,0xE736,0xE737,0xE738,0xE739,0xE73A,0xE73B,0xE73C,0xE73D,0xE73E,0xE73F, + 0xE740,0xE741,0xE742,0xE743,0xE744,0xE745,0xE746,0xE747,0xE748,0xE749,0xE74A,0xE74B,0xE74C,0xE74D,0xE74E,0xE74F, + 0xE750,0xE751,0xE752,0xE753,0xE754,0xE755,0xE756,0xE757,0xE758,0xE759,0xE75A,0xE75B,0xE75C,0xE75D,0xE75E,0xE75F, + 0xE760,0xE761,0xE762,0xE763,0xE764,0xE765,0xE766,0xE767,0xE768,0xE769,0xE76A,0xE76B,0xE76C,0xE76D,0xE76E,0xE76F, + 0xE770,0xE771,0xE772,0xE773,0xE774,0xE775,0xE776,0xE777,0xE778,0xE779,0xE77A,0xE77B,0xE77C,0xE77D,0xE77E,0xE77F, + 0xE780,0xE781,0xE782,0xE783,0xE784,0xE785,0xE786,0xE787,0xE788,0xE789,0xE78A,0xE78B,0xE78C,0xE78D,0xE78E,0xE78F, + 0xE790,0xE791,0xE792,0xE793,0xE794,0xE795,0xE796,0xE797,0xE798,0xE799,0xE79A,0xE79B,0xE79C,0xE79D,0xE79E,0xE79F, + 0xE7A0,0xE7A1,0xE7A2,0xE7A3,0xE7A4,0xE7A5,0xE7A6,0xE7A7,0xE7A8,0xE7A9,0xE7AA,0xE7AB,0xE7AC,0xE7AD,0xE7AE,0xE7AF, + 0xE7B0,0xE7B1,0xE7B2,0xE7B3,0xE7B4,0xE7B5,0xE7B6,0xE7B7,0xE7B8,0xE7B9,0xE7BA,0xE7BB,0xE7BC,0xE7BD,0xE7BE,0xE7BF, + 0xE7C0,0xE7C1,0xE7C2,0xE7C3,0xE7C4,0xE7C5,0xE7C6,0xE7C7,0xE7C8,0xE7C9,0xE7CA,0xE7CB,0xE7CC,0xE7CD,0xE7CE,0xE7CF, + 0xE7D0,0xE7D1,0xE7D2,0xE7D3,0xE7D4,0xE7D5,0xE7D6,0xE7D7,0xE7D8,0xE7D9,0xE7DA,0xE7DB,0xE7DC,0xE7DD,0xE7DE,0xE7DF, + 0xE7E0,0xE7E1,0xE7E2,0xE7E3,0xE7E4,0xE7E5,0xE7E6,0xE7E7,0xE7E8,0xE7E9,0xE7EA,0xE7EB,0xE7EC,0xE7ED,0xE7EE,0xE7EF, + 0xE7F0,0xE7F1,0xE7F2,0xE7F3,0xE7F4,0xE7F5,0xE7F6,0xE7F7,0xE7F8,0xE7F9,0xE7FA,0xE7FB,0xE7FC,0xE7FD,0xE7FE,0xE7FF, + 0xE800,0xE801,0xE802,0xE803,0xE804,0xE805,0xE806,0xE807,0xE808,0xE809,0xE80A,0xE80B,0xE80C,0xE80D,0xE80E,0xE80F, + 0xE810,0xE811,0xE812,0xE813,0xE814,0xE815,0xE816,0xE817,0xE818,0xE819,0xE81A,0xE81B,0xE81C,0xE81D,0xE81E,0xE81F, + 0xE820,0xE821,0xE822,0xE823,0xE824,0xE825,0xE826,0xE827,0xE828,0xE829,0xE82A,0xE82B,0xE82C,0xE82D,0xE82E,0xE82F, + 0xE830,0xE831,0xE832,0xE833,0xE834,0xE835,0xE836,0xE837,0xE838,0xE839,0xE83A,0xE83B,0xE83C,0xE83D,0xE83E,0xE83F, + 0xE840,0xE841,0xE842,0xE843,0xE844,0xE845,0xE846,0xE847,0xE848,0xE849,0xE84A,0xE84B,0xE84C,0xE84D,0xE84E,0xE84F, + 0xE850,0xE851,0xE852,0xE853,0xE854,0xE855,0xE856,0xE857,0xE858,0xE859,0xE85A,0xE85B,0xE85C,0xE85D,0xE85E,0xE85F, + 0xE860,0xE861,0xE862,0xE863,0xE864,0xE865,0xE866,0xE867,0xE868,0xE869,0xE86A,0xE86B,0xE86C,0xE86D,0xE86E,0xE86F, + 0xE870,0xE871,0xE872,0xE873,0xE874,0xE875,0xE876,0xE877,0xE878,0xE879,0xE87A,0xE87B,0xE87C,0xE87D,0xE87E,0xE87F, + 0xE880,0xE881,0xE882,0xE883,0xE884,0xE885,0xE886,0xE887,0xE888,0xE889,0xE88A,0xE88B,0xE88C,0xE88D,0xE88E,0xE88F, + 0xE890,0xE891,0xE892,0xE893,0xE894,0xE895,0xE896,0xE897,0xE898,0xE899,0xE89A,0xE89B,0xE89C,0xE89D,0xE89E,0xE89F, + 0xE8A0,0xE8A1,0xE8A2,0xE8A3,0xE8A4,0xE8A5,0xE8A6,0xE8A7,0xE8A8,0xE8A9,0xE8AA,0xE8AB,0xE8AC,0xE8AD,0xE8AE,0xE8AF, + 0xE8B0,0xE8B1,0xE8B2,0xE8B3,0xE8B4,0xE8B5,0xE8B6,0xE8B7,0xE8B8,0xE8B9,0xE8BA,0xE8BB,0xE8BC,0xE8BD,0xE8BE,0xE8BF, + 0xE8C0,0xE8C1,0xE8C2,0xE8C3,0xE8C4,0xE8C5,0xE8C6,0xE8C7,0xE8C8,0xE8C9,0xE8CA,0xE8CB,0xE8CC,0xE8CD,0xE8CE,0xE8CF, + 0xE8D0,0xE8D1,0xE8D2,0xE8D3,0xE8D4,0xE8D5,0xE8D6,0xE8D7,0xE8D8,0xE8D9,0xE8DA,0xE8DB,0xE8DC,0xE8DD,0xE8DE,0xE8DF, + 0xE8E0,0xE8E1,0xE8E2,0xE8E3,0xE8E4,0xE8E5,0xE8E6,0xE8E7,0xE8E8,0xE8E9,0xE8EA,0xE8EB,0xE8EC,0xE8ED,0xE8EE,0xE8EF, + 0xE8F0,0xE8F1,0xE8F2,0xE8F3,0xE8F4,0xE8F5,0xE8F6,0xE8F7,0xE8F8,0xE8F9,0xE8FA,0xE8FB,0xE8FC,0xE8FD,0xE8FE,0xE8FF, + 0xE900,0xE901,0xE902,0xE903,0xE904,0xE905,0xE906,0xE907,0xE908,0xE909,0xE90A,0xE90B,0xE90C,0xE90D,0xE90E,0xE90F, + 0xE910,0xE911,0xE912,0xE913,0xE914,0xE915,0xE916,0xE917,0xE918,0xE919,0xE91A,0xE91B,0xE91C,0xE91D,0xE91E,0xE91F, + 0xE920,0xE921,0xE922,0xE923,0xE924,0xE925,0xE926,0xE927,0xE928,0xE929,0xE92A,0xE92B,0xE92C,0xE92D,0xE92E,0xE92F, + 0xE930,0xE931,0xE932,0xE933,0xE934,0xE935,0xE936,0xE937,0xE938,0xE939,0xE93A,0xE93B,0xE93C,0xE93D,0xE93E,0xE93F, + 0xE940,0xE941,0xE942,0xE943,0xE944,0xE945,0xE946,0xE947,0xE948,0xE949,0xE94A,0xE94B,0xE94C,0xE94D,0xE94E,0xE94F, + 0xE950,0xE951,0xE952,0xE953,0xE954,0xE955,0xE956,0xE957,0xE958,0xE959,0xE95A,0xE95B,0xE95C,0xE95D,0xE95E,0xE95F, + 0xE960,0xE961,0xE962,0xE963,0xE964,0xE965,0xE966,0xE967,0xE968,0xE969,0xE96A,0xE96B,0xE96C,0xE96D,0xE96E,0xE96F, + 0xE970,0xE971,0xE972,0xE973,0xE974,0xE975,0xE976,0xE977,0xE978,0xE979,0xE97A,0xE97B,0xE97C,0xE97D,0xE97E,0xE97F, + 0xE980,0xE981,0xE982,0xE983,0xE984,0xE985,0xE986,0xE987,0xE988,0xE989,0xE98A,0xE98B,0xE98C,0xE98D,0xE98E,0xE98F, + 0xE990,0xE991,0xE992,0xE993,0xE994,0xE995,0xE996,0xE997,0xE998,0xE999,0xE99A,0xE99B,0xE99C,0xE99D,0xE99E,0xE99F, + 0xE9A0,0xE9A1,0xE9A2,0xE9A3,0xE9A4,0xE9A5,0xE9A6,0xE9A7,0xE9A8,0xE9A9,0xE9AA,0xE9AB,0xE9AC,0xE9AD,0xE9AE,0xE9AF, + 0xE9B0,0xE9B1,0xE9B2,0xE9B3,0xE9B4,0xE9B5,0xE9B6,0xE9B7,0xE9B8,0xE9B9,0xE9BA,0xE9BB,0xE9BC,0xE9BD,0xE9BE,0xE9BF, + 0xE9C0,0xE9C1,0xE9C2,0xE9C3,0xE9C4,0xE9C5,0xE9C6,0xE9C7,0xE9C8,0xE9C9,0xE9CA,0xE9CB,0xE9CC,0xE9CD,0xE9CE,0xE9CF, + 0xE9D0,0xE9D1,0xE9D2,0xE9D3,0xE9D4,0xE9D5,0xE9D6,0xE9D7,0xE9D8,0xE9D9,0xE9DA,0xE9DB,0xE9DC,0xE9DD,0xE9DE,0xE9DF, + 0xE9E0,0xE9E1,0xE9E2,0xE9E3,0xE9E4,0xE9E5,0xE9E6,0xE9E7,0xE9E8,0xE9E9,0xE9EA,0xE9EB,0xE9EC,0xE9ED,0xE9EE,0xE9EF, + 0xE9F0,0xE9F1,0xE9F2,0xE9F3,0xE9F4,0xE9F5,0xE9F6,0xE9F7,0xE9F8,0xE9F9,0xE9FA,0xE9FB,0xE9FC,0xE9FD,0xE9FE,0xE9FF, + 0xEA00,0xEA01,0xEA02,0xEA03,0xEA04,0xEA05,0xEA06,0xEA07,0xEA08,0xEA09,0xEA0A,0xEA0B,0xEA0C,0xEA0D,0xEA0E,0xEA0F, + 0xEA10,0xEA11,0xEA12,0xEA13,0xEA14,0xEA15,0xEA16,0xEA17,0xEA18,0xEA19,0xEA1A,0xEA1B,0xEA1C,0xEA1D,0xEA1E,0xEA1F, + 0xEA20,0xEA21,0xEA22,0xEA23,0xEA24,0xEA25,0xEA26,0xEA27,0xEA28,0xEA29,0xEA2A,0xEA2B,0xEA2C,0xEA2D,0xEA2E,0xEA2F, + 0xEA30,0xEA31,0xEA32,0xEA33,0xEA34,0xEA35,0xEA36,0xEA37,0xEA38,0xEA39,0xEA3A,0xEA3B,0xEA3C,0xEA3D,0xEA3E,0xEA3F, + 0xEA40,0xEA41,0xEA42,0xEA43,0xEA44,0xEA45,0xEA46,0xEA47,0xEA48,0xEA49,0xEA4A,0xEA4B,0xEA4C,0xEA4D,0xEA4E,0xEA4F, + 0xEA50,0xEA51,0xEA52,0xEA53,0xEA54,0xEA55,0xEA56,0xEA57,0xEA58,0xEA59,0xEA5A,0xEA5B,0xEA5C,0xEA5D,0xEA5E,0xEA5F, + 0xEA60,0xEA61,0xEA62,0xEA63,0xEA64,0xEA65,0xEA66,0xEA67,0xEA68,0xEA69,0xEA6A,0xEA6B,0xEA6C,0xEA6D,0xEA6E,0xEA6F, + 0xEA70,0xEA71,0xEA72,0xEA73,0xEA74,0xEA75,0xEA76,0xEA77,0xEA78,0xEA79,0xEA7A,0xEA7B,0xEA7C,0xEA7D,0xEA7E,0xEA7F, + 0xEA80,0xEA81,0xEA82,0xEA83,0xEA84,0xEA85,0xEA86,0xEA87,0xEA88,0xEA89,0xEA8A,0xEA8B,0xEA8C,0xEA8D,0xEA8E,0xEA8F, + 0xEA90,0xEA91,0xEA92,0xEA93,0xEA94,0xEA95,0xEA96,0xEA97,0xEA98,0xEA99,0xEA9A,0xEA9B,0xEA9C,0xEA9D,0xEA9E,0xEA9F, + 0xEAA0,0xEAA1,0xEAA2,0xEAA3,0xEAA4,0xEAA5,0xEAA6,0xEAA7,0xEAA8,0xEAA9,0xEAAA,0xEAAB,0xEAAC,0xEAAD,0xEAAE,0xEAAF, + 0xEAB0,0xEAB1,0xEAB2,0xEAB3,0xEAB4,0xEAB5,0xEAB6,0xEAB7,0xEAB8,0xEAB9,0xEABA,0xEABB,0xEABC,0xEABD,0xEABE,0xEABF, + 0xEAC0,0xEAC1,0xEAC2,0xEAC3,0xEAC4,0xEAC5,0xEAC6,0xEAC7,0xEAC8,0xEAC9,0xEACA,0xEACB,0xEACC,0xEACD,0xEACE,0xEACF, + 0xEAD0,0xEAD1,0xEAD2,0xEAD3,0xEAD4,0xEAD5,0xEAD6,0xEAD7,0xEAD8,0xEAD9,0xEADA,0xEADB,0xEADC,0xEADD,0xEADE,0xEADF, + 0xEAE0,0xEAE1,0xEAE2,0xEAE3,0xEAE4,0xEAE5,0xEAE6,0xEAE7,0xEAE8,0xEAE9,0xEAEA,0xEAEB,0xEAEC,0xEAED,0xEAEE,0xEAEF, + 0xEAF0,0xEAF1,0xEAF2,0xEAF3,0xEAF4,0xEAF5,0xEAF6,0xEAF7,0xEAF8,0xEAF9,0xEAFA,0xEAFB,0xEAFC,0xEAFD,0xEAFE,0xEAFF, + 0xEB00,0xEB01,0xEB02,0xEB03,0xEB04,0xEB05,0xEB06,0xEB07,0xEB08,0xEB09,0xEB0A,0xEB0B,0xEB0C,0xEB0D,0xEB0E,0xEB0F, + 0xEB10,0xEB11,0xEB12,0xEB13,0xEB14,0xEB15,0xEB16,0xEB17,0xEB18,0xEB19,0xEB1A,0xEB1B,0xEB1C,0xEB1D,0xEB1E,0xEB1F, + 0xEB20,0xEB21,0xEB22,0xEB23,0xEB24,0xEB25,0xEB26,0xEB27,0xEB28,0xEB29,0xEB2A,0xEB2B,0xEB2C,0xEB2D,0xEB2E,0xEB2F, + 0xEB30,0xEB31,0xEB32,0xEB33,0xEB34,0xEB35,0xEB36,0xEB37,0xEB38,0xEB39,0xEB3A,0xEB3B,0xEB3C,0xEB3D,0xEB3E,0xEB3F, + 0xEB40,0xEB41,0xEB42,0xEB43,0xEB44,0xEB45,0xEB46,0xEB47,0xEB48,0xEB49,0xEB4A,0xEB4B,0xEB4C,0xEB4D,0xEB4E,0xEB4F, + 0xEB50,0xEB51,0xEB52,0xEB53,0xEB54,0xEB55,0xEB56,0xEB57,0xEB58,0xEB59,0xEB5A,0xEB5B,0xEB5C,0xEB5D,0xEB5E,0xEB5F, + 0xEB60,0xEB61,0xEB62,0xEB63,0xEB64,0xEB65,0xEB66,0xEB67,0xEB68,0xEB69,0xEB6A,0xEB6B,0xEB6C,0xEB6D,0xEB6E,0xEB6F, + 0xEB70,0xEB71,0xEB72,0xEB73,0xEB74,0xEB75,0xEB76,0xEB77,0xEB78,0xEB79,0xEB7A,0xEB7B,0xEB7C,0xEB7D,0xEB7E,0xEB7F, + 0xEB80,0xEB81,0xEB82,0xEB83,0xEB84,0xEB85,0xEB86,0xEB87,0xEB88,0xEB89,0xEB8A,0xEB8B,0xEB8C,0xEB8D,0xEB8E,0xEB8F, + 0xEB90,0xEB91,0xEB92,0xEB93,0xEB94,0xEB95,0xEB96,0xEB97,0xEB98,0xEB99,0xEB9A,0xEB9B,0xEB9C,0xEB9D,0xEB9E,0xEB9F, + 0xEBA0,0xEBA1,0xEBA2,0xEBA3,0xEBA4,0xEBA5,0xEBA6,0xEBA7,0xEBA8,0xEBA9,0xEBAA,0xEBAB,0xEBAC,0xEBAD,0xEBAE,0xEBAF, + 0xEBB0,0xEBB1,0xEBB2,0xEBB3,0xEBB4,0xEBB5,0xEBB6,0xEBB7,0xEBB8,0xEBB9,0xEBBA,0xEBBB,0xEBBC,0xEBBD,0xEBBE,0xEBBF, + 0xEBC0,0xEBC1,0xEBC2,0xEBC3,0xEBC4,0xEBC5,0xEBC6,0xEBC7,0xEBC8,0xEBC9,0xEBCA,0xEBCB,0xEBCC,0xEBCD,0xEBCE,0xEBCF, + 0xEBD0,0xEBD1,0xEBD2,0xEBD3,0xEBD4,0xEBD5,0xEBD6,0xEBD7,0xEBD8,0xEBD9,0xEBDA,0xEBDB,0xEBDC,0xEBDD,0xEBDE,0xEBDF, + 0xEBE0,0xEBE1,0xEBE2,0xEBE3,0xEBE4,0xEBE5,0xEBE6,0xEBE7,0xEBE8,0xEBE9,0xEBEA,0xEBEB,0xEBEC,0xEBED,0xEBEE,0xEBEF, + 0xEBF0,0xEBF1,0xEBF2,0xEBF3,0xEBF4,0xEBF5,0xEBF6,0xEBF7,0xEBF8,0xEBF9,0xEBFA,0xEBFB,0xEBFC,0xEBFD,0xEBFE,0xEBFF, + 0xEC00,0xEC01,0xEC02,0xEC03,0xEC04,0xEC05,0xEC06,0xEC07,0xEC08,0xEC09,0xEC0A,0xEC0B,0xEC0C,0xEC0D,0xEC0E,0xEC0F, + 0xEC10,0xEC11,0xEC12,0xEC13,0xEC14,0xEC15,0xEC16,0xEC17,0xEC18,0xEC19,0xEC1A,0xEC1B,0xEC1C,0xEC1D,0xEC1E,0xEC1F, + 0xEC20,0xEC21,0xEC22,0xEC23,0xEC24,0xEC25,0xEC26,0xEC27,0xEC28,0xEC29,0xEC2A,0xEC2B,0xEC2C,0xEC2D,0xEC2E,0xEC2F, + 0xEC30,0xEC31,0xEC32,0xEC33,0xEC34,0xEC35,0xEC36,0xEC37,0xEC38,0xEC39,0xEC3A,0xEC3B,0xEC3C,0xEC3D,0xEC3E,0xEC3F, + 0xEC40,0xEC41,0xEC42,0xEC43,0xEC44,0xEC45,0xEC46,0xEC47,0xEC48,0xEC49,0xEC4A,0xEC4B,0xEC4C,0xEC4D,0xEC4E,0xEC4F, + 0xEC50,0xEC51,0xEC52,0xEC53,0xEC54,0xEC55,0xEC56,0xEC57,0xEC58,0xEC59,0xEC5A,0xEC5B,0xEC5C,0xEC5D,0xEC5E,0xEC5F, + 0xEC60,0xEC61,0xEC62,0xEC63,0xEC64,0xEC65,0xEC66,0xEC67,0xEC68,0xEC69,0xEC6A,0xEC6B,0xEC6C,0xEC6D,0xEC6E,0xEC6F, + 0xEC70,0xEC71,0xEC72,0xEC73,0xEC74,0xEC75,0xEC76,0xEC77,0xEC78,0xEC79,0xEC7A,0xEC7B,0xEC7C,0xEC7D,0xEC7E,0xEC7F, + 0xEC80,0xEC81,0xEC82,0xEC83,0xEC84,0xEC85,0xEC86,0xEC87,0xEC88,0xEC89,0xEC8A,0xEC8B,0xEC8C,0xEC8D,0xEC8E,0xEC8F, + 0xEC90,0xEC91,0xEC92,0xEC93,0xEC94,0xEC95,0xEC96,0xEC97,0xEC98,0xEC99,0xEC9A,0xEC9B,0xEC9C,0xEC9D,0xEC9E,0xEC9F, + 0xECA0,0xECA1,0xECA2,0xECA3,0xECA4,0xECA5,0xECA6,0xECA7,0xECA8,0xECA9,0xECAA,0xECAB,0xECAC,0xECAD,0xECAE,0xECAF, + 0xECB0,0xECB1,0xECB2,0xECB3,0xECB4,0xECB5,0xECB6,0xECB7,0xECB8,0xECB9,0xECBA,0xECBB,0xECBC,0xECBD,0xECBE,0xECBF, + 0xECC0,0xECC1,0xECC2,0xECC3,0xECC4,0xECC5,0xECC6,0xECC7,0xECC8,0xECC9,0xECCA,0xECCB,0xECCC,0xECCD,0xECCE,0xECCF, + 0xECD0,0xECD1,0xECD2,0xECD3,0xECD4,0xECD5,0xECD6,0xECD7,0xECD8,0xECD9,0xECDA,0xECDB,0xECDC,0xECDD,0xECDE,0xECDF, + 0xECE0,0xECE1,0xECE2,0xECE3,0xECE4,0xECE5,0xECE6,0xECE7,0xECE8,0xECE9,0xECEA,0xECEB,0xECEC,0xECED,0xECEE,0xECEF, + 0xECF0,0xECF1,0xECF2,0xECF3,0xECF4,0xECF5,0xECF6,0xECF7,0xECF8,0xECF9,0xECFA,0xECFB,0xECFC,0xECFD,0xECFE,0xECFF, + 0xED00,0xED01,0xED02,0xED03,0xED04,0xED05,0xED06,0xED07,0xED08,0xED09,0xED0A,0xED0B,0xED0C,0xED0D,0xED0E,0xED0F, + 0xED10,0xED11,0xED12,0xED13,0xED14,0xED15,0xED16,0xED17,0xED18,0xED19,0xED1A,0xED1B,0xED1C,0xED1D,0xED1E,0xED1F, + 0xED20,0xED21,0xED22,0xED23,0xED24,0xED25,0xED26,0xED27,0xED28,0xED29,0xED2A,0xED2B,0xED2C,0xED2D,0xED2E,0xED2F, + 0xED30,0xED31,0xED32,0xED33,0xED34,0xED35,0xED36,0xED37,0xED38,0xED39,0xED3A,0xED3B,0xED3C,0xED3D,0xED3E,0xED3F, + 0xED40,0xED41,0xED42,0xED43,0xED44,0xED45,0xED46,0xED47,0xED48,0xED49,0xED4A,0xED4B,0xED4C,0xED4D,0xED4E,0xED4F, + 0xED50,0xED51,0xED52,0xED53,0xED54,0xED55,0xED56,0xED57,0xED58,0xED59,0xED5A,0xED5B,0xED5C,0xED5D,0xED5E,0xED5F, + 0xED60,0xED61,0xED62,0xED63,0xED64,0xED65,0xED66,0xED67,0xED68,0xED69,0xED6A,0xED6B,0xED6C,0xED6D,0xED6E,0xED6F, + 0xED70,0xED71,0xED72,0xED73,0xED74,0xED75,0xED76,0xED77,0xED78,0xED79,0xED7A,0xED7B,0xED7C,0xED7D,0xED7E,0xED7F, + 0xED80,0xED81,0xED82,0xED83,0xED84,0xED85,0xED86,0xED87,0xED88,0xED89,0xED8A,0xED8B,0xED8C,0xED8D,0xED8E,0xED8F, + 0xED90,0xED91,0xED92,0xED93,0xED94,0xED95,0xED96,0xED97,0xED98,0xED99,0xED9A,0xED9B,0xED9C,0xED9D,0xED9E,0xED9F, + 0xEDA0,0xEDA1,0xEDA2,0xEDA3,0xEDA4,0xEDA5,0xEDA6,0xEDA7,0xEDA8,0xEDA9,0xEDAA,0xEDAB,0xEDAC,0xEDAD,0xEDAE,0xEDAF, + 0xEDB0,0xEDB1,0xEDB2,0xEDB3,0xEDB4,0xEDB5,0xEDB6,0xEDB7,0xEDB8,0xEDB9,0xEDBA,0xEDBB,0xEDBC,0xEDBD,0xEDBE,0xEDBF, + 0xEDC0,0xEDC1,0xEDC2,0xEDC3,0xEDC4,0xEDC5,0xEDC6,0xEDC7,0xEDC8,0xEDC9,0xEDCA,0xEDCB,0xEDCC,0xEDCD,0xEDCE,0xEDCF, + 0xEDD0,0xEDD1,0xEDD2,0xEDD3,0xEDD4,0xEDD5,0xEDD6,0xEDD7,0xEDD8,0xEDD9,0xEDDA,0xEDDB,0xEDDC,0xEDDD,0xEDDE,0xEDDF, + 0xEDE0,0xEDE1,0xEDE2,0xEDE3,0xEDE4,0xEDE5,0xEDE6,0xEDE7,0xEDE8,0xEDE9,0xEDEA,0xEDEB,0xEDEC,0xEDED,0xEDEE,0xEDEF, + 0xEDF0,0xEDF1,0xEDF2,0xEDF3,0xEDF4,0xEDF5,0xEDF6,0xEDF7,0xEDF8,0xEDF9,0xEDFA,0xEDFB,0xEDFC,0xEDFD,0xEDFE,0xEDFF, + 0xEE00,0xEE01,0xEE02,0xEE03,0xEE04,0xEE05,0xEE06,0xEE07,0xEE08,0xEE09,0xEE0A,0xEE0B,0xEE0C,0xEE0D,0xEE0E,0xEE0F, + 0xEE10,0xEE11,0xEE12,0xEE13,0xEE14,0xEE15,0xEE16,0xEE17,0xEE18,0xEE19,0xEE1A,0xEE1B,0xEE1C,0xEE1D,0xEE1E,0xEE1F, + 0xEE20,0xEE21,0xEE22,0xEE23,0xEE24,0xEE25,0xEE26,0xEE27,0xEE28,0xEE29,0xEE2A,0xEE2B,0xEE2C,0xEE2D,0xEE2E,0xEE2F, + 0xEE30,0xEE31,0xEE32,0xEE33,0xEE34,0xEE35,0xEE36,0xEE37,0xEE38,0xEE39,0xEE3A,0xEE3B,0xEE3C,0xEE3D,0xEE3E,0xEE3F, + 0xEE40,0xEE41,0xEE42,0xEE43,0xEE44,0xEE45,0xEE46,0xEE47,0xEE48,0xEE49,0xEE4A,0xEE4B,0xEE4C,0xEE4D,0xEE4E,0xEE4F, + 0xEE50,0xEE51,0xEE52,0xEE53,0xEE54,0xEE55,0xEE56,0xEE57,0xEE58,0xEE59,0xEE5A,0xEE5B,0xEE5C,0xEE5D,0xEE5E,0xEE5F, + 0xEE60,0xEE61,0xEE62,0xEE63,0xEE64,0xEE65,0xEE66,0xEE67,0xEE68,0xEE69,0xEE6A,0xEE6B,0xEE6C,0xEE6D,0xEE6E,0xEE6F, + 0xEE70,0xEE71,0xEE72,0xEE73,0xEE74,0xEE75,0xEE76,0xEE77,0xEE78,0xEE79,0xEE7A,0xEE7B,0xEE7C,0xEE7D,0xEE7E,0xEE7F, + 0xEE80,0xEE81,0xEE82,0xEE83,0xEE84,0xEE85,0xEE86,0xEE87,0xEE88,0xEE89,0xEE8A,0xEE8B,0xEE8C,0xEE8D,0xEE8E,0xEE8F, + 0xEE90,0xEE91,0xEE92,0xEE93,0xEE94,0xEE95,0xEE96,0xEE97,0xEE98,0xEE99,0xEE9A,0xEE9B,0xEE9C,0xEE9D,0xEE9E,0xEE9F, + 0xEEA0,0xEEA1,0xEEA2,0xEEA3,0xEEA4,0xEEA5,0xEEA6,0xEEA7,0xEEA8,0xEEA9,0xEEAA,0xEEAB,0xEEAC,0xEEAD,0xEEAE,0xEEAF, + 0xEEB0,0xEEB1,0xEEB2,0xEEB3,0xEEB4,0xEEB5,0xEEB6,0xEEB7,0xEEB8,0xEEB9,0xEEBA,0xEEBB,0xEEBC,0xEEBD,0xEEBE,0xEEBF, + 0xEEC0,0xEEC1,0xEEC2,0xEEC3,0xEEC4,0xEEC5,0xEEC6,0xEEC7,0xEEC8,0xEEC9,0xEECA,0xEECB,0xEECC,0xEECD,0xEECE,0xEECF, + 0xEED0,0xEED1,0xEED2,0xEED3,0xEED4,0xEED5,0xEED6,0xEED7,0xEED8,0xEED9,0xEEDA,0xEEDB,0xEEDC,0xEEDD,0xEEDE,0xEEDF, + 0xEEE0,0xEEE1,0xEEE2,0xEEE3,0xEEE4,0xEEE5,0xEEE6,0xEEE7,0xEEE8,0xEEE9,0xEEEA,0xEEEB,0xEEEC,0xEEED,0xEEEE,0xEEEF, + 0xEEF0,0xEEF1,0xEEF2,0xEEF3,0xEEF4,0xEEF5,0xEEF6,0xEEF7,0xEEF8,0xEEF9,0xEEFA,0xEEFB,0xEEFC,0xEEFD,0xEEFE,0xEEFF, + 0xEF00,0xEF01,0xEF02,0xEF03,0xEF04,0xEF05,0xEF06,0xEF07,0xEF08,0xEF09,0xEF0A,0xEF0B,0xEF0C,0xEF0D,0xEF0E,0xEF0F, + 0xEF10,0xEF11,0xEF12,0xEF13,0xEF14,0xEF15,0xEF16,0xEF17,0xEF18,0xEF19,0xEF1A,0xEF1B,0xEF1C,0xEF1D,0xEF1E,0xEF1F, + 0xEF20,0xEF21,0xEF22,0xEF23,0xEF24,0xEF25,0xEF26,0xEF27,0xEF28,0xEF29,0xEF2A,0xEF2B,0xEF2C,0xEF2D,0xEF2E,0xEF2F, + 0xEF30,0xEF31,0xEF32,0xEF33,0xEF34,0xEF35,0xEF36,0xEF37,0xEF38,0xEF39,0xEF3A,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0xEF3F, + 0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46,0xEF47,0xEF48,0xEF49,0xEF4A,0xEF4B,0xEF4C,0xEF4D,0xEF4E,0xEF4F, + 0xEF50,0xEF51,0xEF52,0xEF53,0xEF54,0xEF55,0xEF56,0xEF57,0xEF58,0xEF59,0xEF5A,0xEF5B,0xEF5C,0xEF5D,0xEF5E,0xEF5F, + 0xEF60,0xEF61,0xEF62,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F, + 0xEF70,0xEF71,0xEF72,0xEF73,0xEF74,0xEF75,0xEF76,0xEF77,0xEF78,0xEF79,0xEF7A,0xEF7B,0xEF7C,0xEF7D,0xEF7E,0xEF7F, + 0xEF80,0xEF81,0xEF82,0xEF83,0xEF84,0xEF85,0xEF86,0xEF87,0xEF88,0xEF89,0xEF8A,0xEF8B,0xEF8C,0xEF8D,0xEF8E,0xEF8F, + 0xEF90,0xEF91,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0xEF97,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0xEF9F, + 0xEFA0,0xEFA1,0xEFA2,0xEFA3,0xEFA4,0xEFA5,0xEFA6,0xEFA7,0xEFA8,0xEFA9,0xEFAA,0xEFAB,0xEFAC,0xEFAD,0xEFAE,0xEFAF, + 0xEFB0,0xEFB1,0xEFB2,0xEFB3,0xEFB4,0xEFB5,0xEFB6,0xEFB7,0xEFB8,0xEFB9,0xEFBA,0xEFBB,0xEFBC,0xEFBD,0xEFBE,0xEFBF, + 0xEFC0,0xEFC1,0xEFC2,0xEFC3,0xEFC4,0xEFC5,0xEFC6,0xEFC7,0xEFC8,0xEFC9,0xEFCA,0xEFCB,0xEFCC,0xEFCD,0xEFCE,0xEFCF, + 0xEFD0,0xEFD1,0xEFD2,0xEFD3,0xEFD4,0xEFD5,0xEFD6,0xEFD7,0xEFD8,0xEFD9,0xEFDA,0xEFDB,0xEFDC,0xEFDD,0xEFDE,0xEFDF, + 0xEFE0,0xEFE1,0xEFE2,0xEFE3,0xEFE4,0xEFE5,0xEFE6,0xEFE7,0xEFE8,0xEFE9,0xEFEA,0xEFEB,0xEFEC,0xEFED,0xEFEE,0xEFEF, + 0xEFF0,0xEFF1,0xEFF2,0xEFF3,0xEFF4,0xEFF5,0xEFF6,0xEFF7,0xEFF8,0xEFF9,0xEFFA,0xEFFB,0xEFFC,0xEFFD,0xEFFE,0xEFFF, + 0xF000,0xF001,0xF002,0xF003,0xF004,0xF005,0xF006,0xF007,0xF008,0xF009,0xF00A,0xF00B,0xF00C,0xF00D,0xF00E,0xF00F, + 0xF010,0xF011,0xF012,0xF013,0xF014,0xF015,0xF016,0xF017,0xF018,0xF019,0xF01A,0xF01B,0xF01C,0xF01D,0xF01E,0xF01F, + 0xF020,0xF021,0xF022,0xF023,0xF024,0xF025,0xF026,0xF027,0xF028,0xF029,0xF02A,0xF02B,0xF02C,0xF02D,0xF02E,0xF02F, + 0xF030,0xF031,0xF032,0xF033,0xF034,0xF035,0xF036,0xF037,0xF038,0xF039,0xF03A,0xF03B,0xF03C,0xF03D,0xF03E,0xF03F, + 0xF040,0xF041,0xF042,0xF043,0xF044,0xF045,0xF046,0xF047,0xF048,0xF049,0xF04A,0xF04B,0xF04C,0xF04D,0xF04E,0xF04F, + 0xF050,0xF051,0xF052,0xF053,0xF054,0xF055,0xF056,0xF057,0xF058,0xF059,0xF05A,0xF05B,0xF05C,0xF05D,0xF05E,0xF05F, + 0xF060,0xF061,0xF062,0xF063,0xF064,0xF065,0xF066,0xF067,0xF068,0xF069,0xF06A,0xF06B,0xF06C,0xF06D,0xF06E,0xF06F, + 0xF070,0xF071,0xF072,0xF073,0xF074,0xF075,0xF076,0xF077,0xF078,0xF079,0xF07A,0xF07B,0xF07C,0xF07D,0xF07E,0xF07F, + 0xF080,0xF081,0xF082,0xF083,0xF084,0xF085,0xF086,0xF087,0xF088,0xF089,0xF08A,0xF08B,0xF08C,0xF08D,0xF08E,0xF08F, + 0xF090,0xF091,0xF092,0xF093,0xF094,0xF095,0xF096,0xF097,0xF098,0xF099,0xF09A,0xF09B,0xF09C,0xF09D,0xF09E,0xF09F, + 0xF0A0,0xF0A1,0xF0A2,0xF0A3,0xF0A4,0xF0A5,0xF0A6,0xF0A7,0xF0A8,0xF0A9,0xF0AA,0xF0AB,0xF0AC,0xF0AD,0xF0AE,0xF0AF, + 0xF0B0,0xF0B1,0xF0B2,0xF0B3,0xF0B4,0xF0B5,0xF0B6,0xF0B7,0xF0B8,0xF0B9,0xF0BA,0xF0BB,0xF0BC,0xF0BD,0xF0BE,0xF0BF, + 0xF0C0,0xF0C1,0xF0C2,0xF0C3,0xF0C4,0xF0C5,0xF0C6,0xF0C7,0xF0C8,0xF0C9,0xF0CA,0xF0CB,0xF0CC,0xF0CD,0xF0CE,0xF0CF, + 0xF0D0,0xF0D1,0xF0D2,0xF0D3,0xF0D4,0xF0D5,0xF0D6,0xF0D7,0xF0D8,0xF0D9,0xF0DA,0xF0DB,0xF0DC,0xF0DD,0xF0DE,0xF0DF, + 0xF0E0,0xF0E1,0xF0E2,0xF0E3,0xF0E4,0xF0E5,0xF0E6,0xF0E7,0xF0E8,0xF0E9,0xF0EA,0xF0EB,0xF0EC,0xF0ED,0xF0EE,0xF0EF, + 0xF0F0,0xF0F1,0xF0F2,0xF0F3,0xF0F4,0xF0F5,0xF0F6,0xF0F7,0xF0F8,0xF0F9,0xF0FA,0xF0FB,0xF0FC,0xF0FD,0xF0FE,0xF0FF, + 0xF100,0xF101,0xF102,0xF103,0xF104,0xF105,0xF106,0xF107,0xF108,0xF109,0xF10A,0xF10B,0xF10C,0xF10D,0xF10E,0xF10F, + 0xF110,0xF111,0xF112,0xF113,0xF114,0xF115,0xF116,0xF117,0xF118,0xF119,0xF11A,0xF11B,0xF11C,0xF11D,0xF11E,0xF11F, + 0xF120,0xF121,0xF122,0xF123,0xF124,0xF125,0xF126,0xF127,0xF128,0xF129,0xF12A,0xF12B,0xF12C,0xF12D,0xF12E,0xF12F, + 0xF130,0xF131,0xF132,0xF133,0xF134,0xF135,0xF136,0xF137,0xF138,0xF139,0xF13A,0xF13B,0xF13C,0xF13D,0xF13E,0xF13F, + 0xF140,0xF141,0xF142,0xF143,0xF144,0xF145,0xF146,0xF147,0xF148,0xF149,0xF14A,0xF14B,0xF14C,0xF14D,0xF14E,0xF14F, + 0xF150,0xF151,0xF152,0xF153,0xF154,0xF155,0xF156,0xF157,0xF158,0xF159,0xF15A,0xF15B,0xF15C,0xF15D,0xF15E,0xF15F, + 0xF160,0xF161,0xF162,0xF163,0xF164,0xF165,0xF166,0xF167,0xF168,0xF169,0xF16A,0xF16B,0xF16C,0xF16D,0xF16E,0xF16F, + 0xF170,0xF171,0xF172,0xF173,0xF174,0xF175,0xF176,0xF177,0xF178,0xF179,0xF17A,0xF17B,0xF17C,0xF17D,0xF17E,0xF17F, + 0xF180,0xF181,0xF182,0xF183,0xF184,0xF185,0xF186,0xF187,0xF188,0xF189,0xF18A,0xF18B,0xF18C,0xF18D,0xF18E,0xF18F, + 0xF190,0xF191,0xF192,0xF193,0xF194,0xF195,0xF196,0xF197,0xF198,0xF199,0xF19A,0xF19B,0xF19C,0xF19D,0xF19E,0xF19F, + 0xF1A0,0xF1A1,0xF1A2,0xF1A3,0xF1A4,0xF1A5,0xF1A6,0xF1A7,0xF1A8,0xF1A9,0xF1AA,0xF1AB,0xF1AC,0xF1AD,0xF1AE,0xF1AF, + 0xF1B0,0xF1B1,0xF1B2,0xF1B3,0xF1B4,0xF1B5,0xF1B6,0xF1B7,0xF1B8,0xF1B9,0xF1BA,0xF1BB,0xF1BC,0xF1BD,0xF1BE,0xF1BF, + 0xF1C0,0xF1C1,0xF1C2,0xF1C3,0xF1C4,0xF1C5,0xF1C6,0xF1C7,0xF1C8,0xF1C9,0xF1CA,0xF1CB,0xF1CC,0xF1CD,0xF1CE,0xF1CF, + 0xF1D0,0xF1D1,0xF1D2,0xF1D3,0xF1D4,0xF1D5,0xF1D6,0xF1D7,0xF1D8,0xF1D9,0xF1DA,0xF1DB,0xF1DC,0xF1DD,0xF1DE,0xF1DF, + 0xF1E0,0xF1E1,0xF1E2,0xF1E3,0xF1E4,0xF1E5,0xF1E6,0xF1E7,0xF1E8,0xF1E9,0xF1EA,0xF1EB,0xF1EC,0xF1ED,0xF1EE,0xF1EF, + 0xF1F0,0xF1F1,0xF1F2,0xF1F3,0xF1F4,0xF1F5,0xF1F6,0xF1F7,0xF1F8,0xF1F9,0xF1FA,0xF1FB,0xF1FC,0xF1FD,0xF1FE,0xF1FF, + 0xF200,0xF201,0xF202,0xF203,0xF204,0xF205,0xF206,0xF207,0xF208,0xF209,0xF20A,0xF20B,0xF20C,0xF20D,0xF20E,0xF20F, + 0xF210,0xF211,0xF212,0xF213,0xF214,0xF215,0xF216,0xF217,0xF218,0xF219,0xF21A,0xF21B,0xF21C,0xF21D,0xF21E,0xF21F, + 0xF220,0xF221,0xF222,0xF223,0xF224,0xF225,0xF226,0xF227,0xF228,0xF229,0xF22A,0xF22B,0xF22C,0xF22D,0xF22E,0xF22F, + 0xF230,0xF231,0xF232,0xF233,0xF234,0xF235,0xF236,0xF237,0xF238,0xF239,0xF23A,0xF23B,0xF23C,0xF23D,0xF23E,0xF23F, + 0xF240,0xF241,0xF242,0xF243,0xF244,0xF245,0xF246,0xF247,0xF248,0xF249,0xF24A,0xF24B,0xF24C,0xF24D,0xF24E,0xF24F, + 0xF250,0xF251,0xF252,0xF253,0xF254,0xF255,0xF256,0xF257,0xF258,0xF259,0xF25A,0xF25B,0xF25C,0xF25D,0xF25E,0xF25F, + 0xF260,0xF261,0xF262,0xF263,0xF264,0xF265,0xF266,0xF267,0xF268,0xF269,0xF26A,0xF26B,0xF26C,0xF26D,0xF26E,0xF26F, + 0xF270,0xF271,0xF272,0xF273,0xF274,0xF275,0xF276,0xF277,0xF278,0xF279,0xF27A,0xF27B,0xF27C,0xF27D,0xF27E,0xF27F, + 0xF280,0xF281,0xF282,0xF283,0xF284,0xF285,0xF286,0xF287,0xF288,0xF289,0xF28A,0xF28B,0xF28C,0xF28D,0xF28E,0xF28F, + 0xF290,0xF291,0xF292,0xF293,0xF294,0xF295,0xF296,0xF297,0xF298,0xF299,0xF29A,0xF29B,0xF29C,0xF29D,0xF29E,0xF29F, + 0xF2A0,0xF2A1,0xF2A2,0xF2A3,0xF2A4,0xF2A5,0xF2A6,0xF2A7,0xF2A8,0xF2A9,0xF2AA,0xF2AB,0xF2AC,0xF2AD,0xF2AE,0xF2AF, + 0xF2B0,0xF2B1,0xF2B2,0xF2B3,0xF2B4,0xF2B5,0xF2B6,0xF2B7,0xF2B8,0xF2B9,0xF2BA,0xF2BB,0xF2BC,0xF2BD,0xF2BE,0xF2BF, + 0xF2C0,0xF2C1,0xF2C2,0xF2C3,0xF2C4,0xF2C5,0xF2C6,0xF2C7,0xF2C8,0xF2C9,0xF2CA,0xF2CB,0xF2CC,0xF2CD,0xF2CE,0xF2CF, + 0xF2D0,0xF2D1,0xF2D2,0xF2D3,0xF2D4,0xF2D5,0xF2D6,0xF2D7,0xF2D8,0xF2D9,0xF2DA,0xF2DB,0xF2DC,0xF2DD,0xF2DE,0xF2DF, + 0xF2E0,0xF2E1,0xF2E2,0xF2E3,0xF2E4,0xF2E5,0xF2E6,0xF2E7,0xF2E8,0xF2E9,0xF2EA,0xF2EB,0xF2EC,0xF2ED,0xF2EE,0xF2EF, + 0xF2F0,0xF2F1,0xF2F2,0xF2F3,0xF2F4,0xF2F5,0xF2F6,0xF2F7,0xF2F8,0xF2F9,0xF2FA,0xF2FB,0xF2FC,0xF2FD,0xF2FE,0xF2FF, + 0xF300,0xF301,0xF302,0xF303,0xF304,0xF305,0xF306,0xF307,0xF308,0xF309,0xF30A,0xF30B,0xF30C,0xF30D,0xF30E,0xF30F, + 0xF310,0xF311,0xF312,0xF313,0xF314,0xF315,0xF316,0xF317,0xF318,0xF319,0xF31A,0xF31B,0xF31C,0xF31D,0xF31E,0xF31F, + 0xF320,0xF321,0xF322,0xF323,0xF324,0xF325,0xF326,0xF327,0xF328,0xF329,0xF32A,0xF32B,0xF32C,0xF32D,0xF32E,0xF32F, + 0xF330,0xF331,0xF332,0xF333,0xF334,0xF335,0xF336,0xF337,0xF338,0xF339,0xF33A,0xF33B,0xF33C,0xF33D,0xF33E,0xF33F, + 0xF340,0xF341,0xF342,0xF343,0xF344,0xF345,0xF346,0xF347,0xF348,0xF349,0xF34A,0xF34B,0xF34C,0xF34D,0xF34E,0xF34F, + 0xF350,0xF351,0xF352,0xF353,0xF354,0xF355,0xF356,0xF357,0xF358,0xF359,0xF35A,0xF35B,0xF35C,0xF35D,0xF35E,0xF35F, + 0xF360,0xF361,0xF362,0xF363,0xF364,0xF365,0xF366,0xF367,0xF368,0xF369,0xF36A,0xF36B,0xF36C,0xF36D,0xF36E,0xF36F, + 0xF370,0xF371,0xF372,0xF373,0xF374,0xF375,0xF376,0xF377,0xF378,0xF379,0xF37A,0xF37B,0xF37C,0xF37D,0xF37E,0xF37F, + 0xF380,0xF381,0xF382,0xF383,0xF384,0xF385,0xF386,0xF387,0xF388,0xF389,0xF38A,0xF38B,0xF38C,0xF38D,0xF38E,0xF38F, + 0xF390,0xF391,0xF392,0xF393,0xF394,0xF395,0xF396,0xF397,0xF398,0xF399,0xF39A,0xF39B,0xF39C,0xF39D,0xF39E,0xF39F, + 0xF3A0,0xF3A1,0xF3A2,0xF3A3,0xF3A4,0xF3A5,0xF3A6,0xF3A7,0xF3A8,0xF3A9,0xF3AA,0xF3AB,0xF3AC,0xF3AD,0xF3AE,0xF3AF, + 0xF3B0,0xF3B1,0xF3B2,0xF3B3,0xF3B4,0xF3B5,0xF3B6,0xF3B7,0xF3B8,0xF3B9,0xF3BA,0xF3BB,0xF3BC,0xF3BD,0xF3BE,0xF3BF, + 0xF3C0,0xF3C1,0xF3C2,0xF3C3,0xF3C4,0xF3C5,0xF3C6,0xF3C7,0xF3C8,0xF3C9,0xF3CA,0xF3CB,0xF3CC,0xF3CD,0xF3CE,0xF3CF, + 0xF3D0,0xF3D1,0xF3D2,0xF3D3,0xF3D4,0xF3D5,0xF3D6,0xF3D7,0xF3D8,0xF3D9,0xF3DA,0xF3DB,0xF3DC,0xF3DD,0xF3DE,0xF3DF, + 0xF3E0,0xF3E1,0xF3E2,0xF3E3,0xF3E4,0xF3E5,0xF3E6,0xF3E7,0xF3E8,0xF3E9,0xF3EA,0xF3EB,0xF3EC,0xF3ED,0xF3EE,0xF3EF, + 0xF3F0,0xF3F1,0xF3F2,0xF3F3,0xF3F4,0xF3F5,0xF3F6,0xF3F7,0xF3F8,0xF3F9,0xF3FA,0xF3FB,0xF3FC,0xF3FD,0xF3FE,0xF3FF, + 0xF400,0xF401,0xF402,0xF403,0xF404,0xF405,0xF406,0xF407,0xF408,0xF409,0xF40A,0xF40B,0xF40C,0xF40D,0xF40E,0xF40F, + 0xF410,0xF411,0xF412,0xF413,0xF414,0xF415,0xF416,0xF417,0xF418,0xF419,0xF41A,0xF41B,0xF41C,0xF41D,0xF41E,0xF41F, + 0xF420,0xF421,0xF422,0xF423,0xF424,0xF425,0xF426,0xF427,0xF428,0xF429,0xF42A,0xF42B,0xF42C,0xF42D,0xF42E,0xF42F, + 0xF430,0xF431,0xF432,0xF433,0xF434,0xF435,0xF436,0xF437,0xF438,0xF439,0xF43A,0xF43B,0xF43C,0xF43D,0xF43E,0xF43F, + 0xF440,0xF441,0xF442,0xF443,0xF444,0xF445,0xF446,0xF447,0xF448,0xF449,0xF44A,0xF44B,0xF44C,0xF44D,0xF44E,0xF44F, + 0xF450,0xF451,0xF452,0xF453,0xF454,0xF455,0xF456,0xF457,0xF458,0xF459,0xF45A,0xF45B,0xF45C,0xF45D,0xF45E,0xF45F, + 0xF460,0xF461,0xF462,0xF463,0xF464,0xF465,0xF466,0xF467,0xF468,0xF469,0xF46A,0xF46B,0xF46C,0xF46D,0xF46E,0xF46F, + 0xF470,0xF471,0xF472,0xF473,0xF474,0xF475,0xF476,0xF477,0xF478,0xF479,0xF47A,0xF47B,0xF47C,0xF47D,0xF47E,0xF47F, + 0xF480,0xF481,0xF482,0xF483,0xF484,0xF485,0xF486,0xF487,0xF488,0xF489,0xF48A,0xF48B,0xF48C,0xF48D,0xF48E,0xF48F, + 0xF490,0xF491,0xF492,0xF493,0xF494,0xF495,0xF496,0xF497,0xF498,0xF499,0xF49A,0xF49B,0xF49C,0xF49D,0xF49E,0xF49F, + 0xF4A0,0xF4A1,0xF4A2,0xF4A3,0xF4A4,0xF4A5,0xF4A6,0xF4A7,0xF4A8,0xF4A9,0xF4AA,0xF4AB,0xF4AC,0xF4AD,0xF4AE,0xF4AF, + 0xF4B0,0xF4B1,0xF4B2,0xF4B3,0xF4B4,0xF4B5,0xF4B6,0xF4B7,0xF4B8,0xF4B9,0xF4BA,0xF4BB,0xF4BC,0xF4BD,0xF4BE,0xF4BF, + 0xF4C0,0xF4C1,0xF4C2,0xF4C3,0xF4C4,0xF4C5,0xF4C6,0xF4C7,0xF4C8,0xF4C9,0xF4CA,0xF4CB,0xF4CC,0xF4CD,0xF4CE,0xF4CF, + 0xF4D0,0xF4D1,0xF4D2,0xF4D3,0xF4D4,0xF4D5,0xF4D6,0xF4D7,0xF4D8,0xF4D9,0xF4DA,0xF4DB,0xF4DC,0xF4DD,0xF4DE,0xF4DF, + 0xF4E0,0xF4E1,0xF4E2,0xF4E3,0xF4E4,0xF4E5,0xF4E6,0xF4E7,0xF4E8,0xF4E9,0xF4EA,0xF4EB,0xF4EC,0xF4ED,0xF4EE,0xF4EF, + 0xF4F0,0xF4F1,0xF4F2,0xF4F3,0xF4F4,0xF4F5,0xF4F6,0xF4F7,0xF4F8,0xF4F9,0xF4FA,0xF4FB,0xF4FC,0xF4FD,0xF4FE,0xF4FF, + 0xF500,0xF501,0xF502,0xF503,0xF504,0xF505,0xF506,0xF507,0xF508,0xF509,0xF50A,0xF50B,0xF50C,0xF50D,0xF50E,0xF50F, + 0xF510,0xF511,0xF512,0xF513,0xF514,0xF515,0xF516,0xF517,0xF518,0xF519,0xF51A,0xF51B,0xF51C,0xF51D,0xF51E,0xF51F, + 0xF520,0xF521,0xF522,0xF523,0xF524,0xF525,0xF526,0xF527,0xF528,0xF529,0xF52A,0xF52B,0xF52C,0xF52D,0xF52E,0xF52F, + 0xF530,0xF531,0xF532,0xF533,0xF534,0xF535,0xF536,0xF537,0xF538,0xF539,0xF53A,0xF53B,0xF53C,0xF53D,0xF53E,0xF53F, + 0xF540,0xF541,0xF542,0xF543,0xF544,0xF545,0xF546,0xF547,0xF548,0xF549,0xF54A,0xF54B,0xF54C,0xF54D,0xF54E,0xF54F, + 0xF550,0xF551,0xF552,0xF553,0xF554,0xF555,0xF556,0xF557,0xF558,0xF559,0xF55A,0xF55B,0xF55C,0xF55D,0xF55E,0xF55F, + 0xF560,0xF561,0xF562,0xF563,0xF564,0xF565,0xF566,0xF567,0xF568,0xF569,0xF56A,0xF56B,0xF56C,0xF56D,0xF56E,0xF56F, + 0xF570,0xF571,0xF572,0xF573,0xF574,0xF575,0xF576,0xF577,0xF578,0xF579,0xF57A,0xF57B,0xF57C,0xF57D,0xF57E,0xF57F, + 0xF580,0xF581,0xF582,0xF583,0xF584,0xF585,0xF586,0xF587,0xF588,0xF589,0xF58A,0xF58B,0xF58C,0xF58D,0xF58E,0xF58F, + 0xF590,0xF591,0xF592,0xF593,0xF594,0xF595,0xF596,0xF597,0xF598,0xF599,0xF59A,0xF59B,0xF59C,0xF59D,0xF59E,0xF59F, + 0xF5A0,0xF5A1,0xF5A2,0xF5A3,0xF5A4,0xF5A5,0xF5A6,0xF5A7,0xF5A8,0xF5A9,0xF5AA,0xF5AB,0xF5AC,0xF5AD,0xF5AE,0xF5AF, + 0xF5B0,0xF5B1,0xF5B2,0xF5B3,0xF5B4,0xF5B5,0xF5B6,0xF5B7,0xF5B8,0xF5B9,0xF5BA,0xF5BB,0xF5BC,0xF5BD,0xF5BE,0xF5BF, + 0xF5C0,0xF5C1,0xF5C2,0xF5C3,0xF5C4,0xF5C5,0xF5C6,0xF5C7,0xF5C8,0xF5C9,0xF5CA,0xF5CB,0xF5CC,0xF5CD,0xF5CE,0xF5CF, + 0xF5D0,0xF5D1,0xF5D2,0xF5D3,0xF5D4,0xF5D5,0xF5D6,0xF5D7,0xF5D8,0xF5D9,0xF5DA,0xF5DB,0xF5DC,0xF5DD,0xF5DE,0xF5DF, + 0xF5E0,0xF5E1,0xF5E2,0xF5E3,0xF5E4,0xF5E5,0xF5E6,0xF5E7,0xF5E8,0xF5E9,0xF5EA,0xF5EB,0xF5EC,0xF5ED,0xF5EE,0xF5EF, + 0xF5F0,0xF5F1,0xF5F2,0xF5F3,0xF5F4,0xF5F5,0xF5F6,0xF5F7,0xF5F8,0xF5F9,0xF5FA,0xF5FB,0xF5FC,0xF5FD,0xF5FE,0xF5FF, + 0xF600,0xF601,0xF602,0xF603,0xF604,0xF605,0xF606,0xF607,0xF608,0xF609,0xF60A,0xF60B,0xF60C,0xF60D,0xF60E,0xF60F, + 0xF610,0xF611,0xF612,0xF613,0xF614,0xF615,0xF616,0xF617,0xF618,0xF619,0xF61A,0xF61B,0xF61C,0xF61D,0xF61E,0xF61F, + 0xF620,0xF621,0xF622,0xF623,0xF624,0xF625,0xF626,0xF627,0xF628,0xF629,0xF62A,0xF62B,0xF62C,0xF62D,0xF62E,0xF62F, + 0xF630,0xF631,0xF632,0xF633,0xF634,0xF635,0xF636,0xF637,0xF638,0xF639,0xF63A,0xF63B,0xF63C,0xF63D,0xF63E,0xF63F, + 0xF640,0xF641,0xF642,0xF643,0xF644,0xF645,0xF646,0xF647,0xF648,0xF649,0xF64A,0xF64B,0xF64C,0xF64D,0xF64E,0xF64F, + 0xF650,0xF651,0xF652,0xF653,0xF654,0xF655,0xF656,0xF657,0xF658,0xF659,0xF65A,0xF65B,0xF65C,0xF65D,0xF65E,0xF65F, + 0xF660,0xF661,0xF662,0xF663,0xF664,0xF665,0xF666,0xF667,0xF668,0xF669,0xF66A,0xF66B,0xF66C,0xF66D,0xF66E,0xF66F, + 0xF670,0xF671,0xF672,0xF673,0xF674,0xF675,0xF676,0xF677,0xF678,0xF679,0xF67A,0xF67B,0xF67C,0xF67D,0xF67E,0xF67F, + 0xF680,0xF681,0xF682,0xF683,0xF684,0xF685,0xF686,0xF687,0xF688,0xF689,0xF68A,0xF68B,0xF68C,0xF68D,0xF68E,0xF68F, + 0xF690,0xF691,0xF692,0xF693,0xF694,0xF695,0xF696,0xF697,0xF698,0xF699,0xF69A,0xF69B,0xF69C,0xF69D,0xF69E,0xF69F, + 0xF6A0,0xF6A1,0xF6A2,0xF6A3,0xF6A4,0xF6A5,0xF6A6,0xF6A7,0xF6A8,0xF6A9,0xF6AA,0xF6AB,0xF6AC,0xF6AD,0xF6AE,0xF6AF, + 0xF6B0,0xF6B1,0xF6B2,0xF6B3,0xF6B4,0xF6B5,0xF6B6,0xF6B7,0xF6B8,0xF6B9,0xF6BA,0xF6BB,0xF6BC,0xF6BD,0xF6BE,0xF6BF, + 0xF6C0,0xF6C1,0xF6C2,0xF6C3,0xF6C4,0xF6C5,0xF6C6,0xF6C7,0xF6C8,0xF6C9,0xF6CA,0xF6CB,0xF6CC,0xF6CD,0xF6CE,0xF6CF, + 0xF6D0,0xF6D1,0xF6D2,0xF6D3,0xF6D4,0xF6D5,0xF6D6,0xF6D7,0xF6D8,0xF6D9,0xF6DA,0xF6DB,0xF6DC,0xF6DD,0xF6DE,0xF6DF, + 0xF6E0,0xF6E1,0xF6E2,0xF6E3,0xF6E4,0xF6E5,0xF6E6,0xF6E7,0xF6E8,0xF6E9,0xF6EA,0xF6EB,0xF6EC,0xF6ED,0xF6EE,0xF6EF, + 0xF6F0,0xF6F1,0xF6F2,0xF6F3,0xF6F4,0xF6F5,0xF6F6,0xF6F7,0xF6F8,0xF6F9,0xF6FA,0xF6FB,0xF6FC,0xF6FD,0xF6FE,0xF6FF, + 0xF700,0xF701,0xF702,0xF703,0xF704,0xF705,0xF706,0xF707,0xF708,0xF709,0xF70A,0xF70B,0xF70C,0xF70D,0xF70E,0xF70F, + 0xF710,0xF711,0xF712,0xF713,0xF714,0xF715,0xF716,0xF717,0xF718,0xF719,0xF71A,0xF71B,0xF71C,0xF71D,0xF71E,0xF71F, + 0xF720,0xF721,0xF722,0xF723,0xF724,0xF725,0xF726,0xF727,0xF728,0xF729,0xF72A,0xF72B,0xF72C,0xF72D,0xF72E,0xF72F, + 0xF730,0xF731,0xF732,0xF733,0xF734,0xF735,0xF736,0xF737,0xF738,0xF739,0xF73A,0xF73B,0xF73C,0xF73D,0xF73E,0xF73F, + 0xF740,0xF741,0xF742,0xF743,0xF744,0xF745,0xF746,0xF747,0xF748,0xF749,0xF74A,0xF74B,0xF74C,0xF74D,0xF74E,0xF74F, + 0xF750,0xF751,0xF752,0xF753,0xF754,0xF755,0xF756,0xF757,0xF758,0xF759,0xF75A,0xF75B,0xF75C,0xF75D,0xF75E,0xF75F, + 0xF760,0xF761,0xF762,0xF763,0xF764,0xF765,0xF766,0xF767,0xF768,0xF769,0xF76A,0xF76B,0xF76C,0xF76D,0xF76E,0xF76F, + 0xF770,0xF771,0xF772,0xF773,0xF774,0xF775,0xF776,0xF777,0xF778,0xF779,0xF77A,0xF77B,0xF77C,0xF77D,0xF77E,0xF77F, + 0xF780,0xF781,0xF782,0xF783,0xF784,0xF785,0xF786,0xF787,0xF788,0xF789,0xF78A,0xF78B,0xF78C,0xF78D,0xF78E,0xF78F, + 0xF790,0xF791,0xF792,0xF793,0xF794,0xF795,0xF796,0xF797,0xF798,0xF799,0xF79A,0xF79B,0xF79C,0xF79D,0xF79E,0xF79F, + 0xF7A0,0xF7A1,0xF7A2,0xF7A3,0xF7A4,0xF7A5,0xF7A6,0xF7A7,0xF7A8,0xF7A9,0xF7AA,0xF7AB,0xF7AC,0xF7AD,0xF7AE,0xF7AF, + 0xF7B0,0xF7B1,0xF7B2,0xF7B3,0xF7B4,0xF7B5,0xF7B6,0xF7B7,0xF7B8,0xF7B9,0xF7BA,0xF7BB,0xF7BC,0xF7BD,0xF7BE,0xF7BF, + 0xF7C0,0xF7C1,0xF7C2,0xF7C3,0xF7C4,0xF7C5,0xF7C6,0xF7C7,0xF7C8,0xF7C9,0xF7CA,0xF7CB,0xF7CC,0xF7CD,0xF7CE,0xF7CF, + 0xF7D0,0xF7D1,0xF7D2,0xF7D3,0xF7D4,0xF7D5,0xF7D6,0xF7D7,0xF7D8,0xF7D9,0xF7DA,0xF7DB,0xF7DC,0xF7DD,0xF7DE,0xF7DF, + 0xF7E0,0xF7E1,0xF7E2,0xF7E3,0xF7E4,0xF7E5,0xF7E6,0xF7E7,0xF7E8,0xF7E9,0xF7EA,0xF7EB,0xF7EC,0xF7ED,0xF7EE,0xF7EF, + 0xF7F0,0xF7F1,0xF7F2,0xF7F3,0xF7F4,0xF7F5,0xF7F6,0xF7F7,0xF7F8,0xF7F9,0xF7FA,0xF7FB,0xF7FC,0xF7FD,0xF7FE,0xF7FF, + 0xF800,0xF801,0xF802,0xF803,0xF804,0xF805,0xF806,0xF807,0xF808,0xF809,0xF80A,0xF80B,0xF80C,0xF80D,0xF80E,0xF80F, + 0xF810,0xF811,0xF812,0xF813,0xF814,0xF815,0xF816,0xF817,0xF818,0xF819,0xF81A,0xF81B,0xF81C,0xF81D,0xF81E,0xF81F, + 0xF820,0xF821,0xF822,0xF823,0xF824,0xF825,0xF826,0xF827,0xF828,0xF829,0xF82A,0xF82B,0xF82C,0xF82D,0xF82E,0xF82F, + 0xF830,0xF831,0xF832,0xF833,0xF834,0xF835,0xF836,0xF837,0xF838,0xF839,0xF83A,0xF83B,0xF83C,0xF83D,0xF83E,0xF83F, + 0xF840,0xF841,0xF842,0xF843,0xF844,0xF845,0xF846,0xF847,0xF848,0xF849,0xF84A,0xF84B,0xF84C,0xF84D,0xF84E,0xF84F, + 0xF850,0xF851,0xF852,0xF853,0xF854,0xF855,0xF856,0xF857,0xF858,0xF859,0xF85A,0xF85B,0xF85C,0xF85D,0xF85E,0xF85F, + 0xF860,0xF861,0xF862,0xF863,0xF864,0xF865,0xF866,0xF867,0xF868,0xF869,0xF86A,0xF86B,0xF86C,0xF86D,0xF86E,0xF86F, + 0xF870,0xF871,0xF872,0xF873,0xF874,0xF875,0xF876,0xF877,0xF878,0xF879,0xF87A,0xF87B,0xF87C,0xF87D,0xF87E,0xF87F, + 0xF880,0xF881,0xF882,0xF883,0xF884,0xF885,0xF886,0xF887,0xF888,0xF889,0xF88A,0xF88B,0xF88C,0xF88D,0xF88E,0xF88F, + 0xF890,0xF891,0xF892,0xF893,0xF894,0xF895,0xF896,0xF897,0xF898,0xF899,0xF89A,0xF89B,0xF89C,0xF89D,0xF89E,0xF89F, + 0xF8A0,0xF8A1,0xF8A2,0xF8A3,0xF8A4,0xF8A5,0xF8A6,0xF8A7,0xF8A8,0xF8A9,0xF8AA,0xF8AB,0xF8AC,0xF8AD,0xF8AE,0xF8AF, + 0xF8B0,0xF8B1,0xF8B2,0xF8B3,0xF8B4,0xF8B5,0xF8B6,0xF8B7,0xF8B8,0xF8B9,0xF8BA,0xF8BB,0xF8BC,0xF8BD,0xF8BE,0xF8BF, + 0xF8C0,0xF8C1,0xF8C2,0xF8C3,0xF8C4,0xF8C5,0xF8C6,0xF8C7,0xF8C8,0xF8C9,0xF8CA,0xF8CB,0xF8CC,0xF8CD,0xF8CE,0xF8CF, + 0xF8D0,0xF8D1,0xF8D2,0xF8D3,0xF8D4,0xF8D5,0xF8D6,0xF8D7,0xF8D8,0xF8D9,0xF8DA,0xF8DB,0xF8DC,0xF8DD,0xF8DE,0xF8DF, + 0xF8E0,0xF8E1,0xF8E2,0xF8E3,0xF8E4,0xF8E5,0xF8E6,0xF8E7,0xF8E8,0xF8E9,0xF8EA,0xF8EB,0xF8EC,0xF8ED,0xF8EE,0xF8EF, + 0xF8F0,0xF8F1,0xF8F2,0xF8F3,0xF8F4,0xF8F5,0xF8F6,0xF8F7,0xF8F8,0xF8F9,0xF8FA,0xF8FB,0xF8FC,0xF8FD,0xF8FE,0xF8FF, + 0xF900,0xF901,0xF902,0xF903,0xF904,0xF905,0xF906,0xF907,0xF908,0xF909,0xF90A,0xF90B,0xF90C,0xF90D,0xF90E,0xF90F, + 0xF910,0xF911,0xF912,0xF913,0xF914,0xF915,0xF916,0xF917,0xF918,0xF919,0xF91A,0xF91B,0xF91C,0xF91D,0xF91E,0xF91F, + 0xF920,0xF921,0xF922,0xF923,0xF924,0xF925,0xF926,0xF927,0xF928,0xF929,0xF92A,0xF92B,0xF92C,0xF92D,0xF92E,0xF92F, + 0xF930,0xF931,0xF932,0xF933,0xF934,0xF935,0xF936,0xF937,0xF938,0xF939,0xF93A,0xF93B,0xF93C,0xF93D,0xF93E,0xF93F, + 0xF940,0xF941,0xF942,0xF943,0xF944,0xF945,0xF946,0xF947,0xF948,0xF949,0xF94A,0xF94B,0xF94C,0xF94D,0xF94E,0xF94F, + 0xF950,0xF951,0xF952,0xF953,0xF954,0xF955,0xF956,0xF957,0xF958,0xF959,0xF95A,0xF95B,0xF95C,0xF95D,0xF95E,0xF95F, + 0xF960,0xF961,0xF962,0xF963,0xF964,0xF965,0xF966,0xF967,0xF968,0xF969,0xF96A,0xF96B,0xF96C,0xF96D,0xF96E,0xF96F, + 0xF970,0xF971,0xF972,0xF973,0xF974,0xF975,0xF976,0xF977,0xF978,0xF979,0xF97A,0xF97B,0xF97C,0xF97D,0xF97E,0xF97F, + 0xF980,0xF981,0xF982,0xF983,0xF984,0xF985,0xF986,0xF987,0xF988,0xF989,0xF98A,0xF98B,0xF98C,0xF98D,0xF98E,0xF98F, + 0xF990,0xF991,0xF992,0xF993,0xF994,0xF995,0xF996,0xF997,0xF998,0xF999,0xF99A,0xF99B,0xF99C,0xF99D,0xF99E,0xF99F, + 0xF9A0,0xF9A1,0xF9A2,0xF9A3,0xF9A4,0xF9A5,0xF9A6,0xF9A7,0xF9A8,0xF9A9,0xF9AA,0xF9AB,0xF9AC,0xF9AD,0xF9AE,0xF9AF, + 0xF9B0,0xF9B1,0xF9B2,0xF9B3,0xF9B4,0xF9B5,0xF9B6,0xF9B7,0xF9B8,0xF9B9,0xF9BA,0xF9BB,0xF9BC,0xF9BD,0xF9BE,0xF9BF, + 0xF9C0,0xF9C1,0xF9C2,0xF9C3,0xF9C4,0xF9C5,0xF9C6,0xF9C7,0xF9C8,0xF9C9,0xF9CA,0xF9CB,0xF9CC,0xF9CD,0xF9CE,0xF9CF, + 0xF9D0,0xF9D1,0xF9D2,0xF9D3,0xF9D4,0xF9D5,0xF9D6,0xF9D7,0xF9D8,0xF9D9,0xF9DA,0xF9DB,0xF9DC,0xF9DD,0xF9DE,0xF9DF, + 0xF9E0,0xF9E1,0xF9E2,0xF9E3,0xF9E4,0xF9E5,0xF9E6,0xF9E7,0xF9E8,0xF9E9,0xF9EA,0xF9EB,0xF9EC,0xF9ED,0xF9EE,0xF9EF, + 0xF9F0,0xF9F1,0xF9F2,0xF9F3,0xF9F4,0xF9F5,0xF9F6,0xF9F7,0xF9F8,0xF9F9,0xF9FA,0xF9FB,0xF9FC,0xF9FD,0xF9FE,0xF9FF, + 0xFA00,0xFA01,0xFA02,0xFA03,0xFA04,0xFA05,0xFA06,0xFA07,0xFA08,0xFA09,0xFA0A,0xFA0B,0xFA0C,0xFA0D,0xFA0E,0xFA0F, + 0xFA10,0xFA11,0xFA12,0xFA13,0xFA14,0xFA15,0xFA16,0xFA17,0xFA18,0xFA19,0xFA1A,0xFA1B,0xFA1C,0xFA1D,0xFA1E,0xFA1F, + 0xFA20,0xFA21,0xFA22,0xFA23,0xFA24,0xFA25,0xFA26,0xFA27,0xFA28,0xFA29,0xFA2A,0xFA2B,0xFA2C,0xFA2D,0xFA2E,0xFA2F, + 0xFA30,0xFA31,0xFA32,0xFA33,0xFA34,0xFA35,0xFA36,0xFA37,0xFA38,0xFA39,0xFA3A,0xFA3B,0xFA3C,0xFA3D,0xFA3E,0xFA3F, + 0xFA40,0xFA41,0xFA42,0xFA43,0xFA44,0xFA45,0xFA46,0xFA47,0xFA48,0xFA49,0xFA4A,0xFA4B,0xFA4C,0xFA4D,0xFA4E,0xFA4F, + 0xFA50,0xFA51,0xFA52,0xFA53,0xFA54,0xFA55,0xFA56,0xFA57,0xFA58,0xFA59,0xFA5A,0xFA5B,0xFA5C,0xFA5D,0xFA5E,0xFA5F, + 0xFA60,0xFA61,0xFA62,0xFA63,0xFA64,0xFA65,0xFA66,0xFA67,0xFA68,0xFA69,0xFA6A,0xFA6B,0xFA6C,0xFA6D,0xFA6E,0xFA6F, + 0xFA70,0xFA71,0xFA72,0xFA73,0xFA74,0xFA75,0xFA76,0xFA77,0xFA78,0xFA79,0xFA7A,0xFA7B,0xFA7C,0xFA7D,0xFA7E,0xFA7F, + 0xFA80,0xFA81,0xFA82,0xFA83,0xFA84,0xFA85,0xFA86,0xFA87,0xFA88,0xFA89,0xFA8A,0xFA8B,0xFA8C,0xFA8D,0xFA8E,0xFA8F, + 0xFA90,0xFA91,0xFA92,0xFA93,0xFA94,0xFA95,0xFA96,0xFA97,0xFA98,0xFA99,0xFA9A,0xFA9B,0xFA9C,0xFA9D,0xFA9E,0xFA9F, + 0xFAA0,0xFAA1,0xFAA2,0xFAA3,0xFAA4,0xFAA5,0xFAA6,0xFAA7,0xFAA8,0xFAA9,0xFAAA,0xFAAB,0xFAAC,0xFAAD,0xFAAE,0xFAAF, + 0xFAB0,0xFAB1,0xFAB2,0xFAB3,0xFAB4,0xFAB5,0xFAB6,0xFAB7,0xFAB8,0xFAB9,0xFABA,0xFABB,0xFABC,0xFABD,0xFABE,0xFABF, + 0xFAC0,0xFAC1,0xFAC2,0xFAC3,0xFAC4,0xFAC5,0xFAC6,0xFAC7,0xFAC8,0xFAC9,0xFACA,0xFACB,0xFACC,0xFACD,0xFACE,0xFACF, + 0xFAD0,0xFAD1,0xFAD2,0xFAD3,0xFAD4,0xFAD5,0xFAD6,0xFAD7,0xFAD8,0xFAD9,0xFADA,0xFADB,0xFADC,0xFADD,0xFADE,0xFADF, + 0xFAE0,0xFAE1,0xFAE2,0xFAE3,0xFAE4,0xFAE5,0xFAE6,0xFAE7,0xFAE8,0xFAE9,0xFAEA,0xFAEB,0xFAEC,0xFAED,0xFAEE,0xFAEF, + 0xFAF0,0xFAF1,0xFAF2,0xFAF3,0xFAF4,0xFAF5,0xFAF6,0xFAF7,0xFAF8,0xFAF9,0xFAFA,0xFAFB,0xFAFC,0xFAFD,0xFAFE,0xFAFF, + 0xFB00,0xFB01,0xFB02,0xFB03,0xFB04,0xFB05,0xFB06,0xFB07,0xFB08,0xFB09,0xFB0A,0xFB0B,0xFB0C,0xFB0D,0xFB0E,0xFB0F, + 0xFB10,0xFB11,0xFB12,0xFB13,0xFB14,0xFB15,0xFB16,0xFB17,0xFB18,0xFB19,0xFB1A,0xFB1B,0xFB1C,0xFB1D,0xFB1E,0xFB1F, + 0xFB20,0xFB21,0xFB22,0xFB23,0xFB24,0xFB25,0xFB26,0xFB27,0xFB28,0xFB29,0xFB2A,0xFB2B,0xFB2C,0xFB2D,0xFB2E,0xFB2F, + 0xFB30,0xFB31,0xFB32,0xFB33,0xFB34,0xFB35,0xFB36,0xFB37,0xFB38,0xFB39,0xFB3A,0xFB3B,0xFB3C,0xFB3D,0xFB3E,0xFB3F, + 0xFB40,0xFB41,0xFB42,0xFB43,0xFB44,0xFB45,0xFB46,0xFB47,0xFB48,0xFB49,0xFB4A,0xFB4B,0xFB4C,0xFB4D,0xFB4E,0xFB4F, + 0xFB50,0xFB51,0xFB52,0xFB53,0xFB54,0xFB55,0xFB56,0xFB57,0xFB58,0xFB59,0xFB5A,0xFB5B,0xFB5C,0xFB5D,0xFB5E,0xFB5F, + 0xFB60,0xFB61,0xFB62,0xFB63,0xFB64,0xFB65,0xFB66,0xFB67,0xFB68,0xFB69,0xFB6A,0xFB6B,0xFB6C,0xFB6D,0xFB6E,0xFB6F, + 0xFB70,0xFB71,0xFB72,0xFB73,0xFB74,0xFB75,0xFB76,0xFB77,0xFB78,0xFB79,0xFB7A,0xFB7B,0xFB7C,0xFB7D,0xFB7E,0xFB7F, + 0xFB80,0xFB81,0xFB82,0xFB83,0xFB84,0xFB85,0xFB86,0xFB87,0xFB88,0xFB89,0xFB8A,0xFB8B,0xFB8C,0xFB8D,0xFB8E,0xFB8F, + 0xFB90,0xFB91,0xFB92,0xFB93,0xFB94,0xFB95,0xFB96,0xFB97,0xFB98,0xFB99,0xFB9A,0xFB9B,0xFB9C,0xFB9D,0xFB9E,0xFB9F, + 0xFBA0,0xFBA1,0xFBA2,0xFBA3,0xFBA4,0xFBA5,0xFBA6,0xFBA7,0xFBA8,0xFBA9,0xFBAA,0xFBAB,0xFBAC,0xFBAD,0xFBAE,0xFBAF, + 0xFBB0,0xFBB1,0xFBB2,0xFBB3,0xFBB4,0xFBB5,0xFBB6,0xFBB7,0xFBB8,0xFBB9,0xFBBA,0xFBBB,0xFBBC,0xFBBD,0xFBBE,0xFBBF, + 0xFBC0,0xFBC1,0xFBC2,0xFBC3,0xFBC4,0xFBC5,0xFBC6,0xFBC7,0xFBC8,0xFBC9,0xFBCA,0xFBCB,0xFBCC,0xFBCD,0xFBCE,0xFBCF, + 0xFBD0,0xFBD1,0xFBD2,0xFBD3,0xFBD4,0xFBD5,0xFBD6,0xFBD7,0xFBD8,0xFBD9,0xFBDA,0xFBDB,0xFBDC,0xFBDD,0xFBDE,0xFBDF, + 0xFBE0,0xFBE1,0xFBE2,0xFBE3,0xFBE4,0xFBE5,0xFBE6,0xFBE7,0xFBE8,0xFBE9,0xFBEA,0xFBEB,0xFBEC,0xFBED,0xFBEE,0xFBEF, + 0xFBF0,0xFBF1,0xFBF2,0xFBF3,0xFBF4,0xFBF5,0xFBF6,0xFBF7,0xFBF8,0xFBF9,0xFBFA,0xFBFB,0xFBFC,0xFBFD,0xFBFE,0xFBFF, + 0xFC00,0xFC01,0xFC02,0xFC03,0xFC04,0xFC05,0xFC06,0xFC07,0xFC08,0xFC09,0xFC0A,0xFC0B,0xFC0C,0xFC0D,0xFC0E,0xFC0F, + 0xFC10,0xFC11,0xFC12,0xFC13,0xFC14,0xFC15,0xFC16,0xFC17,0xFC18,0xFC19,0xFC1A,0xFC1B,0xFC1C,0xFC1D,0xFC1E,0xFC1F, + 0xFC20,0xFC21,0xFC22,0xFC23,0xFC24,0xFC25,0xFC26,0xFC27,0xFC28,0xFC29,0xFC2A,0xFC2B,0xFC2C,0xFC2D,0xFC2E,0xFC2F, + 0xFC30,0xFC31,0xFC32,0xFC33,0xFC34,0xFC35,0xFC36,0xFC37,0xFC38,0xFC39,0xFC3A,0xFC3B,0xFC3C,0xFC3D,0xFC3E,0xFC3F, + 0xFC40,0xFC41,0xFC42,0xFC43,0xFC44,0xFC45,0xFC46,0xFC47,0xFC48,0xFC49,0xFC4A,0xFC4B,0xFC4C,0xFC4D,0xFC4E,0xFC4F, + 0xFC50,0xFC51,0xFC52,0xFC53,0xFC54,0xFC55,0xFC56,0xFC57,0xFC58,0xFC59,0xFC5A,0xFC5B,0xFC5C,0xFC5D,0xFC5E,0xFC5F, + 0xFC60,0xFC61,0xFC62,0xFC63,0xFC64,0xFC65,0xFC66,0xFC67,0xFC68,0xFC69,0xFC6A,0xFC6B,0xFC6C,0xFC6D,0xFC6E,0xFC6F, + 0xFC70,0xFC71,0xFC72,0xFC73,0xFC74,0xFC75,0xFC76,0xFC77,0xFC78,0xFC79,0xFC7A,0xFC7B,0xFC7C,0xFC7D,0xFC7E,0xFC7F, + 0xFC80,0xFC81,0xFC82,0xFC83,0xFC84,0xFC85,0xFC86,0xFC87,0xFC88,0xFC89,0xFC8A,0xFC8B,0xFC8C,0xFC8D,0xFC8E,0xFC8F, + 0xFC90,0xFC91,0xFC92,0xFC93,0xFC94,0xFC95,0xFC96,0xFC97,0xFC98,0xFC99,0xFC9A,0xFC9B,0xFC9C,0xFC9D,0xFC9E,0xFC9F, + 0xFCA0,0xFCA1,0xFCA2,0xFCA3,0xFCA4,0xFCA5,0xFCA6,0xFCA7,0xFCA8,0xFCA9,0xFCAA,0xFCAB,0xFCAC,0xFCAD,0xFCAE,0xFCAF, + 0xFCB0,0xFCB1,0xFCB2,0xFCB3,0xFCB4,0xFCB5,0xFCB6,0xFCB7,0xFCB8,0xFCB9,0xFCBA,0xFCBB,0xFCBC,0xFCBD,0xFCBE,0xFCBF, + 0xFCC0,0xFCC1,0xFCC2,0xFCC3,0xFCC4,0xFCC5,0xFCC6,0xFCC7,0xFCC8,0xFCC9,0xFCCA,0xFCCB,0xFCCC,0xFCCD,0xFCCE,0xFCCF, + 0xFCD0,0xFCD1,0xFCD2,0xFCD3,0xFCD4,0xFCD5,0xFCD6,0xFCD7,0xFCD8,0xFCD9,0xFCDA,0xFCDB,0xFCDC,0xFCDD,0xFCDE,0xFCDF, + 0xFCE0,0xFCE1,0xFCE2,0xFCE3,0xFCE4,0xFCE5,0xFCE6,0xFCE7,0xFCE8,0xFCE9,0xFCEA,0xFCEB,0xFCEC,0xFCED,0xFCEE,0xFCEF, + 0xFCF0,0xFCF1,0xFCF2,0xFCF3,0xFCF4,0xFCF5,0xFCF6,0xFCF7,0xFCF8,0xFCF9,0xFCFA,0xFCFB,0xFCFC,0xFCFD,0xFCFE,0xFCFF, + 0xFD00,0xFD01,0xFD02,0xFD03,0xFD04,0xFD05,0xFD06,0xFD07,0xFD08,0xFD09,0xFD0A,0xFD0B,0xFD0C,0xFD0D,0xFD0E,0xFD0F, + 0xFD10,0xFD11,0xFD12,0xFD13,0xFD14,0xFD15,0xFD16,0xFD17,0xFD18,0xFD19,0xFD1A,0xFD1B,0xFD1C,0xFD1D,0xFD1E,0xFD1F, + 0xFD20,0xFD21,0xFD22,0xFD23,0xFD24,0xFD25,0xFD26,0xFD27,0xFD28,0xFD29,0xFD2A,0xFD2B,0xFD2C,0xFD2D,0xFD2E,0xFD2F, + 0xFD30,0xFD31,0xFD32,0xFD33,0xFD34,0xFD35,0xFD36,0xFD37,0xFD38,0xFD39,0xFD3A,0xFD3B,0xFD3C,0xFD3D,0xFD3E,0xFD3F, + 0xFD40,0xFD41,0xFD42,0xFD43,0xFD44,0xFD45,0xFD46,0xFD47,0xFD48,0xFD49,0xFD4A,0xFD4B,0xFD4C,0xFD4D,0xFD4E,0xFD4F, + 0xFD50,0xFD51,0xFD52,0xFD53,0xFD54,0xFD55,0xFD56,0xFD57,0xFD58,0xFD59,0xFD5A,0xFD5B,0xFD5C,0xFD5D,0xFD5E,0xFD5F, + 0xFD60,0xFD61,0xFD62,0xFD63,0xFD64,0xFD65,0xFD66,0xFD67,0xFD68,0xFD69,0xFD6A,0xFD6B,0xFD6C,0xFD6D,0xFD6E,0xFD6F, + 0xFD70,0xFD71,0xFD72,0xFD73,0xFD74,0xFD75,0xFD76,0xFD77,0xFD78,0xFD79,0xFD7A,0xFD7B,0xFD7C,0xFD7D,0xFD7E,0xFD7F, + 0xFD80,0xFD81,0xFD82,0xFD83,0xFD84,0xFD85,0xFD86,0xFD87,0xFD88,0xFD89,0xFD8A,0xFD8B,0xFD8C,0xFD8D,0xFD8E,0xFD8F, + 0xFD90,0xFD91,0xFD92,0xFD93,0xFD94,0xFD95,0xFD96,0xFD97,0xFD98,0xFD99,0xFD9A,0xFD9B,0xFD9C,0xFD9D,0xFD9E,0xFD9F, + 0xFDA0,0xFDA1,0xFDA2,0xFDA3,0xFDA4,0xFDA5,0xFDA6,0xFDA7,0xFDA8,0xFDA9,0xFDAA,0xFDAB,0xFDAC,0xFDAD,0xFDAE,0xFDAF, + 0xFDB0,0xFDB1,0xFDB2,0xFDB3,0xFDB4,0xFDB5,0xFDB6,0xFDB7,0xFDB8,0xFDB9,0xFDBA,0xFDBB,0xFDBC,0xFDBD,0xFDBE,0xFDBF, + 0xFDC0,0xFDC1,0xFDC2,0xFDC3,0xFDC4,0xFDC5,0xFDC6,0xFDC7,0xFDC8,0xFDC9,0xFDCA,0xFDCB,0xFDCC,0xFDCD,0xFDCE,0xFDCF, + 0xFDD0,0xFDD1,0xFDD2,0xFDD3,0xFDD4,0xFDD5,0xFDD6,0xFDD7,0xFDD8,0xFDD9,0xFDDA,0xFDDB,0xFDDC,0xFDDD,0xFDDE,0xFDDF, + 0xFDE0,0xFDE1,0xFDE2,0xFDE3,0xFDE4,0xFDE5,0xFDE6,0xFDE7,0xFDE8,0xFDE9,0xFDEA,0xFDEB,0xFDEC,0xFDED,0xFDEE,0xFDEF, + 0xFDF0,0xFDF1,0xFDF2,0xFDF3,0xFDF4,0xFDF5,0xFDF6,0xFDF7,0xFDF8,0xFDF9,0xFDFA,0xFDFB,0xFDFC,0xFDFD,0xFDFE,0xFDFF, + 0xFE00,0xFE01,0xFE02,0xFE03,0xFE04,0xFE05,0xFE06,0xFE07,0xFE08,0xFE09,0xFE0A,0xFE0B,0xFE0C,0xFE0D,0xFE0E,0xFE0F, + 0xFE10,0xFE11,0xFE12,0xFE13,0xFE14,0xFE15,0xFE16,0xFE17,0xFE18,0xFE19,0xFE1A,0xFE1B,0xFE1C,0xFE1D,0xFE1E,0xFE1F, + 0xFE20,0xFE21,0xFE22,0xFE23,0xFE24,0xFE25,0xFE26,0xFE27,0xFE28,0xFE29,0xFE2A,0xFE2B,0xFE2C,0xFE2D,0xFE2E,0xFE2F, + 0xFE30,0xFE31,0xFE32,0xFE33,0xFE34,0xFE35,0xFE36,0xFE37,0xFE38,0xFE39,0xFE3A,0xFE3B,0xFE3C,0xFE3D,0xFE3E,0xFE3F, + 0xFE40,0xFE41,0xFE42,0xFE43,0xFE44,0xFE45,0xFE46,0xFE47,0xFE48,0xFE49,0xFE4A,0xFE4B,0xFE4C,0xFE4D,0xFE4E,0xFE4F, + 0xFE50,0xFE51,0xFE52,0xFE53,0xFE54,0xFE55,0xFE56,0xFE57,0xFE58,0xFE59,0xFE5A,0xFE5B,0xFE5C,0xFE5D,0xFE5E,0xFE5F, + 0xFE60,0xFE61,0xFE62,0xFE63,0xFE64,0xFE65,0xFE66,0xFE67,0xFE68,0xFE69,0xFE6A,0xFE6B,0xFE6C,0xFE6D,0xFE6E,0xFE6F, + 0xFE70,0xFE71,0xFE72,0xFE73,0xFE74,0xFE75,0xFE76,0xFE77,0xFE78,0xFE79,0xFE7A,0xFE7B,0xFE7C,0xFE7D,0xFE7E,0xFE7F, + 0xFE80,0xFE81,0xFE82,0xFE83,0xFE84,0xFE85,0xFE86,0xFE87,0xFE88,0xFE89,0xFE8A,0xFE8B,0xFE8C,0xFE8D,0xFE8E,0xFE8F, + 0xFE90,0xFE91,0xFE92,0xFE93,0xFE94,0xFE95,0xFE96,0xFE97,0xFE98,0xFE99,0xFE9A,0xFE9B,0xFE9C,0xFE9D,0xFE9E,0xFE9F, + 0xFEA0,0xFEA1,0xFEA2,0xFEA3,0xFEA4,0xFEA5,0xFEA6,0xFEA7,0xFEA8,0xFEA9,0xFEAA,0xFEAB,0xFEAC,0xFEAD,0xFEAE,0xFEAF, + 0xFEB0,0xFEB1,0xFEB2,0xFEB3,0xFEB4,0xFEB5,0xFEB6,0xFEB7,0xFEB8,0xFEB9,0xFEBA,0xFEBB,0xFEBC,0xFEBD,0xFEBE,0xFEBF, + 0xFEC0,0xFEC1,0xFEC2,0xFEC3,0xFEC4,0xFEC5,0xFEC6,0xFEC7,0xFEC8,0xFEC9,0xFECA,0xFECB,0xFECC,0xFECD,0xFECE,0xFECF, + 0xFED0,0xFED1,0xFED2,0xFED3,0xFED4,0xFED5,0xFED6,0xFED7,0xFED8,0xFED9,0xFEDA,0xFEDB,0xFEDC,0xFEDD,0xFEDE,0xFEDF, + 0xFEE0,0xFEE1,0xFEE2,0xFEE3,0xFEE4,0xFEE5,0xFEE6,0xFEE7,0xFEE8,0xFEE9,0xFEEA,0xFEEB,0xFEEC,0xFEED,0xFEEE,0xFEEF, + 0xFEF0,0xFEF1,0xFEF2,0xFEF3,0xFEF4,0xFEF5,0xFEF6,0xFEF7,0xFEF8,0xFEF9,0xFEFA,0xFEFB,0xFEFC,0xFEFD,0xFEFE,0xFEFF, + 0xFF00,0xFF01,0xFF02,0xFF03,0xFF04,0xFF05,0xFF06,0xFF07,0xFF08,0xFF09,0xFF0A,0xFF0B,0xFF0C,0xFF0D,0xFF0E,0xFF0F, + 0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,0xFF19,0xFF1A,0xFF1B,0xFF1C,0xFF1D,0xFF1E,0xFF1F, + 0xFF20,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F, + 0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F, + 0xFF40,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F, + 0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFF5E,0xFF5F, + 0xFF60,0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,0xFF68,0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F, + 0xFF70,0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,0xFF78,0xFF79,0xFF7A,0xFF7B,0xFF7C,0xFF7D,0xFF7E,0xFF7F, + 0xFF80,0xFF81,0xFF82,0xFF83,0xFF84,0xFF85,0xFF86,0xFF87,0xFF88,0xFF89,0xFF8A,0xFF8B,0xFF8C,0xFF8D,0xFF8E,0xFF8F, + 0xFF90,0xFF91,0xFF92,0xFF93,0xFF94,0xFF95,0xFF96,0xFF97,0xFF98,0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F, + 0xFFA0,0xFFA1,0xFFA2,0xFFA3,0xFFA4,0xFFA5,0xFFA6,0xFFA7,0xFFA8,0xFFA9,0xFFAA,0xFFAB,0xFFAC,0xFFAD,0xFFAE,0xFFAF, + 0xFFB0,0xFFB1,0xFFB2,0xFFB3,0xFFB4,0xFFB5,0xFFB6,0xFFB7,0xFFB8,0xFFB9,0xFFBA,0xFFBB,0xFFBC,0xFFBD,0xFFBE,0xFFBF, + 0xFFC0,0xFFC1,0xFFC2,0xFFC3,0xFFC4,0xFFC5,0xFFC6,0xFFC7,0xFFC8,0xFFC9,0xFFCA,0xFFCB,0xFFCC,0xFFCD,0xFFCE,0xFFCF, + 0xFFD0,0xFFD1,0xFFD2,0xFFD3,0xFFD4,0xFFD5,0xFFD6,0xFFD7,0xFFD8,0xFFD9,0xFFDA,0xFFDB,0xFFDC,0xFFDD,0xFFDE,0xFFDF, + 0xFFE0,0xFFE1,0xFFE2,0xFFE3,0xFFE4,0xFFE5,0xFFE6,0xFFE7,0xFFE8,0xFFE9,0xFFEA,0xFFEB,0xFFEC,0xFFED,0xFFEE,0xFFEF, + 0xFFF0,0xFFF1,0xFFF2,0xFFF3,0xFFF4,0xFFF5,0xFFF6,0xFFF7,0xFFF8,0xFFF9,0xFFFA,0xFFFB,0xFFFC,0xFFFD,0xFFFE,0xFFFF, +}; +#endif + +#endif /* _HCA_KEYS_AWB_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/imc.c b/Frameworks/vgmstream/vgmstream/src/meta/imc.c new file mode 100644 index 000000000..5cdfe41c1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/imc.c @@ -0,0 +1,121 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* .IMC - from iNiS Gitaroo Man (PS2) */ +VGMSTREAM * init_vgmstream_imc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, sample_rate, interleave, blocks; + size_t file_size, data_size; + + + /* checks */ + /* .imc: extension from the main container */ + if (!check_extensions(streamFile, "imc")) + goto fail; + + channel_count = read_32bitLE(0x00, streamFile); + sample_rate = read_32bitLE(0x04, streamFile); + interleave = read_32bitLE(0x08, streamFile) * 0x10; /* number of frames in a block */ + blocks = read_32bitLE(0x0c, streamFile); /* number of interleave blocks (even in mono) */ + + file_size = get_streamfile_size(streamFile); + loop_flag = 0; + start_offset = 0x10; + + /* extra checks since the header is so simple */ + if (channel_count < 1 || channel_count > 8 || sample_rate < 22000 || sample_rate > 48000) + goto fail; + if (interleave*blocks + start_offset != file_size) + goto fail; + + /* remove padding (important to play gapless subsongs, happens even for mono) */ + { + off_t min_offset = file_size - interleave; + off_t offset = file_size - 0x10; + + data_size = file_size - start_offset; + while (offset > min_offset) { + if (read_32bitLE(offset, streamFile) != 0) + break; + data_size -= 0x10*channel_count; + offset -= 0x10; + } + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_IMC; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* ****************************************************************************** */ + +/* .IMC in containers */ +VGMSTREAM * init_vgmstream_imc_container(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t header_offset, subfile_offset, next_offset, name_offset; + size_t subfile_size; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* checks */ + if (!check_extensions(streamFile, "imc")) + goto fail; + + total_subsongs = read_32bitLE(0x00, streamFile); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + + header_offset = 0x04 + 0x20*(target_subsong-1); + + name_offset = header_offset + 0x00; + /* 0x08: flags? (0x702ADE77|0x002ADE77|0x20000000|etc) */ + /* 0x0c: same for all songs in single .imc but varies between .imc */ + subfile_offset = read_32bitLE(header_offset + 0x10,streamFile); + /* 0x14: flags/size? (0xF0950000|0x3CFA1200|etc) */ + /* 0x18: same for all songs in single .imc but varies between .imc */ + /* 0x1c: flags? (0 or 2) */ + + if (target_subsong == total_subsongs) { + next_offset = get_streamfile_size(streamFile); + } + else { + next_offset = read_32bitLE(header_offset + 0x20 + 0x10,streamFile); + } + subfile_size = next_offset - subfile_offset; + + + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); + if (!temp_streamFile) goto fail; + + vgmstream = init_vgmstream_imc(temp_streamFile); + if (!vgmstream) goto fail; + + close_streamfile(temp_streamFile); + vgmstream->num_streams = total_subsongs; + read_string(vgmstream->stream_name,0x08+1, name_offset,streamFile); + + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index f8b084461..3b4fdbe0d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -46,8 +46,9 @@ VGMSTREAM * init_vgmstream_dsp_dspw(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_dsp_mcadpcm(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dsp_switch_audio(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_dsp_vag(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_dsp_sps_n1(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dsp_itl_ch(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_dsp_adpcmx(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile); @@ -64,7 +65,7 @@ VGMSTREAM * init_vgmstream_rsf(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile); @@ -173,6 +174,7 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nwa(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_eacs(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_xss(STREAMFILE * streamFile); @@ -289,7 +291,7 @@ VGMSTREAM * init_vgmstream_sadl(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_ccc(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_fag(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile); @@ -360,8 +362,7 @@ VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_mul(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile); @@ -400,7 +401,7 @@ VGMSTREAM * init_vgmstream_zsd(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_RedSpark(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_redspark(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile); @@ -533,7 +534,7 @@ VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_iab(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_vs_str(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE* streamFile); @@ -629,6 +630,8 @@ VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_vita(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile); + VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ngc_ulw(STREAMFILE * streamFile); @@ -643,7 +646,8 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_idx_big(STREAMFILE * steeamFile); +VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE * steeamFile); +VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE * steeamFile); VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile); @@ -659,8 +663,9 @@ VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_opus_nop(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_opus_shinen(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_opus_nus3(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_opus_nlsd(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_opus_nxa(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE * streamFile); @@ -669,6 +674,7 @@ VGMSTREAM * init_vgmstream_pc_ast(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_naac(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ubi_sm(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ezw(STREAMFILE * streamFile); @@ -679,6 +685,7 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_abk_new(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_hdr_sth_dat(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE * streamFile); @@ -733,7 +740,7 @@ VGMSTREAM * init_vgmstream_ea_sps_fb(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ppst(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_opus_ppp(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_opus_sps_n1_segmented(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ubi_bao_pk(STREAMFILE *streamFile); @@ -793,4 +800,31 @@ VGMSTREAM * init_vgmstream_adpcm_capcom(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_xwma(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xopus(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_vs_square(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_msf_banpresto_wmsf(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_msf_banpresto_2msf(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_nwav(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xpcm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_msf_tamasoft(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xps_dat(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_xps(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_zsnd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_nus3audio(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_imc(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_imc_container(STREAMFILE * streamFile); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c b/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c new file mode 100644 index 000000000..ca63a961b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c @@ -0,0 +1,62 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* WMSF - Banpresto MSFx wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS3)] */ +VGMSTREAM * init_vgmstream_msf_banpresto_wmsf(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t subfile_offset = 0x10; + size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; + + + /* checks */ + if ( !check_extensions(streamFile,"msf")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x574D5346) /* "WMSF" */ + goto fail; + /* 0x04: size, 0x08: flags? 0x0c: null? */ + + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); + if (!temp_streamFile) goto fail; + + vgmstream = init_vgmstream_ps3_msf(temp_streamFile); + if (!vgmstream) goto fail; + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} + +/* 2MSF - Banpresto RIFF wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS4)] */ +VGMSTREAM * init_vgmstream_msf_banpresto_2msf(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t subfile_offset = 0x14; + size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; + + + /* checks */ + if ( !check_extensions(streamFile,"at9")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x324D5346) /* "2MSF" */ + goto fail; + /* 0x04: size, 0x08: flags? 0x0c: null?, 0x10: 0x01? (BE values even though RIFF is LE) */ + + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); + if (!temp_streamFile) goto fail; + + vgmstream = init_vgmstream_riff(temp_streamFile); + if (!vgmstream) goto fail; + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msf_tamasoft.c b/Frameworks/vgmstream/vgmstream/src/meta/msf_tamasoft.c new file mode 100644 index 000000000..9dbb7ffda --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/msf_tamasoft.c @@ -0,0 +1,74 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* MSF - TamaSoft games [Abandoner: The Severed Dreams (PC)] */ +VGMSTREAM * init_vgmstream_msf_tamasoft(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, sample_rate, codec, loop_start = 0, loop_end = 0; + size_t data_size; + uint16_t xor16; + uint32_t xor32; + + + /* checks */ + /* .msf: extension referenced in .EXE (bigfiles don't have filenames) */ + if (!check_extensions(streamFile, "msf")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x4D534620) /* "MSF " */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x00) /* just in case since there are other .msf */ + goto fail; + + /* header from 0x10 to 0x30 is encrypted (though value at 0x10 doubles as key...) */ + xor16 = (uint16_t)(((uint32_t)read_32bitLE(0x04,streamFile) * 0x65u) + 0x30Au); /* from the exe */ + xor32 = (uint32_t)(((uint32_t)xor16 << 16u) | (uint32_t)xor16); + + /* 0x10: null */ + loop_flag = (uint32_t)read_32bitLE(0x14,streamFile) ^ xor32; + data_size = (uint32_t)read_32bitLE(0x18,streamFile) ^ xor32; + codec = (uint16_t)read_16bitLE(0x1c,streamFile) ^ xor16; + channel_count = (uint16_t)read_16bitLE(0x1e,streamFile) ^ xor16; + sample_rate = (uint32_t)read_32bitLE(0x20,streamFile) ^ xor32; + /* 0x24: average bitrate? */ + /* 0x28: block size */ + /* 0x2a: bps */ + /* 0x2c: unknown (fixed) */ + + if (loop_flag) { + loop_start = read_32bitLE(0x30,streamFile); + loop_end = read_32bitLE(0x34,streamFile); + /* 0x38/3c: null */ + start_offset = 0x40; + } + else { + start_offset = 0x30; + } + + if (codec != 0x01) + goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MSF_TAMASOFT; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 16); + vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16); + vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count, 16); + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mul.c b/Frameworks/vgmstream/vgmstream/src/meta/mul.c new file mode 100644 index 000000000..cf262160a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/mul.c @@ -0,0 +1,164 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + +typedef enum { NONE, PSX, DSP, XBOX } mul_codec; + +/* .MUL - from Crystal Dynamics games [Legacy of Kain: Defiance (PS2), Tomb Raider Underworld (multi)] */ +VGMSTREAM * init_vgmstream_mul(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, coefs_offset = 0; + int loop_flag, channel_count, sample_rate, num_samples, loop_start; + int big_endian; + mul_codec codec = NONE; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + /* .mul: found in the exe, used by the bigfile extractor (Gibbed.TombRaider) + * (some files have companion .mus/sam files but seem to be sequences/control stuff) + * .(extensionless): filenames as found in the bigfile + * .emff: fake extension ('Eidos Music File Format') */ + if (!check_extensions(streamFile, "mul,,emff")) + goto fail; + if (read_32bitBE(0x10,streamFile) != 0 || + read_32bitBE(0x14,streamFile) != 0 || + read_32bitBE(0x18,streamFile) != 0 || + read_32bitBE(0x1c,streamFile) != 0) + goto fail; + + big_endian = guess_endianness32bit(0x00, streamFile); + read_32bit = big_endian ? read_32bitBE : read_32bitLE; + + sample_rate = read_32bit(0x00,streamFile); + loop_start = read_32bit(0x04,streamFile); + num_samples = read_32bit(0x08,streamFile); + channel_count = read_32bit(0x0C,streamFile); + if (sample_rate < 8000 || sample_rate > 48000 || channel_count > 8) + goto fail; + /* 0x20: flag when file has non-audio blocks (ignored by the layout) */ + /* 0x24: same? */ + /* 0x28: loop offset within audio data (not file offset) */ + /* 0x2c: some value related to loop? */ + /* 0x34: id? */ + /* 0x38+: channel config until ~0x100? (multiple 0x3F800000 depending on the number of channels) */ + + /* test known versions (later versions start from 0x24 instead of 0x20) */ + if (!(read_32bit(0x38,streamFile) == 0x3F800000 || + read_32bit(0x3c,streamFile) == 0x3F800000)) /* Tomb Raider Underworld */ + goto fail; + + loop_flag = (loop_start >= 0); /* 0xFFFFFFFF when not looping */ + start_offset = 0x800; + + /* format is pretty limited so we need to guess codec */ + if (big_endian) { + /* test DSP (GC/Wii): check known coef locations */ + if (read_32bitBE(0xC8,streamFile) != 0) { /* Tomb Raider Legend (GC) */ + codec = DSP; + coefs_offset = 0xC8; + } + else if (read_32bitBE(0xCC,streamFile) != 0) { /* Tomb Raider Anniversary (Wii) */ + codec = DSP; + coefs_offset = 0xCC; + } + else if (read_32bitBE(0x2D0,streamFile) != 0) { /* Tomb Raider Underworld (Wii) */ + codec = DSP; + coefs_offset = 0x2D0; + } + + // todo test XMA1 (X360): mono streams, each block has 1 sub-blocks of 0x800 packet per channel + + // todo test ? (PS3) + } + else { + int i; + off_t offset = start_offset; + size_t file_size = get_streamfile_size(streamFile); + size_t frame_size; + + /* check first audio frame */ + while (offset < file_size) { + uint32_t block_type = read_32bit(offset+0x00, streamFile); + uint32_t block_size = read_32bit(offset+0x04, streamFile); + uint32_t data_size = read_32bit(offset+0x10, streamFile); + + if (block_type != 0x00) { + offset += 0x10 + block_size; + continue; /* not audio */ + } + + /* test PS-ADPCM (PS2/PSP): flag is always 2 in .mul */ + frame_size = 0x10; + for (i = 0; i < data_size / frame_size; i++) { + if (read_8bit(offset + 0x20 + frame_size*i + 0x01, streamFile) != 0x02) + break; + } + if (i == data_size / frame_size) { + codec = PSX; + break; + } + + /* test XBOX-IMA (PC/Xbox): reserved frame header value is always 0 */ + frame_size = 0x24; + for (i = 0; i < data_size / frame_size; i++) { + if (read_8bit(offset + 0x20 + frame_size*i + 0x03, streamFile) != 0x00) + break; + } + if (i == data_size / frame_size) { + codec = XBOX; + break; + } + + break; + } + } + + if (codec == NONE) { + VGM_LOG("MUL: unknown codec\n"); + goto fail; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MUL; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = num_samples; + vgmstream->codec_endian = big_endian; + + switch(codec) { + case PSX: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_mul; + break; + + case DSP: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_blocked_mul; + + dsp_read_coefs_be(vgmstream,streamFile,coefs_offset+0x00,0x2e); + dsp_read_hist_be (vgmstream,streamFile,coefs_offset+0x24,0x2e); + break; + + case XBOX: + vgmstream->coding_type = coding_XBOX_IMA_int; + vgmstream->layout_type = layout_blocked_mul; + break; + + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c b/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c index 5780774b4..f9b5e7682 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -/* SPSD - Naomi (arcade) streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */ +/* SPSD - Naomi (arcade) and early Dreamcast streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; @@ -10,8 +10,9 @@ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) { /* checks */ - /* .spsd: header id */ - if (!check_extensions(streamFile, "spsd")) + /* .str: actual extension, rare [Shenmue (DC)] + * .spsd: header id */ + if (!check_extensions(streamFile, "str,spsd")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */ goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c index fcb0fa33d..077404ac2 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c @@ -6,8 +6,11 @@ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { off_t start_offset; int loop_flag, channel_count; - /* check extension, case insensitive (the ROM seems to use simply .bin though) */ - if (!check_extensions(streamFile,"strm")) + + /* checks*/ + /* .bin: actual extension + * .strm: header id */ + if (!check_extensions(streamFile,"bin,strm")) goto fail; /* check header */ @@ -31,13 +34,12 @@ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { vgmstream->meta_type = meta_NDS_STRM_FFTA2; - vgmstream->coding_type = coding_DVI_IMA_int; + vgmstream->coding_type = coding_FFTA2_IMA; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x80; if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; - return vgmstream; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c index 68e43df85..fc492dce3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c @@ -9,30 +9,30 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) { int loop_flag = 0, channel_count, short_mpds; - /* check extension, case insensitive */ + /* checks */ /* .dsp: Big Air Freestyle */ /* .mds: Terminator 3 The Redemption, Mission Impossible: Operation Surma */ - if (!check_extensions(streamFile, "dsp,mds")) goto fail; - - /* check header */ + if (!check_extensions(streamFile, "dsp,mds")) + goto fail; if (read_32bitBE(0x00,streamFile) != 0x4D504453) /* "MPDS" */ goto fail; - short_mpds = read_32bitBE(0x04,streamFile) != 0x00010000 && check_extensions(streamFile, "mds"); /* version byte? */ + short_mpds = read_32bitBE(0x04,streamFile) != 0x00010000 && /* version byte? */ + check_extensions(streamFile, "mds"); channel_count = short_mpds ? read_16bitBE(0x0a, streamFile) : read_32bitBE(0x14, streamFile); if (channel_count > 2) goto fail; + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->coding_type = coding_NGC_DSP; vgmstream->meta_type = meta_NGC_DSP_MPDS; - vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; if (!short_mpds) { /* Big Air Freestyle */ start_offset = 0x80; @@ -50,17 +50,22 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) { vgmstream->num_samples = read_32bitBE(0x04,streamFile); vgmstream->sample_rate = (uint16_t)read_16bitBE(0x08,streamFile); vgmstream->interleave_block_size = channel_count==1 ? 0 : 0x200; + /* some kind of hist after 0x0c? */ -#if 0 //unknown coeffs/hist, related to data after 0x0c? (only coefs 0..7 seem to be needed) + /* set coefs, debugged from the MI:OS ELF (helpfully marked as "sMdsCoefs") */ { - off_t offset = 0x0c; - int i,ch; - for (ch=0; ch < vgmstream->channels; ch++) { - for (i=0; i < 16; i++) - vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(offset + i*2); + static const int16_t coefs[16] = { + 0x0000,0x0000,0x0780,0x0000,0x0e60,0xf980,0x0c40,0xf920, + 0x0f40,0xf880,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 + }; + int i, ch; + + for (ch = 0; ch < channel_count; ch++) { + for (i = 0; i < 16; i++) { + vgmstream->ch[ch].adpcm_coef[i] = coefs[i]; + } } } -#endif } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c index ddf4d34e6..010287e18 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -1114,16 +1114,18 @@ fail: return NULL; } -/* .vag - from Penny-Punching Princess (Switch) sfx */ -VGMSTREAM * init_vgmstream_dsp_vag(STREAMFILE *streamFile) { +/* .vag - Nippon Ichi SPS wrapper [Penny-Punching Princess (Switch), Ys VIII (Switch)] */ +VGMSTREAM * init_vgmstream_dsp_sps_n1(STREAMFILE *streamFile) { dsp_meta dspm = {0}; /* checks */ - if (!check_extensions(streamFile, "vag")) + /* .vag: Penny-Punching Princess (Switch) + * .nlsd: Ys VIII (Switch) */ + if (!check_extensions(streamFile, "vag,nlsd")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x08000000) /* file type? OPUSs had 09 */ + if (read_32bitBE(0x00,streamFile) != 0x08000000) /* file type (see other N1 SPS) */ goto fail; - if (read_32bitLE(0x08,streamFile) != read_32bitLE(0x24,streamFile)) /* header has various repeated values */ + if ((uint16_t)read_16bitLE(0x08,streamFile) != read_32bitLE(0x24,streamFile)) /* header has various repeated values */ goto fail; dspm.channel_count = 1; @@ -1166,3 +1168,31 @@ VGMSTREAM * init_vgmstream_dsp_itl_ch(STREAMFILE *streamFile) { fail: return NULL; } + +/* .adpcmx - AQUASTYLE wrapper [Touhou Genso Wanderer -Reloaded- (Switch)] */ +VGMSTREAM * init_vgmstream_dsp_adpcmx(STREAMFILE *streamFile) { + dsp_meta dspm = {0}; + + /* checks */ + if (!check_extensions(streamFile, "adpcmx")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x41445059) /* "ADPY" */ + goto fail; + /* 0x04(2): 1? */ + /* 0x08: some size? */ + /* 0x0c: null */ + + dspm.channel_count = read_16bitLE(0x06,streamFile); + dspm.max_channels = 2; + dspm.little_endian = 1; + + dspm.header_offset = 0x10; + dspm.header_spacing = 0x60; + dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channel_count; + dspm.interleave = 0x08; + + dspm.meta_type = meta_DSP_ADPCMX; + return init_vgmstream_dsp_common(streamFile, &dspm); +fail: + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c index 71c0556fb..e7f5bd59e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c @@ -17,7 +17,8 @@ VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE *streamFile) { if (read_16bitBE(0x00,streamFile) != 0x01) /* version? */ goto fail; - if (read_32bitBE(0x04,streamFile) != 0x04) /* entry size? */ + if (read_32bitBE(0x04,streamFile) != 0x02 && /* Mario Party 4 (GC) */ + read_32bitBE(0x04,streamFile) != 0x04) /* Cubic Lode Runner (GC) */ goto fail; if (read_32bitBE(0x08,streamFile) != 0x7d00) /* not-sample rate? */ goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nub_xma.c b/Frameworks/vgmstream/vgmstream/src/meta/nub_xma.c index cb33d551c..8ce8fa62c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nub_xma.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nub_xma.c @@ -10,10 +10,9 @@ VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile) { int num_samples, loop_start_sample, loop_end_sample; - /* check extension, case insensitive */ + /* checks */ if ( !check_extensions(streamFile,"xma")) /* (probably meant to be .nub) */ goto fail; - if (read_32bitBE(0x00,streamFile) != 0x786D6100) /* "xma\0" */ goto fail; @@ -55,19 +54,17 @@ VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile) { } else { /* "fmt " */ bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1); } - if (bytes <= 0) goto fail; - - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);; + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); /* samples needs adjustment */ } #else goto fail; #endif - - /* open the file for reading */ if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nus3audio.c b/Frameworks/vgmstream/vgmstream/src/meta/nus3audio.c new file mode 100644 index 000000000..79826bc38 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nus3audio.c @@ -0,0 +1,119 @@ +#include "meta.h" +#include "../coding/coding.h" + +typedef enum { IDSP, OPUS, } nus3audio_codec; + +/* .nus3audio - Namco's newest newest audio container [Super Smash Bros. Ultimate (Switch)] */ +VGMSTREAM * init_vgmstream_nus3audio(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t subfile_offset = 0, name_offset = 0; + size_t subfile_size = 0; + nus3audio_codec codec; + const char* fake_ext = NULL; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* checks */ + if (!check_extensions(streamFile, "nus3audio")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x4E555333) /* "NUS3" */ + goto fail; + if (read_32bitLE(0x04,streamFile) + 0x08 != get_streamfile_size(streamFile)) + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x41554449) /* "AUDI" */ + goto fail; + + + /* parse existing chunks */ + { + off_t offset = 0x0c; + size_t file_size = get_streamfile_size(streamFile); + uint32_t codec_id = 0; + + total_subsongs = 0; + + while (offset < file_size) { + uint32_t chunk_id = (uint32_t)read_32bitBE(offset+0x00, streamFile); + size_t chunk_size = (size_t)read_32bitLE(offset+0x04, streamFile); + + switch(chunk_id) { + case 0x494E4458: /* "INDX": audio index */ + total_subsongs = read_32bitLE(offset+0x08 + 0x00,streamFile); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + break; + + case 0x4E4D4F46: /* "NMOF": name offsets (absolute, inside TNNM) */ + name_offset = read_32bitLE(offset+0x08 + 0x04*(target_subsong-1),streamFile); + break; + + case 0x41444F46: /* "ADOF": audio offsets (absolute, inside PACK) */ + subfile_offset = read_32bitLE(offset+0x08 + 0x08*(target_subsong-1) + 0x00,streamFile); + subfile_size = read_32bitLE(offset+0x08 + 0x08*(target_subsong-1) + 0x04,streamFile); + break; + + case 0x544E4944: /* "TNID": tone ids? */ + case 0x544E4E4D: /* "TNNM": tone names */ + case 0x4A554E4B: /* "JUNK": padding */ + case 0x5041434B: /* "PACK": main data */ + default: + break; + } + + offset += 0x08 + chunk_size; + } + + if (total_subsongs == 0 || subfile_offset == 0 || subfile_size == 0) { + VGM_LOG("NUS3AUDIO: subfile not found\n"); + goto fail; + } + + codec_id = read_32bitBE(subfile_offset, streamFile); + switch(codec_id) { + case 0x49445350: /* "IDSP" */ + codec = IDSP; + fake_ext = "idsp"; + break; + case 0x4F505553: /* "OPUS" */ + codec = OPUS; + fake_ext = "opus"; + break; + default: + VGM_LOG("NUS3AUDIO: unknown codec %x\n", codec_id); + goto fail; + } + } + + + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); + if (!temp_streamFile) goto fail; + + /* init the VGMSTREAM */ + switch(codec) { + case IDSP: + vgmstream = init_vgmstream_idsp_nus3(temp_streamFile); + if (!vgmstream) goto fail; + break; + case OPUS: + vgmstream = init_vgmstream_opus_nus3(temp_streamFile); + if (!vgmstream) goto fail; + break; + default: + goto fail; + } + + vgmstream->num_streams = total_subsongs; + if (name_offset) /* null-terminated */ + read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile); + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} + + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nus3bank.c b/Frameworks/vgmstream/vgmstream/src/meta/nus3bank.c index f47919ae5..48b749d79 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nus3bank.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nus3bank.c @@ -1,7 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_nus3bank_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); typedef enum { /*XMA_RAW, ATRAC3,*/ IDSP, ATRAC9, OPUS, BNSF, /*PCM, XMA_RIFF*/ } nus3bank_codec; /* .nus3bank - Namco's newest audio container [Super Smash Bros (Wii U), idolmaster (PS4))] */ @@ -144,7 +143,7 @@ VGMSTREAM * init_vgmstream_nus3bank(STREAMFILE *streamFile) { //;VGM_LOG("NUS3BANK: subfile=%lx, size=%x\n", subfile_offset, subfile_size); - temp_streamFile = setup_nus3bank_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); if (!temp_streamFile) goto fail; /* init the VGMSTREAM */ @@ -182,27 +181,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - - -static STREAMFILE* setup_nus3bank_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nwav.c b/Frameworks/vgmstream/vgmstream/src/meta/nwav.c new file mode 100644 index 000000000..3d2309e2c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nwav.c @@ -0,0 +1,57 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* NWAV - from Chunsoft games [Fuurai no Shiren Gaiden: Onnakenshi Asuka Kenzan! (PC)] */ +VGMSTREAM * init_vgmstream_nwav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + + + /* checks */ + /* .nwav: header id (no filenames in bigfiles) */ + if ( !check_extensions(streamFile,"nwav") ) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x4E574156) /* "NWAV" */ + goto fail; + + +#ifdef VGM_USE_VORBIS + { + ogg_vorbis_meta_info_t ovmi = {0}; + int channels; + + /* 0x04: version? */ + /* 0x08: crc? */ + ovmi.stream_size = read_32bitLE(0x0c, streamFile); + ovmi.loop_end = read_32bitLE(0x10, streamFile); /* num_samples, actually */ + /* 0x14: sample rate */ + /* 0x18: bps? (16) */ + channels = read_8bit(0x19, streamFile); + start_offset = read_16bitLE(0x1a, streamFile); + + ovmi.loop_flag = read_16bitLE(0x1c, streamFile) != 0; /* loop count? -1 = loops */ + /* 0x1e: always 2? */ + /* 0x20: always 1? */ + ovmi.loop_start = read_32bitLE(0x24, streamFile); + /* 0x28: always 1? */ + /* 0x2a: always 1? */ + /* 0x2c: always null? */ + + ovmi.meta_type = meta_NWAV; + + /* values are in resulting bytes */ + ovmi.loop_start = ovmi.loop_start / sizeof(int16_t) / channels; + ovmi.loop_end = ovmi.loop_end / sizeof(int16_t) / channels; + + vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); + } +#else + goto fail; +#endif + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nxa.c b/Frameworks/vgmstream/vgmstream/src/meta/nxa.c index 3c385ad2a..fc05d6818 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nxa.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nxa.c @@ -40,7 +40,7 @@ VGMSTREAM * init_vgmstream_opus_nxa(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; if (vgmstream->num_samples == 0) { - vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile) - skip; + vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip; } } #else diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c new file mode 100644 index 000000000..41a5ca736 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c @@ -0,0 +1,173 @@ +#include "meta.h" +#include "../coding/coding.h" + + +static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size); +static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset); + +/* Ogg Opus - standard Opus with optional looping comments [The Pillars of Earth (PC), Monster Boy and the Cursed Kingdom (Switch)] */ +VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, data_offset = 0; + size_t page_size = 0; + int loop_flag, channel_count, original_rate; + int loop_start = 0, loop_end = 0; + + + /* checks */ + /* .opus: standard, .lopus: fake extension for plugins + * .ogg: less common, .logg: same */ + if (!check_extensions(streamFile, "opus,lopus,ogg,logg")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x4F676753) /* "OggS" */ + goto fail; + /* see: https://tools.ietf.org/html/rfc7845.html */ + + start_offset = 0x00; + + /* parse 1st page: opus head */ + if (!get_ogg_page_size(streamFile, start_offset, &data_offset, &page_size)) + goto fail; + if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ + read_32bitBE(data_offset+0x04,streamFile) != 0x48656164) /* "Head" */ + goto fail; + /* 0x01: version 1, fixed */ + channel_count = read_8bit(data_offset+0x09,streamFile); + /* 0x0A: skip samples */ + original_rate = read_32bitLE(data_offset+0x0c,streamFile); + /* 0x10: gain */ + /* 0x12: mapping family */ + + /* parse 2nd page: opus tags (also mandatory) */ + if (!get_ogg_page_size(streamFile, start_offset+page_size, &data_offset, &page_size)) + goto fail; + if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ + read_32bitBE(data_offset+0x04,streamFile) != 0x54616773) /* "Tags" */ + goto fail; + + loop_flag = 0; + { + char user_comment[1024+1]; + off_t offset; + int vendor_size, comment_count, user_comment_size, user_comment_max; + int i; + int has_encoder_options = 0, has_title = 0; + + vendor_size = read_32bitLE(data_offset+0x08,streamFile); + comment_count = read_32bitLE(data_offset+0x0c+vendor_size,streamFile); + + /* parse comments */ + offset = data_offset + 0x0c + vendor_size + 0x04; + for (i = 0; i < comment_count; i++) { + user_comment_size = read_32bitLE(offset+0x00,streamFile); + user_comment_max = user_comment_size > 1024 ? 1024 : user_comment_size; + read_string(user_comment,user_comment_max+1, offset+0x04,streamFile); + + + /* parse loop strings */ + if (strstr(user_comment,"LOOP_START=")==user_comment) { /* Monster Boy and the Cursed Kingdom (Switch) */ + loop_start = atol(strrchr(user_comment,'=')+1); + loop_flag = (loop_start >= 0); + } + else if (strstr(user_comment,"LOOP_END=")==user_comment) { /* LOOP_START pair */ + loop_end = atol(strrchr(user_comment,'=')+1); + } + else if (strstr(user_comment,"ENCODER_OPTIONS=")==user_comment) { /* for detection */ + has_encoder_options = 1; + } + else if (strstr(user_comment,"TITLE=")==user_comment) { /* for detection */ + has_title = 1; + } + + + //;VGM_LOG("OggOpus: user_comment=%s\n", user_comment); + offset += 0x04 + user_comment_size; + } + + + /* Monster Boy has loop points for 44100hz (what), but Opus is resampled so + * they must be adjusted (with extra checks just in case). */ + if (loop_flag && original_rate < 48000 && has_encoder_options && has_title) { + float modifier = 48000.0f / (float)original_rate; + loop_start = loop_start * modifier; + loop_end = loop_end * modifier; + } + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_OGG_OPUS; + vgmstream->sample_rate = 48000; /* Opus always resamples to this */ + vgmstream->num_samples = ogg_get_num_samples(streamFile, 0x00); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + +#ifdef VGM_USE_FFMPEG + { + vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset, get_streamfile_size(streamFile)); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + /* FFmpeg+libopus handles skip samples ok, FFmpeg+opus doesn't */ + } +#else + goto fail; +#endif + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +/* parse OggS's bizarre segment table */ +static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size) { + uint8_t segments; + size_t page_size = 0; + int i; + + if (read_32bitBE(page_offset+0x00,streamFile) != 0x4F676753) /* "OggS" */ + goto fail; + + /* read all segment sizes */ + segments = (uint8_t)read_8bit(page_offset+0x1a, streamFile); + for (i = 0; i < segments; i++) { + page_size += (uint8_t)read_8bit(page_offset + 0x1b + i, streamFile); + } + page_size += 0x1b + segments; + + if (out_data_offset) *out_data_offset = page_offset + 0x1b + segments; + if (out_page_size) *out_page_size = page_size; + return 1; +fail: + return 0; +} + +/* Ogg doesn't have num_samples info, must manually seek+read last granule + * (Xiph is insistent this is the One True Way). */ +static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset) { + uint32_t expected_id = 0x4F676753; + off_t offset = get_streamfile_size(streamFile) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04; + + //todo better buffer reads (Ogg page max is 0xFFFF) + //lame way to force buffer, assuming it's around that + read_32bitBE(offset - 0x4000, streamFile); + + while (offset >= start_offset) { + uint32_t current_id = read_32bitBE(offset, streamFile); + if (current_id == expected_id) { /* if more checks are needed last page starts with 0x0004 */ + return read_32bitLE(offset+0x04+0x01+0x01, streamFile); /* get last granule = total samples (64b but whatevs) */ + } + + offset--; + } + + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c index 76bd0aa5d..b9342421b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c @@ -78,7 +78,7 @@ static void um3_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* first 0x800 bytes are xor'd with 0xff */ + /* first 0x800 bytes are xor'd */ if (ov_streamfile->offset < 0x800) { int num_crypt = 0x800 - ov_streamfile->offset; if (num_crypt > bytes_read) @@ -94,7 +94,7 @@ static void kovs_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* first 0x100 bytes are xor'd with offset */ + /* first 0x100 bytes are xor'd */ if (ov_streamfile->offset < 0x100) { int max_offset = ov_streamfile->offset + bytes_read; if (max_offset > 0x100) @@ -110,9 +110,9 @@ static void psychic_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb size_t bytes_read = size*nmemb; int i; - /* add 0x23 ('#') */ + /* bytes add 0x23 ('#') */ for (i = 0; i < bytes_read; i++) { - ((uint8_t*)ptr)[i] += 0x23; + ((uint8_t*)ptr)[i] += 0x23; } } @@ -125,7 +125,7 @@ static void sngw_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v put_32bitBE(key, ov_streamfile->xor_value); - /* bytes are xor'd with key and nibble-swapped, first "OggS" is changed */ + /* first "OggS" is changed and bytes are xor'd and nibble-swapped */ for (i = 0; i < bytes_read; i++) { if (ov_streamfile->offset+i < 0x04) { ((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4]; @@ -145,7 +145,7 @@ static void isd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* bytes are xor'd with key */ + /* bytes are xor'd */ for (i = 0; i < bytes_read; i++) { ((uint8_t*)ptr)[i] ^= key[(ov_streamfile->offset + i) % 16]; } @@ -160,7 +160,6 @@ static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v /* first "OggS" is changed */ for (i = 0; i < bytes_read; i++) { if (ov_streamfile->offset+i < 0x04) { - /* replace key in the first 4 bytes with "OggS" */ ((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4]; } else { @@ -177,7 +176,7 @@ static void rpgmvo_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* first 0x10 are xor'd with a key, but the header can be easily reconstructed + /* first 0x10 are xor'd, but header can be easily reconstructed * (key is also in (game)/www/data/System.json "encryptionKey") */ for (i = 0; i < bytes_read; i++) { if (ov_streamfile->offset+i < 0x10) { @@ -197,7 +196,7 @@ static void eno_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* bytes are xor'd with key */ + /* bytes are xor'd */ for (i = 0; i < bytes_read; i++) { ((uint8_t*)ptr)[i] ^= (uint8_t)ov_streamfile->xor_value; } @@ -208,7 +207,7 @@ static void ys8_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* bytes are xor'd with key and nibble-swapped */ + /* bytes are xor'd and nibble-swapped */ for (i = 0; i < bytes_read; i++) { uint8_t val = ((uint8_t*)ptr)[i] ^ ov_streamfile->xor_value; ((uint8_t*)ptr)[i] = ((val << 4) & 0xf0) | ((val >> 4) & 0x0f); @@ -220,7 +219,7 @@ static void gwm_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo ogg_vorbis_streamfile * const ov_streamfile = datasource; int i; - /* bytes are xor'd with key */ + /* bytes are xor'd */ for (i = 0; i < bytes_read; i++) { ((uint8_t*)ptr)[i] ^= (uint8_t)ov_streamfile->xor_value; } @@ -236,7 +235,7 @@ static void mus_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo int i; char *header_id = "OggS"; - /* bytes are xor'd with key, first "OggS" is changed */ + /* first "OggS" is changed and bytes are xor'd */ for (i = 0; i < bytes_read; i++) { if (ov_streamfile->offset+i < 0x04) { /* if decrypted gives "Mus " */ ((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4]; @@ -247,6 +246,35 @@ static void mus_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo } } +static void lse_add_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { + size_t bytes_read = size*nmemb; + ogg_vorbis_streamfile * const ov_streamfile = datasource; + int i; + + /* bytes are xor'd */ + for (i = 0; i < bytes_read; i++) { + int key = (uint8_t)ov_streamfile->xor_value + ((ov_streamfile->offset + i) % 256); + ((uint8_t*)ptr)[i] ^= key; + } +} + +static void lse_ff_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { + size_t bytes_read = size*nmemb; + ogg_vorbis_streamfile * const ov_streamfile = datasource; + int i; + char *header_id = "OggS"; + + /* first "OggS" is changed and bytes are xor'd */ + for (i = 0; i < bytes_read; i++) { + if (ov_streamfile->offset+i < 0x04) { + ((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4]; + } + else { + ((uint8_t*)ptr)[i] ^= 0xFF; + } + } +} + /* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { @@ -262,6 +290,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { int is_eno = 0; int is_gwm = 0; int is_mus = 0; + int is_lse = 0; /* check extension */ @@ -288,26 +317,27 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { is_gwm = 1; } else if (check_extensions(streamFile,"mus")) { /* .mus: Redux - Dark Matters (PC) */ is_mus = 1; + } else if (check_extensions(streamFile,"lse")) { /* .lse: Labyrinth of Refrain: Coven of Dusk (PC) */ + is_lse = 1; } else { goto fail; } - /* check standard Ogg Vorbis and variations */ if (is_ogg) { if (read_32bitBE(0x00,streamFile) == 0x2c444430) { /* Psychic Software [Darkwind: War on Wheels (PC)] */ ovmi.decryption_callback = psychic_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_PSYCHIC; + ovmi.meta_type = meta_OGG_encrypted; } else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */ ovmi.decryption_callback = l2sd_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_L2SD; + ovmi.meta_type = meta_OGG_encrypted; } - else if (read_32bitBE(0x00,streamFile) == 0x048686C5) { /* XOR'ed + bitswapped "OggS" [Ys VIII (PC)] */ + else if (read_32bitBE(0x00,streamFile) == 0x048686C5) { /* "OggS" XOR'ed + bitswapped [Ys VIII (PC)] */ ovmi.xor_value = 0xF0; ovmi.decryption_callback = ys8_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_YS8; + ovmi.meta_type = meta_OGG_encrypted; } - else if (read_32bitBE(0x00,streamFile) == 0x4f676753) { /* "OggS" */ + else if (read_32bitBE(0x00,streamFile) == 0x4f676753) { /* "OggS" (standard) */ ovmi.meta_type = meta_OGG_VORBIS; } else { @@ -315,16 +345,14 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { } } - /* check "Ultramarine3" (???), may be encrypted */ - if (is_um3) { - if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */ + if (is_um3) { /* ["Ultramarine3" (???)] */ + if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" (optionally encrypted) */ ovmi.decryption_callback = um3_ogg_decryption_callback; } - ovmi.meta_type = meta_OGG_UM3; + ovmi.meta_type = meta_OGG_encrypted; } - /* check KOVS (Koei Tecmo games), header + encrypted */ - if (is_kovs) { + if (is_kovs) { /* Koei Tecmo PC games] */ if (read_32bitBE(0x00,streamFile) != 0x4b4f5653) { /* "KOVS" */ goto fail; } @@ -336,19 +364,17 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { start_offset = 0x20; } - /* check SNGW (Capcom's MT Framework PC games), may be encrypted */ - if (is_sngw) { - if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */ + if (is_sngw) { /* [Capcom's MT Framework PC games] */ + if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" (optionally encrypted) */ ovmi.xor_value = read_32bitBE(0x00,streamFile); ovmi.decryption_callback = sngw_ogg_decryption_callback; } - ovmi.meta_type = meta_OGG_SNGW; + ovmi.meta_type = meta_OGG_encrypted; } - /* check ISD [Gunvolt (PC)], encrypted */ - if (is_isd) { + if (is_isd) { /* [Gunvolt (PC)] */ ovmi.decryption_callback = isd_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_ISD; + ovmi.meta_type = meta_OGG_encrypted; //todo looping unknown, not in Ogg comments // game has sound/GV_steam.* files with info about sound/stream/*.isd @@ -359,39 +385,48 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { // 0x0c(2): PCM block size, 0x0e(2): PCM bps, 0x10: null, 0x18: samples (in PCM bytes) } - /* check RPGMKVO [RPG Maker MV (PC)], header + partially encrypted */ - if (is_rpgmvo) { + if (is_rpgmvo) { /* [RPG Maker MV (PC)] */ if (read_32bitBE(0x00,streamFile) != 0x5250474D && /* "RPGM" */ read_32bitBE(0x00,streamFile) != 0x56000000) { /* "V\0\0\0" */ goto fail; } ovmi.decryption_callback = rpgmvo_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_RPGMV; + ovmi.meta_type = meta_OGG_encrypted; start_offset = 0x10; } - /* check ENO [Metronomicon (PC)], key + encrypted */ - if (is_eno) { + if (is_eno) { /* [Metronomicon (PC)] */ /* first byte probably derives into xor key, but this works too */ ovmi.xor_value = read_8bit(0x05,streamFile); /* always zero = easy key */ ovmi.decryption_callback = eno_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_ENO; + ovmi.meta_type = meta_OGG_encrypted; start_offset = 0x01; } - /* check GWM [Adagio: Cloudburst (PC)], encrypted */ - if (is_gwm) { + if (is_gwm) { /* [Adagio: Cloudburst (PC)] */ ovmi.xor_value = 0x5D; ovmi.decryption_callback = gwm_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_GWM; + ovmi.meta_type = meta_OGG_encrypted; } - /* check .mus [Redux - Dark Matters (PC)], encrypted */ - if (is_mus) { + if (is_mus) { /* [Redux - Dark Matters (PC)] */ ovmi.decryption_callback = mus_ogg_decryption_callback; - ovmi.meta_type = meta_OGG_MUS; + ovmi.meta_type = meta_OGG_encrypted; + } + + if (is_lse) { /* [Nippon Ichi PC games] */ + if (read_32bitBE(0x00,streamFile) == 0xFFFFFFFF) { /* [Operation Abyss: New Tokyo Legacy (PC)] */ + ovmi.decryption_callback = lse_ff_ogg_decryption_callback; + ovmi.meta_type = meta_OGG_encrypted; + } + else { /* [Operation Babel: New Tokyo Legacy (PC), Labyrinth of Refrain: Coven of Dusk (PC)] */ + ovmi.decryption_callback = lse_add_ogg_decryption_callback; + ovmi.xor_value = (uint8_t)read_8bit(0x04,streamFile) - 0x04; + ovmi.meta_type = meta_OGG_encrypted; + /* key is found at file_size-1 but this works too (same key for most files but can vary) */ + } } @@ -566,7 +601,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb } } - //;VGM_LOG("OGG: user_comment=%s\n", user_comment); + ;VGM_LOG("OGG: user_comment=%s\n", user_comment); } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/opus.c b/Frameworks/vgmstream/vgmstream/src/meta/opus.c index 125e1e9d1..21186b881 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/opus.c @@ -50,14 +50,13 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type, vgmstream->layout_type = layout_none; if (vgmstream->num_samples == 0) { - vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile) - skip; + vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip; } } #else goto fail; #endif - /* open the file for reading */ if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; @@ -71,8 +70,8 @@ fail: /* standard Switch Opus, Nintendo header + raw data (generated by opus_test.c?) [Lego City Undercover (Switch)] */ VGMSTREAM * init_vgmstream_opus_std(STREAMFILE *streamFile) { STREAMFILE * PSIFile = NULL; - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0; + off_t offset; + int num_samples, loop_start, loop_end; /* checks */ if (!check_extensions(streamFile,"opus,lopus")) @@ -102,13 +101,12 @@ fail: /* Nippon1 variation [Disgaea 5 (Switch)] */ VGMSTREAM * init_vgmstream_opus_n1(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0; + off_t offset; + int num_samples, loop_start, loop_end; /* checks */ if ( !check_extensions(streamFile,"opus,lopus")) goto fail; - if (!((read_32bitBE(0x04,streamFile) == 0x00000000 && read_32bitBE(0x0c,streamFile) == 0x00000000) || (read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && read_32bitBE(0x0c,streamFile) == 0xFFFFFFFF))) goto fail; @@ -126,8 +124,8 @@ fail: /* Capcom variation [Ultra Street Fighter II (Switch), Resident Evil: Revelations (Switch)] */ VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0; + off_t offset; + int num_samples, loop_start, loop_end; int channel_count; /* checks */ @@ -205,8 +203,8 @@ fail: /* Procyon Studio variation [Xenoblade Chronicles 2 (Switch)] */ VGMSTREAM * init_vgmstream_opus_nop(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; + off_t offset; + int num_samples, loop_start = 0, loop_end = 0, loop_flag; /* checks */ if (!check_extensions(streamFile,"nop")) @@ -231,12 +229,11 @@ fail: /* Shin'en variation [Fast RMX (Switch)] */ VGMSTREAM * init_vgmstream_opus_shinen(STREAMFILE *streamFile) { off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0; + int num_samples, loop_start, loop_end; /* checks */ if ( !check_extensions(streamFile,"opus,lopus")) goto fail; - if (read_32bitBE(0x08,streamFile) != 0x01000080) goto fail; @@ -259,6 +256,7 @@ VGMSTREAM * init_vgmstream_opus_nus3(STREAMFILE *streamFile) { int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; /* checks */ + /* .opus: header ID (they only exist inside .nus3bank) */ if (!check_extensions(streamFile, "opus,lopus")) goto fail; if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ @@ -281,32 +279,61 @@ fail: return NULL; } -/* Nihon Falcom NLSD Opus [Ys VIII: Lacrimosa of Dana (Switch)] - Similar to Nippon Ichi Software "AT9" Opus (Penny Punching Princess (Switch) - Unlike Penny Punching Princess, this is not segmented */ -VGMSTREAM * init_vgmstream_opus_nlsd(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; +/* Nippon Ichi SPS wrapper (non-segmented) [Ys VIII: Lacrimosa of Dana (Switch)] */ +VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE *streamFile) { + off_t offset; + int num_samples, loop_start = 0, loop_end = 0, loop_flag; /* checks */ - if (!check_extensions(streamFile, "nlsd")) + /* .sps: Labyrinth of Refrain - Coven of Dusk (Switch) + * .nlsd: Disgaea Refine (Switch), Ys VIII (Switch) */ + if (!check_extensions(streamFile, "sps,nlsd")) goto fail; - /* File type check - DSP is 0x8, Opus is 0x9 */ - if (read_32bitBE(0x00, streamFile) != 0x09000000) + if (read_32bitBE(0x00, streamFile) != 0x09000000) /* file type (see other N1 SPS) */ goto fail; offset = 0x1C; num_samples = read_32bitLE(0x0C, streamFile); - /* Check if there's a loop_end "adjuster" value to determine loop_flag - Setting loop_flag to loop_start would work too but it may cause conflicts - With files that may have a 0 sample loop_start. */ - // Not sure why this is a thing but let's roll with it. - loop_flag = read_32bitLE(0x18, streamFile); + /* sections num_samples (remnant of segmented opus_sps_n1): + * 0x10: intro, 0x14: loop, 0x18: end (all must add up to num_samples) */ + loop_flag = read_32bitLE(0x18, streamFile); /* with loop disabled only loop section has samples */ if (loop_flag) { loop_start = read_32bitLE(0x10, streamFile); - /* They were being really creative here */ - loop_end = (num_samples - read_32bitLE(0x18, streamFile)); + loop_end = loop_start + read_32bitLE(0x14, streamFile); + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} + +/* AQUASTYLE wrapper [Touhou Genso Wanderer -Reloaded- (Switch)] */ +VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE *streamFile) { + off_t offset; + int num_samples, loop_start = 0, loop_end = 0; + float modifier; + + /* checks */ + if (!check_extensions(streamFile, "opusx")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ + goto fail; + + offset = 0x10; + /* values are for the original 44100 files, but Opus resamples to 48000 */ + modifier = 48000.0f / 44100.0f; + num_samples = 0;//read_32bitLE(0x04, streamFile) * modifier; /* better use calc'd num_samples */ + loop_start = read_32bitLE(0x08, streamFile) * modifier; + loop_end = read_32bitLE(0x0c, streamFile) * modifier; + + /* resampling calcs are slighly off and may to over num_samples, but by removing delay seems ok */ + if (loop_start >= 120) { + loop_start -= 128; + loop_end -= 128; + } + else { + loop_end = 0; } return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/opus_ppp.c b/Frameworks/vgmstream/vgmstream/src/meta/opus_ppp.c index 87906b9f8..0ff9a26ae 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/opus_ppp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/opus_ppp.c @@ -2,10 +2,8 @@ #include "../coding/coding.h" #include "../layout/layout.h" -static STREAMFILE* setup_opus_ppp_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); - -/* .AT9 Opus - from Penny-Punching Princess (Switch) */ -VGMSTREAM * init_vgmstream_opus_ppp(STREAMFILE *streamFile) { +/* Nippon Ichi SPS wrapper (segmented) [Penny-Punching Princess (Switch)] */ +VGMSTREAM * init_vgmstream_opus_sps_n1_segmented(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t segment_offset; int loop_flag, channel_count; @@ -19,11 +17,11 @@ VGMSTREAM * init_vgmstream_opus_ppp(STREAMFILE *streamFile) { /* checks */ if (!check_extensions(streamFile, "at9")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x09000000) /* file type? DSPs had 08 */ + if (read_32bitBE(0x00,streamFile) != 0x09000000) /* file type (see other N1 SPS) */ goto fail; if (read_32bitLE(0x04,streamFile) + 0x1c != get_streamfile_size(streamFile)) goto fail; - /* 0x08(2): sample rate, 0x0a(2): loop flag?, 0x0c: num_samples (slightly smaller than added samples) */ + /* 0x08(2): sample rate, 0x0a(2): flag?, 0x0c: num_samples (slightly smaller than added samples) */ segment_count = 3; /* intro/loop/end */ loop_start_segment = 1; @@ -43,7 +41,7 @@ VGMSTREAM * init_vgmstream_opus_ppp(STREAMFILE *streamFile) { if (!segment_size) goto fail; - temp_streamFile = setup_opus_ppp_streamfile(streamFile, segment_offset,segment_size, "opus"); + temp_streamFile = setup_subfile_streamfile(streamFile, segment_offset,segment_size, "opus"); if (!temp_streamFile) goto fail; data->segments[i] = init_vgmstream_opus_std(temp_streamFile); @@ -93,26 +91,3 @@ fail: free_layout_segmented(data); return NULL; } - -static STREAMFILE* setup_opus_ppp_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/p3d.c b/Frameworks/vgmstream/vgmstream/src/meta/p3d.c index d03e44587..6e1b77991 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/p3d.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/p3d.c @@ -11,11 +11,9 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) { int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - /* check extension, case insensitive */ + /* checks */ if (!check_extensions(streamFile,"p3d")) goto fail; - - /* check header */ if (read_32bitBE(0x0,streamFile) != 0x503344FF && /* "P3D"\FF (LE: PC) */ read_32bitBE(0x0,streamFile) != 0xFF443350) /* \FF"D3P" (BE: PS3, X360) */ goto fail; @@ -164,12 +162,12 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) { size_t bytes; bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, 0, 1,1); /* samples needs adjustment */ break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pona.c b/Frameworks/vgmstream/vgmstream/src/meta/pona.c index 791c23aa3..87d00b100 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/pona.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/pona.c @@ -1,127 +1,91 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* PONA (from Policenauts [3DO]) */ +/* PONA - from Policenauts (3DO) */ VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag; - int channel_count; + int loop_flag, channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("pona",filename_extension(filename))) goto fail; - /* check header */ + /* checks */ + /* .pona: fake extension? + * .sxd: Policenauts Pilot Disc (3DO) */ + if (!check_extensions(streamFile, "pona,sxd")) + goto fail; if (read_32bitBE(0x00,streamFile) != 0x13020000) goto fail; - - if ((read_32bitBE(0x06,streamFile)+0x800) != (get_streamfile_size(streamFile))) + if (read_32bitBE(0x06,streamFile)+0x800 != get_streamfile_size(streamFile)) goto fail; loop_flag = (read_32bitBE(0x0A,streamFile) != 0xFFFFFFFF); channel_count = 1; - - /* build the VGMSTREAM */ + start_offset = (uint16_t)(read_16bitBE(0x04,streamFile)); + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = (uint16_t)(read_16bitBE(0x04,streamFile)); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 22050; - vgmstream->coding_type = coding_SDX2; - vgmstream->num_samples = (get_streamfile_size(streamFile))-start_offset; - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitBE(0x0A,streamFile)); - vgmstream->loop_end_sample = (read_32bitBE(0x06,streamFile)); - } - - vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_PONA_3DO; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } + vgmstream->sample_rate = 22050; + vgmstream->num_samples = get_streamfile_size(streamFile) - start_offset; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x0A,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile); } + vgmstream->coding_type = coding_SDX2; + vgmstream->layout_type = layout_none; + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } -/* PONA (from Policenauts [PSX]) */ +/* PONA - from Policenauts (PSX) */ VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag; - int channel_count; + int loop_flag, channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("pona",filename_extension(filename))) goto fail; - - /* check header */ + /* checks */ + /* .pona: fake extension? */ + if (!check_extensions(streamFile, "pona")) + goto fail; if (read_32bitBE(0x00,streamFile) != 0x00000800) goto fail; - - if ((read_32bitBE(0x08,streamFile)+0x800) != (get_streamfile_size(streamFile))) + if (read_32bitBE(0x08,streamFile)+0x800 != get_streamfile_size(streamFile)) goto fail; loop_flag = (read_32bitBE(0xC,streamFile) != 0xFFFFFFFF); channel_count = 1; - - /* build the VGMSTREAM */ + start_offset = read_32bitBE(0x04,streamFile); + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = read_32bitBE(0x04,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = ((get_streamfile_size(streamFile))-start_offset)/16/channel_count*28; - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitBE(0x0C,streamFile)/16/channel_count*28); - vgmstream->loop_end_sample = (read_32bitBE(0x08,streamFile)/16/channel_count*28); - } - - vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_PONA_PSX; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } + vgmstream->sample_rate = 44100; + vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); + if (loop_flag) { + vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitBE(0x0C,streamFile), channel_count); + vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitBE(0x08,streamFile), channel_count); } + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_none; + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pos.c b/Frameworks/vgmstream/vgmstream/src/meta/pos.c index 0c904d62f..5e499ce66 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/pos.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/pos.c @@ -15,11 +15,12 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE *streamFile) { streamData = open_streamfile_by_ext(streamFile, "wav"); if (streamData) { - vgmstream = init_vgmstream_riff(streamData); + vgmstream = init_vgmstream_riff(streamData); if (!vgmstream) goto fail; vgmstream->meta_type = meta_RIFF_WAVE_POS; } else { +#ifdef VGM_USE_VORBIS /* hack for Ogg with external loops */ streamData = open_streamfile_by_ext(streamFile, "ogg"); if (streamData) { @@ -29,6 +30,9 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE *streamFile) { else { goto fail; } +#else + goto fail; +#endif } close_streamfile(streamData); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c index a20aedc7d..b72fb8858 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c @@ -150,10 +150,11 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { loop_start_sample = loop_start / 2 / channel_count; is_loop_samples = 1; } - else if ((loop_start % 0x800 == 0) && loop_start > 0) {/* sector-aligned, min is 0x800 */ + else if ((loop_start % 0x800 == 0) && loop_start > 0) {/* sector-aligned, min/0 is 0x800 */ /* cavia games: loop_start is offset [Drakengard 1/2, GITS: Stand Alone Complex] */ + /* offset is absolute from the "cavia stream format" container that adjusts ADS start */ loop_flag = 1; - loop_start_offset = loop_start; + loop_start_offset = loop_start - 0x800; ignore_silent_frame_cavia = 1; } else if (loop_start % 0x800 != 0 || loop_start == 0) { /* not sector aligned */ @@ -312,8 +313,6 @@ fail: /* ****************************************************************************** */ -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); - /* ADS in containers */ VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; @@ -355,28 +354,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - if (fake_ext) { - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - } - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_va3.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_va3.c new file mode 100644 index 000000000..616b37742 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_va3.c @@ -0,0 +1,80 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* VA3 - Konami / Sony Atrac3 Container [PS2 DDR Supernova 2 Arcade] */ +VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + uint32_t data_size, loop_start, loop_end; + + /* check extension, case insensitive */ + if (!check_extensions(streamFile, "va3")) + goto fail; + + if (read_32bitBE(0x00, streamFile) != 0x21334156) /* "!3AV" */ + goto fail; + + /* va3 header */ + start_offset = 0x800; + data_size = read_32bitLE(0x04, streamFile);// get_streamfile_size(streamFile) - start_offset; + // pretty sure 0x4 LE 32 bit is some sort of filesize... + + loop_flag = 0; + //0x18 is 1... what is this? + channel_count = 2; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + + vgmstream->sample_rate = read_32bitLE(0x14, streamFile); + vgmstream->num_samples = read_32bitLE(0x08, streamFile); + vgmstream->channels = channel_count; + vgmstream->meta_type = meta_VA3; + loop_start = 0; + loop_end = 0; + +#ifdef VGM_USE_FFMPEG + { + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[200]; + int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo; + block_size = 0xC0 * vgmstream->channels; + //max_samples = (data_size / block_size) * samples_size; + encoder_delay = 0x0; + joint_stereo = 0; + + /* make a fake riff so FFmpeg can parse the ATRAC3 */ + bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); + if (bytes <= 0) goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + //vgmstream->num_samples = max_samples; + + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start / block_size) * samples_size; + vgmstream->loop_end_sample = (loop_end / block_size) * samples_size; + } + + } +#else + goto fail; +#endif + + /* open the file for reading */ + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c index d76850efc..52e10b064 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c @@ -4,32 +4,30 @@ /* MSF - Sony's PS3 SDK format (MultiStream File) */ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - off_t start_offset, header_offset = 0; + off_t start_offset; uint32_t data_size, loop_start = 0, loop_end = 0; uint32_t id, codec_id, flags; int loop_flag = 0, channel_count; /* checks */ - /* .msf: standard, .at3: Silent Hill HD Collection, .mp3: Darkstalkers Resurrection */ + /* .msf: standard + * .at3: Silent Hill HD Collection (PS3) + * .mp3: Darkstalkers Resurrection (PS3) */ if (!check_extensions(streamFile,"msf,at3,mp3")) goto fail; - /* "WMSF" variation with a mini header over the MSFC header [Dai-2-Ji Super Robot Generations (PS3)] */ - if (read_32bitBE(0x00,streamFile) == 0x574D5346) { - header_offset = 0x10; - } - start_offset = header_offset+0x40; /* MSF header is always 0x40 */ + start_offset = 0x40; - /* check header "MSF" + version-char - * usually "MSF\0\1", "MSF\0\2", "MSF0"(\3\0), "MSF5"(\3\5), "MSFC"(\4\3) (last/common version) */ - id = read_32bitBE(header_offset+0x00,streamFile); + /* check header "MSF" + version-char, usually: + * 0x01, 0x02, 0x30 ("0"), 0x35 ("5"), 0x43 ("C") (last/most common version) */ + id = read_32bitBE(0x00,streamFile); if ((id & 0xffffff00) != 0x4D534600) goto fail; - codec_id = read_32bitBE(header_offset+0x04,streamFile); - channel_count = read_32bitBE(header_offset+0x08,streamFile); - data_size = read_32bitBE(header_offset+0x0C,streamFile); /* without header */ + codec_id = read_32bitBE(0x04,streamFile); + channel_count = read_32bitBE(0x08,streamFile); + data_size = read_32bitBE(0x0C,streamFile); /* without header */ if (data_size == 0xFFFFFFFF) /* unneeded? */ data_size = get_streamfile_size(streamFile) - start_offset; @@ -39,15 +37,15 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { * 0x20: VBR MP3 source (changed into simplified 0x1a1 CBR) * 0x40: joint stereo MP3 (apparently interleaved stereo for other formats) * 0x80+: (none/reserved) */ - flags = read_32bitBE(header_offset+0x14,streamFile); + flags = read_32bitBE(0x14,streamFile); /* sometimes loop_start/end is set with flag 0x10, but from tests it only loops if 0x01/02 is set * 0x10 often goes with 0x01 but not always (Castlevania HoD); Malicious PS3 uses flag 0x2 instead */ loop_flag = flags != 0xffffffff && ((flags & 0x01) || (flags & 0x02)); /* loop markers (marker N @ 0x18 + N*(4+4), but in practice only marker 0 is used) */ if (loop_flag) { - loop_start = read_32bitBE(header_offset+0x18,streamFile); - loop_end = read_32bitBE(header_offset+0x1C,streamFile); /* loop duration */ + loop_start = read_32bitBE(0x18,streamFile); + loop_end = read_32bitBE(0x1C,streamFile); /* loop duration */ loop_end = loop_start + loop_end; /* usually equals data_size but not always */ if (loop_end > data_size)/* not seen */ loop_end = data_size; @@ -58,9 +56,9 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* sample rate hack for strange MSFv1 files that don't have it */ - vgmstream->sample_rate = read_32bitBE(header_offset+0x10,streamFile); - if (vgmstream->sample_rate == 0x00000000) /* PS ADPCM only? */ + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + /* sample rate hack for strange MSFv1 files (PS ADPCM only?) */ + if (vgmstream->sample_rate == 0x00000000) vgmstream->sample_rate = 48000; vgmstream->meta_type = meta_PS3_MSF; @@ -115,12 +113,10 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { * (note that encoder may add a fade-in with looping/resampling enabled but should be skipped) */ encoder_delay = 1162; vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_size) - encoder_delay; - if (vgmstream->sample_rate==0xFFFFFFFF) /* some MSFv1 (Digi World SP) */ - vgmstream->sample_rate = 44100;//voice tracks seems to use 44khz, not sure about other tracks + if (vgmstream->sample_rate == 0xFFFFFFFF) /* some MSFv1 (Digi World SP) */ + vgmstream->sample_rate = 44100; /* voice tracks seems to use 44khz, not sure about other tracks */ bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if (!ffmpeg_data) goto fail; vgmstream->codec_data = ffmpeg_data; @@ -156,7 +152,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { if (loop_flag) { vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; vgmstream->loop_end_sample = (int64_t)loop_end * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; - /* loops are always CBR frame beginnings */ + /* loops are always aligned to CBR frame beginnings */ } /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ @@ -164,7 +160,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { } #endif #ifdef VGM_USE_MPEG - case 0x07: { /* MPEG (CBR LAME MP3) []Dengeki Bunko Fighting Climax (PS3) */ + case 0x07: { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */ mpeg_codec_data *mpeg_data = NULL; mpeg_data = init_mpeg(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels); @@ -176,7 +172,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { if (loop_flag) { vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data); - /* loops are always CBR frame beginnings */ + /* loops are always aligned to CBR frame beginnings */ } /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c deleted file mode 100644 index e49344291..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* FAG (Jackie Chan - Stuntmaster) */ -VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("fag",filename_extension(filename))) goto fail; - - /* check header */ - - /* Look if there's more than 1 one file... */ - if (read_32bitBE(0x00,streamFile) != 0x01000000) - goto fail; - - loop_flag = 0; - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x04,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 24000; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))/channel_count/32*28; - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x8000; - vgmstream->meta_type = meta_PSX_FAG; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/redspark.c b/Frameworks/vgmstream/vgmstream/src/meta/redspark.c index aee8f5e3e..fe8f0b93c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/redspark.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/redspark.c @@ -13,7 +13,7 @@ static uint32_t find_key(uint32_t firstword) { /* RSD - RedSpark (MadWorld) RS3D - RedSpark (Mario & Luigi: Dream Team I fi*/ -VGMSTREAM * init_vgmstream_RedSpark(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_redspark(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; off_t start_offset; @@ -105,7 +105,7 @@ VGMSTREAM * init_vgmstream_RedSpark(STREAMFILE *streamFile) { } else { vgmstream->layout_type = layout_none; } - vgmstream->meta_type = meta_RedSpark; + vgmstream->meta_type = meta_REDSPARK; { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 03b21ba3d..c0fc8683b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -272,8 +272,11 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { * .adx: Remember11 (PC) sfx * .adp: Headhunter (DC) * .xss: Spider-Man The Movie (Xbox) - * .xsew: Mega Man X Legacy Collections (PC) */ - if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew") ) { + * .xsew: Mega Man X Legacy Collections (PC) + * .adpcm: Angry Birds Transformers (Android) + * .adw: Dead Rising 2 (PC) + * .wd: Genma Onimusha (Xbox) voices */ + if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd") ) { ; } else if ( check_extensions(streamFile, "mwv") ) { @@ -310,13 +313,13 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { /* some Dreamcast/Naomi games do this [Headhunter (DC), Bomber hehhe (DC)] */ if (riff_size + 0x04 == file_size && read_16bitLE(0x14,streamFile)==0x0000) riff_size -= 0x04; - /* some PC games do this [Halo 2 (PC)] */ + /* some PC games do this [Halo 2 (PC)] (possibly bad extractor? 'Gravemind Tool') */ if (riff_size + 0x04 == file_size && read_16bitLE(0x14,streamFile)==0x0069) riff_size -= 0x04; - /* check for truncated RIFF */ - if (file_size < riff_size+0x08) goto fail; + if (file_size < riff_size+0x08) + goto fail; /* read through chunks to verify format and find metadata */ { @@ -371,16 +374,16 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { break; case 0x736D706C: /* "smpl" (RIFFMIDISample + MIDILoop chunk) */ - /* check loop count/loop info (most common) *///todo double check values + /* check loop count/loop info (most common) */ /* 0x00: manufacturer id, 0x04: product id, 0x08: sample period, 0x0c: unity node, * 0x10: pitch fraction, 0x14: SMPTE format, 0x18: SMPTE offset, 0x1c: loop count, 0x20: sampler data */ - if (read_32bitLE(current_chunk+0x08+0x1c, streamFile)==1) { + if (read_32bitLE(current_chunk+0x08+0x1c, streamFile) == 1) { /* handle only one loop (could contain N MIDILoop) */ /* 0x24: cue point id, 0x28: type (0=forward, 1=alternating, 2=backward) * 0x2c: start, 0x30: end, 0x34: fraction, 0x38: play count */ - if (read_32bitLE(current_chunk+0x08+0x28, streamFile)==0) { + if (read_32bitLE(current_chunk+0x08+0x28, streamFile) == 0) { /* loop forward */ loop_flag = 1; loop_start_smpl = read_32bitLE(current_chunk+0x08+0x2c, streamFile); - loop_end_smpl = read_32bitLE(current_chunk+0x08+0x30, streamFile); + loop_end_smpl = read_32bitLE(current_chunk+0x08+0x30, streamFile) + 1; /* must add 1 as per spec (ok for standard WAV/AT3/AT9) */ } } break; @@ -393,10 +396,10 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { && read_32bitLE(current_chunk+0x08+0x10, streamFile) > 0 && read_32bitLE(current_chunk+0x08+0x14, streamFile) == 0x10) { /* 0x14: size, 0x18: loop type (0=forward, 1=release), 0x1c: loop start, 0x20: loop length */ - if (read_32bitLE(current_chunk+0x08+0x18, streamFile)==0) { + if (read_32bitLE(current_chunk+0x08+0x18, streamFile) == 0) { /* loop forward */ loop_flag = 1; loop_start_wsmp = read_32bitLE(current_chunk+0x08+0x1c, streamFile); - loop_end_wsmp = read_32bitLE(current_chunk+0x08+0x20, streamFile); + loop_end_wsmp = read_32bitLE(current_chunk+0x08+0x20, streamFile); /* must not add 1 as per spec */ loop_end_wsmp += loop_start_wsmp; } } @@ -655,6 +658,10 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { else if (loop_start_smpl >= 0) { vgmstream->loop_start_sample = loop_start_smpl; vgmstream->loop_end_sample = loop_end_smpl; + /* end must add +1, but check in case of faulty tools */ + if (vgmstream->loop_end_sample - 1 == vgmstream->num_samples) + vgmstream->loop_end_sample--; + vgmstream->meta_type = meta_RIFF_WAVE_smpl; } else if (loop_start_wsmp >= 0) { @@ -754,7 +761,7 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) { if (read_32bitBE(current_chunk+0x2c+4, streamFile)==0) { loop_flag = 1; loop_start_offset = read_32bitBE(current_chunk+0x2c+8, streamFile); - loop_end_offset = read_32bitBE(current_chunk+0x2c+0xc,streamFile); + loop_end_offset = read_32bitBE(current_chunk+0x2c+0xc,streamFile) + 1; } } break; @@ -803,6 +810,10 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) { if (loop_start_offset >= 0) { vgmstream->loop_start_sample = loop_start_offset; vgmstream->loop_end_sample = loop_end_offset; + /* end must add +1, but check in case of faulty tools */ + if (vgmstream->loop_end_sample - 1 == vgmstream->num_samples) + vgmstream->loop_end_sample--; + vgmstream->meta_type = meta_RIFX_WAVE_smpl; } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c index 08fd535ba..e40b3b746 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c @@ -1025,13 +1025,15 @@ VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile) { datasize = read_32bitBE(0x808, streamFile); bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, datasize); if (!ffmpeg_data) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + /* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */ + //xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0); + ffmpeg_set_skip_samples(ffmpeg_data, 512+64); } #else goto fail; @@ -1053,13 +1055,15 @@ VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile) { datasize = read_32bitBE(0x808, streamFile); bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, datasize); if (!ffmpeg_data) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + /* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */ + //xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0); + ffmpeg_set_skip_samples(ffmpeg_data, 512+64); } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sdt.c b/Frameworks/vgmstream/vgmstream/src/meta/sdt.c index 6b3f4011f..9e7497e7a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sdt.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sdt.c @@ -1,80 +1,58 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* SDT (Baldur's Gate - Dark Alliance) */ +/* .sdt - from High Voltage games? [Baldur's Gate - Dark Alliance (GC)] */ VGMSTREAM * init_vgmstream_sdt(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + size_t data_size; + int loop_flag, channel_count; - int loop_flag; - int channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("sdt",filename_extension(filename))) goto fail; - -#if 0 - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x53565300) /* "SVS\0" */ + /* checks */ + if (!check_extensions(streamFile, "sdt")) goto fail; -#endif - loop_flag = (read_32bitBE(0x04,streamFile)!=0); - channel_count = 2; - - /* build the VGMSTREAM */ + channel_count = read_32bitBE(0x00,streamFile); /* assumed */ + loop_flag = (read_32bitBE(0x04,streamFile) != 0); + start_offset = 0xA0; + data_size = get_streamfile_size(streamFile) - start_offset; + + if (channel_count != 2) + goto fail; /* only seen this */ + if (read_32bitBE(0x08,streamFile) != read_32bitBE(0x08,streamFile)) + goto fail; /* sample rate agreement between channels */ + if (read_32bitBE(0x98,streamFile) != 0x8000) + goto fail; /* expected interleave */ + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0xA0; - vgmstream->channels = channel_count; /*read_32bitBE(0x00,streamFile);*/ + vgmstream->meta_type = meta_SDT; vgmstream->sample_rate = read_32bitBE(0x08,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitBE(0x14,streamFile)/8*14/channel_count; + vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count); /* maybe at @0x14 - 2? */ if (loop_flag) { - vgmstream->loop_start_sample = 0; /* (read_32bitLE(0x08,streamFile)-1)*28; */ - vgmstream->loop_end_sample = read_32bitBE(0x14,streamFile)/8*14/channel_count; + vgmstream->loop_start_sample = 0; /* maybe @0x08? */ + vgmstream->loop_end_sample = vgmstream->num_samples; /* maybe @0x10? */ } + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + if (vgmstream->interleave_block_size) + vgmstream->interleave_last_block_size = + (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x8000; - vgmstream->meta_type = meta_SDT; + dsp_read_coefs_be(vgmstream,streamFile, 0x3c,0x2E); + dsp_read_hist_be(vgmstream, streamFile, 0x60,0x2E); -if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); - } - if (vgmstream->channels) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x6A+i*2,streamFile); - } - } -} - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/seg.c b/Frameworks/vgmstream/vgmstream/src/meta/seg.c index 7aa3cbea5..9a09210af 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/seg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/seg.c @@ -1,94 +1,112 @@ #include "meta.h" #include "../coding/coding.h" - -/* SEG - found in Eragon */ +/* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag; - int channel_count; - coding_t coding; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("seg",filename_extension(filename))) goto fail; + int loop_flag, channel_count; + size_t data_size; + uint32_t codec; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x73656700) /* "seg\0" */ + /* checks */ + if (!check_extensions(streamFile, "seg")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x73656700) /* "seg\0" */ goto fail; - if (read_32bitBE(0x04,streamFile) == 0x70733200) /* "ps2\0" */ - { - coding = coding_PSX; - } - else if (read_32bitBE(0x04,streamFile) == 0x78627800) /* "xbx\0" */ - { - coding = coding_XBOX_IMA; - } - else goto fail; - loop_flag = 0; - channel_count = read_32bitLE(0x24,streamFile); - - /* build the VGMSTREAM */ + codec = read_32bitBE(0x04,streamFile); + /* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */ + if (guess_endianness32bit(0x08,streamFile)) { + read_32bit = read_32bitBE; + } else { + read_32bit = read_32bitLE; + } + /* 0x0c: file size */ + data_size = read_32bit(0x10, streamFile); /* including interleave padding */ + /* 0x14: null */ + + loop_flag = read_32bit(0x20,streamFile); /* rare */ + channel_count = read_32bit(0x24,streamFile); + /* 0x28: extradata 1 entries (0x08 per entry, unknown) */ + /* 0x2c: extradata 1 offset */ + /* 0x30: extradata 2 entries (0x10 or 0x14 per entry, seek/hist table?) */ + /* 0x34: extradata 2 offset */ + + start_offset = 0x4000; + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x4000; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x18,streamFile); - vgmstream->coding_type = coding; - + vgmstream->meta_type = meta_SEG; + vgmstream->sample_rate = read_32bit(0x18,streamFile); + vgmstream->num_samples = read_32bit(0x1c,streamFile); if (loop_flag) { vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; } + read_string(vgmstream->stream_name,0x20+1, 0x38,streamFile); - vgmstream->interleave_block_size = 0; + switch(codec) { + case 0x70733200: /* "ps2\0" */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; + break; - if (coding_PSX == coding) - { - vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)*28/16/channel_count; - vgmstream->meta_type = meta_PS2_SEG; + case 0x78627800: /* "xbx\0" */ + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + break; - if (channel_count == 1) { - vgmstream->layout_type = layout_none; - } else if (channel_count == 2) { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2000; - } - } - else if (coding_XBOX_IMA == coding) - { - vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x0C,streamFile)-start_offset, channel_count); - vgmstream->meta_type = meta_XBOX_SEG; - vgmstream->layout_type = layout_none; - } - else goto fail; + case 0x77696900: /* "wii\0" */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; + /* standard dsp header at start_offset */ + dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c, vgmstream->interleave_block_size); + dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, vgmstream->interleave_block_size); + //todo first_interleave: 0x2000 - 60 + break; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; + case 0x70635F00: /* "pc_\0" */ + vgmstream->coding_type = coding_IMA; + vgmstream->layout_type = layout_none; + break; +#ifdef VGM_USE_FFMPEG + case 0x78623300: { /* "xb3\0" */ + uint8_t buf[0x100]; + int bytes, block_size, block_count; + + block_size = 0x4000; + block_count = data_size / block_size + (data_size % block_size ? 1 : 0); + + bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok */ + break; } +#endif + + default: + goto fail; } + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sgxd.c b/Frameworks/vgmstream/vgmstream/src/meta/sgxd.c index 9c43ecfef..1e4454631 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sgxd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sgxd.c @@ -111,11 +111,6 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) { if (name_offset) read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader); - /* needs -1 to match RIFF AT3's loop chunk - * (maybe SGXD = "loop before this sample" rather than "loop after this sample" as expected by vgmstream) */ - if (vgmstream->loop_end_sample > 0) - vgmstream->loop_end_sample -= 1; - switch (type) { case 0x03: /* PS-ADPCM [Genji (PS3), Ape Escape Move (PS3)]*/ vgmstream->coding_type = coding_PSX; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sli.c b/Frameworks/vgmstream/vgmstream/src/meta/sli.c index f4ed50242..2ecf5427e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sli.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sli.c @@ -2,7 +2,7 @@ #include -/* .sli - loop points associated with a similarly named .ogg [Fate/Stay Night (PC), World End Economica (PC)]*/ +/* .sli+ogg/opus - KiriKiri engine / WaveLoopManager loop points loader [Fate/Stay Night (PC), World End Economica (PC)] */ VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; STREAMFILE * streamData = NULL; @@ -14,23 +14,42 @@ VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE *streamFile) { goto fail; { - /* try with file.ogg.sli=header and file.ogg=data */ + /* try with file.ogg/opus.sli=header and file.ogg/opus=data */ char basename[PATH_LIMIT]; get_streamfile_basename(streamFile,basename,PATH_LIMIT); streamData = open_streamfile_by_filename(streamFile, basename); if (!streamData) goto fail; - - if (!check_extensions(streamData, "ogg")) - goto fail; } -#ifdef VGM_USE_VORBIS + /* let the real initer do the parsing */ - vgmstream = init_vgmstream_ogg_vorbis(streamData); - if (!vgmstream) goto fail; + if (check_extensions(streamData, "ogg")) { /* Fate/Stay Night (PC) */ +#ifdef VGM_USE_VORBIS + vgmstream = init_vgmstream_ogg_vorbis(streamData); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_OGG_SLI; #else goto fail; #endif + } + else if (check_extensions(streamData, "opus")) { /* Sabbat of the Witch (PC) */ +#ifdef VGM_USE_FFMPEG + vgmstream = init_vgmstream_ffmpeg(streamData); + if (!vgmstream) goto fail; + + /* FFmpeg's Opus encoder delay is borked but no need to fix: + * somehow sli+opus use 0 in the OpusHead (to simplify looping?) */ + + vgmstream->meta_type = meta_OPUS_SLI; +#else + goto fail; +#endif + } + else { + goto fail; + } + /* find loop text */ { @@ -77,13 +96,11 @@ VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE *streamFile) { } } - if (loop_start != -1 && loop_length != -1) { + if (loop_start != -1 && loop_length != -1) { /* v1 */ vgmstream_force_loop(vgmstream,1,loop_start, loop_start+loop_length); - vgmstream->meta_type = meta_OGG_SLI; } - else if (loop_from != -1 && loop_to != -1) { + else if (loop_from != -1 && loop_to != -1) { /* v2 */ vgmstream_force_loop(vgmstream,1,loop_to, loop_from); - vgmstream->meta_type = meta_OGG_SLI2; } else { goto fail; /* if there's no loop points the .sli wasn't valid */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c b/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c index ba0280fc7..d75101bac 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c @@ -1,9 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_sps_streamfile(STREAMFILE *streamfile, off_t subfile_offset, size_t subfile_size, char* extension); - -/* .SPS - Nippon Ichi's RIFF AT3 wrapper [ClaDun (PSP)] */ +/* .SPS - Nippon Ichi wrapper [ClaDun (PSP)] */ VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; STREAMFILE *temp_streamFile = NULL; @@ -16,17 +14,17 @@ VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile) { goto fail; /* mini header */ - type = read_32bitLE(0x00,streamFile); //todo channels? all known VAG are mono and AT3 stereo + type = read_32bitLE(0x00,streamFile); subfile_size = read_32bitLE(0x04,streamFile); sample_rate = (uint16_t)read_16bitLE(0x08,streamFile); - /* 0x0a/0b: stereo+loop flags? */ + /* 0x0a: flag? */ //num_samples = read_32bitLE(0x0c,streamFile); subfile_offset = 0x10; /* init the VGMSTREAM */ switch(type) { case 1: /* .vag */ - temp_streamFile = setup_sps_streamfile(streamFile, subfile_offset, subfile_size, "vag"); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, "vag"); if (!temp_streamFile) goto fail; vgmstream = init_vgmstream_vag(temp_streamFile); @@ -34,7 +32,7 @@ VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile) { break; case 2: /* .at3 */ - temp_streamFile = setup_sps_streamfile(streamFile, subfile_offset, subfile_size, "at3"); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, "at3"); if (!temp_streamFile) goto fail; vgmstream = init_vgmstream_riff(temp_streamFile); @@ -54,26 +52,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_sps_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, char* extension) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,extension); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c index 900a32c8f..3522a3c1f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -334,23 +334,23 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */ - ffmpeg_codec_data *ffmpeg_data = NULL; - uint8_t buf[200]; - int32_t bytes; + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[200]; + int32_t bytes; - /* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */ - bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1); - if (bytes <= 0) goto fail; + /* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */ + bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1); + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; + vgmstream->num_samples = ffmpeg_data->totalSamples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; - vgmstream->num_samples = ffmpeg_data->totalSamples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */ break; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/svs.c b/Frameworks/vgmstream/vgmstream/src/meta/svs.c index f78b6f0c2..92b366f04 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/svs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/svs.c @@ -1,69 +1,54 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* SVS (from Unlimited Saga) */ -/* probably Square Vag Stream */ + +/* SVS - SeqVagStream from Square games [Unlimited Saga (PS2) music] */ VGMSTREAM * init_vgmstream_svs(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int channel_count, loop_flag, pitch; - int loop_flag = 0; - int channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("svs",filename_extension(filename))) goto fail; - - /* check header */ + /* checks */ + /* .svs: header id (probably ok like The Bouncer's .vs) */ + if (!check_extensions(streamFile, "svs")) + goto fail; if (read_32bitBE(0x00,streamFile) != 0x53565300) /* "SVS\0" */ goto fail; - loop_flag = (read_32bitLE(0x08,streamFile)!=0); - /* 63.SVS has start and end on the same sample, which crashes stuff */ - if (read_32bitLE(0x08,streamFile)==read_32bitLE(0x0c,streamFile)) - loop_flag = 0; + /* 0x04: flags (1=stereo?, 2=loop) */ + pitch = read_32bitLE(0x10,streamFile); /* usually 0x1000 = 48000 */ + /* 0x14: volume? */ + /* 0x18: file id (may be null) */ + /* 0x1c: null */ + + loop_flag = (read_32bitLE(0x08,streamFile) > 0); /* loop start frame, min is 1 */ channel_count = 2; - - /* build the VGMSTREAM */ + start_offset = 0x20; + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x40; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-0x40)*28/16/channel_count; + vgmstream->meta_type = meta_SVS; + vgmstream->sample_rate = round10((48000 * pitch) / 4096); /* music = ~44100, ambience = 48000 (rounding makes more sense but not sure) */ + vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitLE(0x08,streamFile)-1)*28; - vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-1)*28; + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile) * 28; /* frame count (0x10*ch) */ + vgmstream->loop_end_sample = read_32bitLE(0x0c,streamFile) * 28; /* frame count, (not exact num_samples when no loop) */ + /* start/end on the same frame rarely happens too (ex. file_id 63 SVS), perhaps loop should be +1 */ } + vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_PS2_SVS; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sxd.c b/Frameworks/vgmstream/vgmstream/src/meta/sxd.c index 1e0420dfb..302b2fb84 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sxd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sxd.c @@ -10,7 +10,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { size_t chunk_size, stream_size = 0; int is_dual = 0, is_external = 0; - int loop_flag, channels, codec, location; + int loop_flag, channels, codec, flags; int sample_rate, num_samples, loop_start_sample, loop_end_sample; uint32_t at9_config_data = 0; int total_subsongs, target_subsong = streamFile->stream_index; @@ -35,12 +35,15 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { /* typical chunks: NAME, WAVE and many control chunks (SXDs don't need to contain any sound data) */ - if (!find_chunk_le(streamHeader, 0x57415645,first_offset,0, &chunk_offset,&chunk_size)) goto fail; /* "WAVE" */ + if (!find_chunk_le(streamHeader, 0x57415645,first_offset,0, &chunk_offset,&chunk_size)) /* "WAVE" */ + goto fail; /* check multi-streams (usually only in SFX containers) */ total_subsongs = read_32bitLE(chunk_offset+0x04,streamHeader); if (target_subsong == 0) target_subsong = 1; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + // todo rarely a WAVE subsong may point to a repeated data offset, with different tags only + /* read stream header */ { @@ -50,9 +53,10 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { table_offset = chunk_offset + 0x08 + 4*(target_subsong-1); header_offset = table_offset + read_32bitLE(table_offset,streamHeader); - location = read_32bitLE(header_offset+0x00,streamHeader); + flags = read_32bitLE(header_offset+0x00,streamHeader); codec = read_8bit (header_offset+0x04,streamHeader); channels = read_8bit (header_offset+0x05,streamHeader); + /* 0x06(2): unknown, rarely 0xFF */ sample_rate = read_32bitLE(header_offset+0x08,streamHeader); /* 0x0c(4): unknown size? (0x4000/0x3999/0x3333/etc, not related to extra data) */ /* 0x10(4): ? + volume? + pan? (can be 0 for music) */ @@ -62,14 +66,32 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { stream_size = read_32bitLE(header_offset+0x20,streamHeader); stream_offset = read_32bitLE(header_offset+0x24,streamHeader); - /* Extra data, variable sized and uses some kind of TLVs (HEVAG's is optional and much smaller). - * One tag seems to add a small part of the ATRAC9 data, for RAM preloding I guess. */ + loop_flag = loop_start_sample != -1 && loop_end_sample != -1; + + /* known flag combos: + * 0x00: Chaos Rings 2 sfx (RAM + no tags) + * 0x01: common (RAM + tags) + * 0x02: Chaos Rings 3 sfx (stream + no tags) + * 0x03: common (stream + tags) + * 0x05: Gravity Rush 2 sfx (RAM + tags) */ + //has_tags = flags & 1; + is_external = flags & 2; + //unknown = flags & 4; /* no apparent differences with/without it? */ + + /* flag 1 signals TLV-like extra data. Format appears to be 0x00(1)=tag?, 0x01(1)=extra size*32b?, 0x02(2)=config? + * but not always (ex. size=0x07 but actually=0), perhaps only some bits are used or varies with tag, or are subflags. + * A tag may appear with or without extra data (even 0x0a), 0x01/03/04/06 are common at the beginnig (imply number of tags?), + * 0x64/7F are common at the end (but not always), 0x0A=ATRAC9 config, 0x0B/0C appear with RAM preloading data + * (most variable in Soul Sacrifice; total TLVs size isn't plainly found in the SXD header AFAIK). */ + + /* manually try to find ATRAC9 tag */ if (codec == 0x42) { off_t extra_offset = header_offset+0x28; off_t max_offset = chunk_offset + chunk_size; - /* manually try to find certain tag, no idea about the actual format - * (most variable in Soul Sacrifice; extra data size isn't found in the header AFAIK) */ + if (!(flags & 1)) + goto fail; + while (extra_offset < max_offset) { uint32_t tag = read_32bitBE(extra_offset, streamHeader); if (tag == 0x0A010000 || tag == 0x0A010600) { @@ -83,26 +105,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { goto fail; } - loop_flag = loop_start_sample != -1 && loop_end_sample != -1; - - /* usually sxd=header+data and sxd1=header + sxd2=data, but rarely sxd1 contain data [The Last Guardian (PS4)] */ - switch(location) { /* might not be exact but seems the only difference in TLG */ - case 0x00: /* some Chaos Rings 2 sfx */ - case 0x01: /* most common */ - case 0x05: /* some Gradity Rush 2 sfx */ - is_external = 0; /* RAM asset? */ - break; - - case 0x02: /* some Chaos Rings 3 sfx */ - case 0x03: /* most common */ - is_external = 1; /* stream asset? */ - break; - - default: - VGM_LOG("SXD: unknown location 0x%x\n", location); - goto fail; - } - + /* usually .sxd=header+data and .sxd1=header + .sxd2=data, but rarely sxd1 may contain data [The Last Guardian (PS4)] */ if (is_external) { start_offset = stream_offset; /* absolute if external */ } else { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c b/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c index 2d3c6a97b..bbc78e46e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c @@ -108,13 +108,17 @@ VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile) { datasize = dataSize; bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); if ( !ffmpeg_data ) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, datasize, 0, 1,1); + if (loop_flag) { /* reapply adjusted samples */ + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index cebdfea39..4dbb72a75 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -30,16 +30,22 @@ typedef enum { XMA2 = 21, /* raw XMA2 */ FFMPEG = 22, /* any headered FFmpeg format */ AC3 = 23, /* AC3/SPDIF */ + PCFX = 24, /* PC-FX ADPCM */ } txth_type; typedef struct { txth_type codec; uint32_t codec_mode; - uint32_t interleave; + + uint32_t value_mul; + uint32_t value_div; + uint32_t value_add; + uint32_t value_sub; uint32_t id_value; uint32_t id_offset; + uint32_t interleave; uint32_t channels; uint32_t sample_rate; @@ -66,12 +72,33 @@ typedef struct { int num_samples_data_size; + int target_subsong; + uint32_t subsong_count; + uint32_t subsong_offset; + + uint32_t name_offset_set; + uint32_t name_offset; + uint32_t name_size; + + /* original STREAMFILE and its type (may be an unsupported "base" file or a .txth) */ + STREAMFILE *streamFile; + int streamfile_is_txth; + + /* configurable STREAMFILEs and if we opened it (thus must close it later) */ + STREAMFILE *streamText; + STREAMFILE *streamHead; + STREAMFILE *streamBody; + int streamtext_opened; + int streamhead_opened; + int streambody_opened; + } txth_header; + static STREAMFILE * open_txth(STREAMFILE * streamFile); -static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth); -static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth, const char * key, const char * val); -static int parse_num(STREAMFILE * streamFile, const char * val, uint32_t * out_value); +static int parse_txth(txth_header * txth); +static int parse_keyval(STREAMFILE * streamFile, txth_header * txth, const char * key, char * val); +static int parse_num(STREAMFILE * streamFile, txth_header * txth, const char * val, uint32_t * out_value); static int get_bytes_to_samples(txth_header * txth, uint32_t bytes); @@ -79,23 +106,42 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes); * Similar to GENH, but with a single separate .txth file in the dir and text-based. */ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamText = NULL; txth_header txth = {0}; coding_t coding; int i, j; - /* reject .txth as the CLI can open and decode with itself */ - if (check_extensions(streamFile, "txth")) - goto fail; + /* accept .txth (should set body_file or will fail later) */ + if (check_extensions(streamFile, "txth")) { + txth.streamFile = streamFile; + txth.streamfile_is_txth = 1; - /* no need for ID or ext checks -- if a .TXTH exists all is good - * (player still needs to accept the streamfile's ext, so at worst rename to .vgmstream) */ - streamText = open_txth(streamFile); - if (!streamText) goto fail; + txth.streamText = streamFile; + txth.streamHead = NULL; + txth.streamBody = NULL; + txth.streamtext_opened = 0; + txth.streamhead_opened = 0; + txth.streambody_opened = 0; + } + else { + /* accept base file (no need for ID or ext checks --if a companion .TXTH exists all is good) + * (player still needs to accept the streamfile's ext, so at worst rename to .vgmstream) */ + STREAMFILE * streamText = open_txth(streamFile); + if (!streamText) goto fail; + + txth.streamFile = streamFile; + txth.streamfile_is_txth = 0; + + txth.streamText = streamText; + txth.streamHead = streamFile; + txth.streamBody = streamFile; + txth.streamtext_opened = 1; + txth.streamhead_opened = 0; + txth.streambody_opened = 0; + } /* process the text file */ - if (!parse_txth(streamFile, streamText, &txth)) + if (!parse_txth(&txth)) goto fail; @@ -129,14 +175,15 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { case AC3: case FFMPEG: coding = coding_FFmpeg; break; #endif + case PCFX: coding = coding_PCFX; break; default: goto fail; } + /* try to autodetect PS-ADPCM loop data */ if (txth.loop_flag_auto && coding == coding_PSX) { - size_t data_size = get_streamfile_size(streamFile) - txth.start_offset; - txth.loop_flag = ps_find_loop_offsets(streamFile, txth.start_offset, data_size, txth.channels, txth.interleave, + txth.loop_flag = ps_find_loop_offsets(txth.streamBody, txth.start_offset, txth.data_size, txth.channels, txth.interleave, (int32_t*)&txth.loop_start_sample, (int32_t*)&txth.loop_end_sample); } @@ -149,6 +196,12 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { vgmstream->num_samples = txth.num_samples; vgmstream->loop_start_sample = txth.loop_start_sample; vgmstream->loop_end_sample = txth.loop_end_sample; + vgmstream->num_streams = txth.subsong_count; + vgmstream->stream_size = txth.data_size; + if (txth.name_offset_set) { + size_t name_size = txth.name_size ? txth.name_size + 1 : STREAM_NAME_SIZE; + read_string(vgmstream->stream_name,name_size, txth.name_offset,txth.streamHead); + } /* codec specific (taken from GENH with minimal changes) */ switch (coding) { @@ -207,8 +260,15 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { vgmstream->ch[i].adpcm_step_index = 0x7f; } } - break; + + case coding_PCFX: + vgmstream->interleave_block_size = txth.interleave; + vgmstream->layout_type = layout_interleave; + if (txth.codec_mode >= 0 && txth.codec_mode <= 3) + vgmstream->codec_config = txth.codec_mode; + break; + case coding_MS_IMA: if (!txth.interleave) goto fail; /* creates garbage */ @@ -260,17 +320,17 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { int16_t (*read_16bit)(off_t , STREAMFILE*) = txth.coef_big_endian ? read_16bitBE : read_16bitLE; /* normal/split coefs */ - if (txth.coef_mode == 0) { - for (j=0;j<16;j++) { - vgmstream->ch[i].adpcm_coef[j] = read_16bit(txth.coef_offset + i*txth.coef_spacing + j*2,streamFile); + if (txth.coef_mode == 0) { /* normal mode */ + for (j = 0; j < 16; j++) { + vgmstream->ch[i].adpcm_coef[j] = read_16bit(txth.coef_offset + i*txth.coef_spacing + j*2, txth.streamHead); } } - else { + else { /* split coefs */ goto fail; //IDK what is this /* - for (j=0;j<8;j++) { - vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(coef[i]+j*2,streamFile); - vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(coef_splitted[i]+j*2,streamFile); + for (j = 0; j < 8; j++) { + vgmstream->ch[i].adpcm_coef[j*2] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, txth.streamHead); + vgmstream->ch[i].adpcm_coef[j*2+1] = read_16bit(genh.coef_split_offset + i*genh.coef_split_spacing + j*2, txth.streamHead); } */ } @@ -280,7 +340,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { #ifdef VGM_USE_MPEG case coding_MPEG_layer3: vgmstream->layout_type = layout_none; - vgmstream->codec_data = init_mpeg(streamFile, txth.start_offset, &coding, vgmstream->channels); + vgmstream->codec_data = init_mpeg(txth.streamBody, txth.start_offset, &coding, vgmstream->channels); if (!vgmstream->codec_data) goto fail; break; @@ -291,7 +351,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { if (txth.codec == FFMPEG || txth.codec == AC3) { /* default FFmpeg */ - ffmpeg_data = init_ffmpeg_offset(streamFile, txth.start_offset,txth.data_size); + ffmpeg_data = init_ffmpeg_offset(txth.streamBody, txth.start_offset,txth.data_size); if ( !ffmpeg_data ) goto fail; if (vgmstream->num_samples == 0) @@ -335,17 +395,17 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { else { goto fail; } - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, txth.start_offset,txth.data_size); + ffmpeg_data = init_ffmpeg_header_offset(txth.streamBody, buf,bytes, txth.start_offset,txth.data_size); if ( !ffmpeg_data ) goto fail; } vgmstream->codec_data = ffmpeg_data; vgmstream->layout_type = layout_none; - /* force encoder delay */ - if (txth.skip_samples_set) { + if (txth.codec == XMA1 || txth.codec == XMA2) { + xma_fix_raw_samples(vgmstream, txth.streamBody, txth.start_offset,txth.data_size, 0, 0,0); + } else if (txth.skip_samples_set) { /* force encoder delay */ ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples); } @@ -373,14 +433,13 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { msd.loop_end_subframe = txth.loop_adjust >> 4; /* upper 4b: subframe where the loop ends, 0..3 */ } - xma_get_samples(&msd, streamFile); + xma_get_samples(&msd, txth.streamBody); vgmstream->num_samples = msd.num_samples; if (txth.sample_type==1) { vgmstream->loop_start_sample = msd.loop_start_sample; vgmstream->loop_end_sample = msd.loop_end_sample; } - //skip_samples = msd.skip_samples; //todo add skip samples } #endif @@ -389,14 +448,18 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { vgmstream->allow_dual_stereo = 1; - if ( !vgmstream_open_stream(vgmstream,streamFile,txth.start_offset) ) + if ( !vgmstream_open_stream(vgmstream,txth.streamBody,txth.start_offset) ) goto fail; - if (streamText) close_streamfile(streamText); + if (txth.streamtext_opened) close_streamfile(txth.streamText); + if (txth.streamhead_opened) close_streamfile(txth.streamHead); + if (txth.streambody_opened) close_streamfile(txth.streamBody); return vgmstream; fail: - if (streamText) close_streamfile(streamText); + if (txth.streamtext_opened) close_streamfile(txth.streamText); + if (txth.streamhead_opened) close_streamfile(txth.streamHead); + if (txth.streambody_opened) close_streamfile(txth.streamBody); close_vgmstream(vgmstream); return NULL; } @@ -434,15 +497,25 @@ static STREAMFILE * open_txth(STREAMFILE * streamFile) { /* Simple text parser of "key = value" lines. * The code is meh and error handling not exactly the best. */ -static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth) { +static int parse_txth(txth_header * txth) { off_t txt_offset = 0x00; - off_t file_size = get_streamfile_size(streamText); + off_t file_size = get_streamfile_size(txth->streamText); + + /* setup txth defaults */ + if (txth->streamBody) + txth->data_size = get_streamfile_size(txth->streamBody); + txth->target_subsong = txth->streamFile->stream_index; + if (txth->target_subsong == 0) txth->target_subsong = 1; - txth->data_size = get_streamfile_size(streamFile); /* for later use */ /* skip BOM if needed */ - if ((uint16_t)read_16bitLE(0x00, streamText) == 0xFFFE || (uint16_t)read_16bitLE(0x00, streamText) == 0xFEFF) + if ((uint16_t)read_16bitLE(0x00, txth->streamText) == 0xFFFE || + (uint16_t)read_16bitLE(0x00, txth->streamText) == 0xFEFF) { txt_offset = 0x02; + } + else if (((uint32_t)read_32bitBE(0x00, txth->streamText) & 0xFFFFFF00) == 0xEFBBBF00) { + txt_offset = 0x03; + } /* read lines */ while (txt_offset < file_size) { @@ -450,8 +523,9 @@ static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_hea char key[TXT_LINE_MAX] = {0}, val[TXT_LINE_MAX] = {0}; /* at least as big as a line to avoid overflows (I hope) */ int ok, bytes_read, line_done; - bytes_read = get_streamfile_text_line(TXT_LINE_MAX,line, txt_offset,streamText, &line_done); + bytes_read = get_streamfile_text_line(TXT_LINE_MAX,line, txt_offset,txth->streamText, &line_done); if (!line_done) goto fail; + //;VGM_LOG("TXTH: line=%s\n",line); txt_offset += bytes_read; @@ -460,49 +534,79 @@ static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_hea if (ok != 2) /* ignore line if no key=val (comment or garbage) */ continue; - if (!parse_keyval(streamFile, streamText, txth, key, val)) /* read key/val */ + if (!parse_keyval(txth->streamFile, txth, key, val)) /* read key/val */ goto fail; } if (!txth->loop_flag_set) txth->loop_flag = txth->loop_end_sample && txth->loop_end_sample != 0xFFFFFFFF; + if (!txth->streamBody) + goto fail; + + if (txth->data_size > get_streamfile_size(txth->streamBody) - txth->start_offset || txth->data_size == 0) + txth->data_size = get_streamfile_size(txth->streamBody) - txth->start_offset; + return 1; fail: return 0; } -static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth, const char * key, const char * val) { +static int parse_keyval(STREAMFILE * streamFile_, txth_header * txth, const char * key, char * val) { + //;VGM_LOG("TXTH: key=%s, val=%s\n", key, val); if (0==strcmp(key,"codec")) { - if (0==strcmp(val,"PSX")) txth->codec = PSX; - else if (0==strcmp(val,"XBOX")) txth->codec = XBOX; - else if (0==strcmp(val,"NGC_DTK")) txth->codec = NGC_DTK; - else if (0==strcmp(val,"PCM16BE")) txth->codec = PCM16BE; - else if (0==strcmp(val,"PCM16LE")) txth->codec = PCM16LE; - else if (0==strcmp(val,"PCM8")) txth->codec = PCM8; - else if (0==strcmp(val,"SDX2")) txth->codec = SDX2; - else if (0==strcmp(val,"DVI_IMA")) txth->codec = DVI_IMA; - else if (0==strcmp(val,"MPEG")) txth->codec = MPEG; - else if (0==strcmp(val,"IMA")) txth->codec = IMA; - else if (0==strcmp(val,"AICA")) txth->codec = AICA; - else if (0==strcmp(val,"MSADPCM")) txth->codec = MSADPCM; - else if (0==strcmp(val,"NGC_DSP")) txth->codec = NGC_DSP; - else if (0==strcmp(val,"PCM8_U_int")) txth->codec = PCM8_U_int; - else if (0==strcmp(val,"PSX_bf")) txth->codec = PSX_bf; - else if (0==strcmp(val,"MS_IMA")) txth->codec = MS_IMA; - else if (0==strcmp(val,"PCM8_U")) txth->codec = PCM8_U; - else if (0==strcmp(val,"APPLE_IMA4")) txth->codec = APPLE_IMA4; - else if (0==strcmp(val,"ATRAC3")) txth->codec = ATRAC3; - else if (0==strcmp(val,"ATRAC3PLUS")) txth->codec = ATRAC3PLUS; - else if (0==strcmp(val,"XMA1")) txth->codec = XMA1; - else if (0==strcmp(val,"XMA2")) txth->codec = XMA2; - else if (0==strcmp(val,"FFMPEG")) txth->codec = FFMPEG; - else if (0==strcmp(val,"AC3")) txth->codec = AC3; + if (0==strcmp(val,"PSX")) txth->codec = PSX; + else if (0==strcmp(val,"XBOX")) txth->codec = XBOX; + else if (0==strcmp(val,"NGC_DTK")) txth->codec = NGC_DTK; + else if (0==strcmp(val,"DTK")) txth->codec = NGC_DTK; + else if (0==strcmp(val,"PCM16BE")) txth->codec = PCM16BE; + else if (0==strcmp(val,"PCM16LE")) txth->codec = PCM16LE; + else if (0==strcmp(val,"PCM8")) txth->codec = PCM8; + else if (0==strcmp(val,"SDX2")) txth->codec = SDX2; + else if (0==strcmp(val,"DVI_IMA")) txth->codec = DVI_IMA; + else if (0==strcmp(val,"MPEG")) txth->codec = MPEG; + else if (0==strcmp(val,"IMA")) txth->codec = IMA; + else if (0==strcmp(val,"AICA")) txth->codec = AICA; + else if (0==strcmp(val,"MSADPCM")) txth->codec = MSADPCM; + else if (0==strcmp(val,"NGC_DSP")) txth->codec = NGC_DSP; + else if (0==strcmp(val,"DSP")) txth->codec = NGC_DSP; + else if (0==strcmp(val,"PCM8_U_int")) txth->codec = PCM8_U_int; + else if (0==strcmp(val,"PSX_bf")) txth->codec = PSX_bf; + else if (0==strcmp(val,"MS_IMA")) txth->codec = MS_IMA; + else if (0==strcmp(val,"PCM8_U")) txth->codec = PCM8_U; + else if (0==strcmp(val,"APPLE_IMA4")) txth->codec = APPLE_IMA4; + else if (0==strcmp(val,"ATRAC3")) txth->codec = ATRAC3; + else if (0==strcmp(val,"ATRAC3PLUS")) txth->codec = ATRAC3PLUS; + else if (0==strcmp(val,"XMA1")) txth->codec = XMA1; + else if (0==strcmp(val,"XMA2")) txth->codec = XMA2; + else if (0==strcmp(val,"FFMPEG")) txth->codec = FFMPEG; + else if (0==strcmp(val,"AC3")) txth->codec = AC3; + else if (0==strcmp(val,"PCFX")) txth->codec = PCFX; else goto fail; } else if (0==strcmp(key,"codec_mode")) { - if (!parse_num(streamFile,val, &txth->codec_mode)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->codec_mode)) goto fail; + } + else if (0==strcmp(key,"value_mul") || 0==strcmp(key,"value_*")) { + if (!parse_num(txth->streamHead,txth,val, &txth->value_mul)) goto fail; + } + else if (0==strcmp(key,"value_div") || 0==strcmp(key,"value_/")) { + if (!parse_num(txth->streamHead,txth,val, &txth->value_div)) goto fail; + } + else if (0==strcmp(key,"value_add") || 0==strcmp(key,"value_+")) { + if (!parse_num(txth->streamHead,txth,val, &txth->value_add)) goto fail; + } + else if (0==strcmp(key,"value_sub") || 0==strcmp(key,"value_-")) { + if (!parse_num(txth->streamHead,txth,val, &txth->value_sub)) goto fail; + } + else if (0==strcmp(key,"id_value")) { + if (!parse_num(txth->streamHead,txth,val, &txth->id_value)) goto fail; + } + else if (0==strcmp(key,"id_offset")) { + if (!parse_num(txth->streamHead,txth,val, &txth->id_offset)) goto fail; + if (txth->id_value != txth->id_offset) /* evaluate current ID */ + goto fail; } else if (0==strcmp(key,"interleave")) { if (0==strcmp(val,"half_size")) { @@ -510,30 +614,24 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h txth->interleave = txth->data_size / txth->channels; } else { - if (!parse_num(streamFile,val, &txth->interleave)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->interleave)) goto fail; } } - else if (0==strcmp(key,"id_value")) { - if (!parse_num(streamFile,val, &txth->id_value)) goto fail; - } - else if (0==strcmp(key,"id_offset")) { - if (!parse_num(streamFile,val, &txth->id_offset)) goto fail; - if (txth->id_value != txth->id_offset) /* evaluate current ID */ - goto fail; - } else if (0==strcmp(key,"channels")) { - if (!parse_num(streamFile,val, &txth->channels)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->channels)) goto fail; } else if (0==strcmp(key,"sample_rate")) { - if (!parse_num(streamFile,val, &txth->sample_rate)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->sample_rate)) goto fail; } else if (0==strcmp(key,"start_offset")) { - if (!parse_num(streamFile,val, &txth->start_offset)) goto fail; - if (!txth->data_size_set) - txth->data_size = get_streamfile_size(streamFile) - txth->start_offset; /* re-evaluate */ + if (!parse_num(txth->streamHead,txth,val, &txth->start_offset)) goto fail; + if (!txth->data_size_set) { + txth->data_size = !txth->streamBody ? 0 : + get_streamfile_size(txth->streamBody) - txth->start_offset; /* re-evaluate */ + } } else if (0==strcmp(key,"data_size")) { - if (!parse_num(streamFile,val, &txth->data_size)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->data_size)) goto fail; txth->data_size_set = 1; } else if (0==strcmp(key,"sample_type")) { @@ -548,7 +646,7 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h txth->num_samples_data_size = 1; } else { - if (!parse_num(streamFile,val, &txth->num_samples)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->num_samples)) goto fail; if (txth->sample_type==1) txth->num_samples = get_bytes_to_samples(txth, txth->num_samples); if (txth->sample_type==2) @@ -556,7 +654,7 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h } } else if (0==strcmp(key,"loop_start_sample")) { - if (!parse_num(streamFile,val, &txth->loop_start_sample)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->loop_start_sample)) goto fail; if (txth->sample_type==1) txth->loop_start_sample = get_bytes_to_samples(txth, txth->loop_start_sample); if (txth->sample_type==2) @@ -569,7 +667,7 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h txth->loop_end_sample = get_bytes_to_samples(txth, txth->data_size); } else { - if (!parse_num(streamFile,val, &txth->loop_end_sample)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->loop_end_sample)) goto fail; if (txth->sample_type==1) txth->loop_end_sample = get_bytes_to_samples(txth, txth->loop_end_sample); if (txth->sample_type==2) @@ -579,7 +677,7 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h txth->loop_end_sample += txth->loop_adjust; } else if (0==strcmp(key,"skip_samples")) { - if (!parse_num(streamFile,val, &txth->skip_samples)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->skip_samples)) goto fail; txth->skip_samples_set = 1; if (txth->sample_type==1) txth->skip_samples = get_bytes_to_samples(txth, txth->skip_samples); @@ -587,7 +685,7 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h txth->skip_samples = get_bytes_to_samples(txth, txth->skip_samples * (txth->interleave*txth->channels)); } else if (0==strcmp(key,"loop_adjust")) { - if (!parse_num(streamFile,val, &txth->loop_adjust)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->loop_adjust)) goto fail; if (txth->sample_type==1) txth->loop_adjust = get_bytes_to_samples(txth, txth->loop_adjust); if (txth->sample_type==2) @@ -598,28 +696,105 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h txth->loop_flag_auto = 1; } else { - if (!parse_num(streamFile,val, &txth->loop_flag)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->loop_flag)) goto fail; txth->loop_flag_set = 1; + if (txth->loop_flag == 0xFFFF || txth->loop_flag == 0xFFFFFFFF) { /* normally -1 = no loop */ + txth->loop_flag = 0; + } } } else if (0==strcmp(key,"coef_offset")) { - if (!parse_num(streamFile,val, &txth->coef_offset)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->coef_offset)) goto fail; } else if (0==strcmp(key,"coef_spacing")) { - if (!parse_num(streamFile,val, &txth->coef_spacing)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->coef_spacing)) goto fail; } else if (0==strcmp(key,"coef_endianness")) { if (val[0]=='B' && val[1]=='E') txth->coef_big_endian = 1; else if (val[0]=='L' && val[1]=='E') txth->coef_big_endian = 0; - else if (!parse_num(streamFile,val, &txth->coef_big_endian)) goto fail; + else if (!parse_num(txth->streamHead,txth,val, &txth->coef_big_endian)) goto fail; } else if (0==strcmp(key,"coef_mode")) { - if (!parse_num(streamFile,val, &txth->coef_mode)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->coef_mode)) goto fail; } else if (0==strcmp(key,"psx_loops")) { - if (!parse_num(streamFile,val, &txth->coef_mode)) goto fail; + if (!parse_num(txth->streamHead,txth,val, &txth->coef_mode)) goto fail; + } + else if (0==strcmp(key,"subsong_count")) { + if (!parse_num(txth->streamHead,txth,val, &txth->subsong_count)) goto fail; + } + else if (0==strcmp(key,"subsong_offset")) { + if (!parse_num(txth->streamHead,txth,val, &txth->subsong_offset)) goto fail; + } + else if (0==strcmp(key,"name_offset")) { + if (!parse_num(txth->streamHead,txth,val, &txth->name_offset)) goto fail; + txth->name_offset_set = 1; + /* special subsong adjustment */ + if (txth->subsong_offset) + txth->name_offset = txth->name_offset + txth->subsong_offset * (txth->target_subsong - 1); + } + else if (0==strcmp(key,"name_size")) { + if (!parse_num(txth->streamHead,txth,val, &txth->name_size)) goto fail; + } + else if (0==strcmp(key,"header_file")) { + if (txth->streamhead_opened) { + close_streamfile(txth->streamHead); + txth->streamHead = NULL; + txth->streamhead_opened = 0; + } + + if (0==strcmp(val,"null")) { /* reset */ + if (!txth->streamfile_is_txth) { + txth->streamHead = txth->streamFile; + } + } + else if (val[0]=='*' && val[1]=='.') { /* basename + extension */ + txth->streamHead = open_streamfile_by_ext(txth->streamFile, (val+2)); + if (!txth->streamHead) goto fail; + txth->streamhead_opened = 1; + } + else { /* open file */ + fix_dir_separators(val); /* clean paths */ + + txth->streamHead = open_streamfile_by_filename(txth->streamFile, val); + if (!txth->streamHead) goto fail; + txth->streamhead_opened = 1; + } + } + else if (0==strcmp(key,"body_file")) { + if (txth->streambody_opened) { + close_streamfile(txth->streamBody); + txth->streamBody = NULL; + txth->streambody_opened = 0; + } + + if (0==strcmp(val,"null")) { /* reset */ + if (!txth->streamfile_is_txth) { + txth->streamBody = txth->streamFile; + } + } + else if (val[0]=='*' && val[1]=='.') { /* basename + extension */ + txth->streamBody = open_streamfile_by_ext(txth->streamFile, (val+2)); + if (!txth->streamBody) goto fail; + txth->streambody_opened = 1; + } + else { /* open file */ + fix_dir_separators(val); /* clean paths */ + + txth->streamBody = open_streamfile_by_filename(txth->streamFile, val); + if (!txth->streamBody) goto fail; + txth->streambody_opened = 1; + } + + /* use body as header when opening a .txth directly to simplify things */ + if (txth->streamfile_is_txth && !txth->streamhead_opened) { + txth->streamHead = txth->streamBody; + } + + txth->data_size = !txth->streamBody ? 0 : + get_streamfile_size(txth->streamBody) - txth->start_offset; /* re-evaluate */ } else { VGM_LOG("TXTH: unknown key=%s, val=%s\n", key,val); @@ -631,27 +806,37 @@ fail: return 0; } -static int parse_num(STREAMFILE * streamFile, const char * val, uint32_t * out_value) { +static int parse_num(STREAMFILE * streamFile, txth_header * txth, const char * val, uint32_t * out_value) { + /* out_value can be these, save before modifying */ + uint32_t value_mul = txth->value_mul; + uint32_t value_div = txth->value_div; + uint32_t value_add = txth->value_add; + uint32_t value_sub = txth->value_sub; + uint32_t subsong_offset = txth->subsong_offset; if (val[0] == '@') { /* offset */ - uint32_t off = 0; + uint32_t offset = 0; char ed1 = 'L', ed2 = 'E'; int size = 4; int big_endian = 0; int hex = (val[1]=='0' && val[2]=='x'); + /* can happen when loading .txth and not setting body/head */ + if (!streamFile) + goto fail; + /* read exactly N fields in the expected format */ if (strchr(val,':') && strchr(val,'$')) { - if (sscanf(val, hex ? "@%x:%c%c$%i" : "@%u:%c%c$%i", &off, &ed1,&ed2, &size) != 4) goto fail; + if (sscanf(val, hex ? "@%x:%c%c$%i" : "@%u:%c%c$%i", &offset, &ed1,&ed2, &size) != 4) goto fail; } else if (strchr(val,':')) { - if (sscanf(val, hex ? "@%x:%c%c" : "@%u:%c%c", &off, &ed1,&ed2) != 3) goto fail; + if (sscanf(val, hex ? "@%x:%c%c" : "@%u:%c%c", &offset, &ed1,&ed2) != 3) goto fail; } else if (strchr(val,'$')) { - if (sscanf(val, hex ? "@%x$%i" : "@%u$%i", &off, &size) != 2) goto fail; + if (sscanf(val, hex ? "@%x$%i" : "@%u$%i", &offset, &size) != 2) goto fail; } else { - if (sscanf(val, hex ? "@%x" : "@%u", &off) != 1) goto fail; + if (sscanf(val, hex ? "@%x" : "@%u", &offset) != 1) goto fail; } - if (off < 0 || off > get_streamfile_size(streamFile)) + if (/*offset < 0 ||*/ offset > get_streamfile_size(streamFile)) goto fail; if (ed1 == 'B' && ed2 == 'E') @@ -659,21 +844,48 @@ static int parse_num(STREAMFILE * streamFile, const char * val, uint32_t * out_v else if (!(ed1 == 'L' && ed2 == 'E')) goto fail; + if (subsong_offset) + offset = offset + subsong_offset * (txth->target_subsong - 1); + switch(size) { - case 1: *out_value = read_8bit(off,streamFile); break; - case 2: *out_value = big_endian ? (uint16_t)read_16bitBE(off,streamFile) : (uint16_t)read_16bitLE(off,streamFile); break; - case 3: *out_value = (big_endian ? (uint32_t)read_32bitBE(off,streamFile) : (uint32_t)read_32bitLE(off,streamFile)) & 0x00FFFFFF; break; - case 4: *out_value = big_endian ? (uint32_t)read_32bitBE(off,streamFile) : (uint32_t)read_32bitLE(off,streamFile); break; + case 1: *out_value = read_8bit(offset,streamFile); break; + case 2: *out_value = big_endian ? (uint16_t)read_16bitBE(offset,streamFile) : (uint16_t)read_16bitLE(offset,streamFile); break; + case 3: *out_value = (big_endian ? (uint32_t)read_32bitBE(offset,streamFile) : (uint32_t)read_32bitLE(offset,streamFile)) & 0x00FFFFFF; break; + case 4: *out_value = big_endian ? (uint32_t)read_32bitBE(offset,streamFile) : (uint32_t)read_32bitLE(offset,streamFile); break; default: goto fail; } } - else { /* constant */ + else if (val[0] >= '0' && val[0] <= '9') { /* unsigned constant */ int hex = (val[0]=='0' && val[1]=='x'); - if (sscanf(val, hex ? "%x" : "%u", out_value)!=1) goto fail; + if (sscanf(val, hex ? "%x" : "%u", out_value)!=1) + goto fail; + } + else { /* known field */ + if (0==strcmp(val,"interleave")) *out_value = txth->interleave; + else if (0==strcmp(val,"channels")) *out_value = txth->channels; + else if (0==strcmp(val,"sample_rate")) *out_value = txth->sample_rate; + else if (0==strcmp(val,"start_offset")) *out_value = txth->start_offset; + else if (0==strcmp(val,"data_size")) *out_value = txth->data_size; + else if (0==strcmp(val,"num_samples")) *out_value = txth->num_samples; + else if (0==strcmp(val,"loop_start_sample")) *out_value = txth->loop_start_sample; + else if (0==strcmp(val,"loop_end_sample")) *out_value = txth->loop_end_sample; + else if (0==strcmp(val,"subsong_count")) *out_value = txth->subsong_count; + else if (0==strcmp(val,"subsong_offset")) *out_value = txth->subsong_offset; + else goto fail; } - //VGM_LOG("TXTH: value=%s, read %u\n", val, *out_value); + /* operators, but only if current value wasn't set to 0 right before */ + if (value_mul && txth->value_mul) + *out_value = (*out_value) * value_mul; + if (value_div && txth->value_div) + *out_value = (*out_value) / value_div; + if (value_add && txth->value_add) + *out_value = (*out_value) + value_add; + if (value_sub && txth->value_sub) + *out_value = (*out_value) - value_sub; + + //;VGM_LOG("TXTH: val=%s, read %u (0x%x)\n", val, *out_value, *out_value); return 1; fail: return 0; @@ -725,6 +937,8 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) { return ima_bytes_to_samples(bytes, txth->channels); case AICA: return aica_bytes_to_samples(bytes, txth->channels); + case PCFX: + return pcfx_bytes_to_samples(bytes, txth->channels); /* untested */ case SDX2: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txtp.c b/Frameworks/vgmstream/vgmstream/src/meta/txtp.c index a020c0d4b..fce903dcf 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txtp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txtp.c @@ -25,8 +25,8 @@ typedef struct { size_t entry_count; size_t entry_max; - size_t loop_start_segment; - size_t loop_end_segment; + uint32_t loop_start_segment; + uint32_t loop_end_segment; size_t is_layered; } txtp_header; @@ -365,20 +365,9 @@ static int add_filename(txtp_header * txtp, char *filename) { } - /* hack to allow relative paths in various OSs */ - { - char c; + fix_dir_separators(filename); /* clean paths */ - i = 0; - while ((c = filename[i]) != '\0') { - if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\')) - filename[i] = DIR_SEPARATOR; - i++; - } - } - - - /* add filesnames */ + /* add filenames */ for (i = range_start; i < range_end; i++){ txtp_entry *current; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c index 329bc4bc4..75af0e623 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c @@ -190,6 +190,8 @@ static VGMSTREAM * init_vgmstream_ubi_bao_main(ubi_bao_header * bao, STREAMFILE vgmstream->layout_type = layout_none; vgmstream->stream_size = data_size; + + xma_fix_raw_samples(vgmstream, streamData, start_offset,data_size, 0, 0,0); break; } @@ -263,6 +265,8 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) { size_t index_size, index_header_size; off_t bao_offset, resources_offset; int target_subsong = streamFile->stream_index; + uint8_t *index_buffer = NULL; + STREAMFILE *streamTest = NULL; /* class: 0x01=index, 0x02=BAO */ @@ -271,7 +275,7 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) { /* index and resources always LE */ /* 0x01(3): version, major/minor/release (numbering continues from .sb0/sm0) */ - index_size = read_32bitLE(0x04, streamFile); /* can be 0 */ + index_size = read_32bitLE(0x04, streamFile); /* can be 0, not including */ resources_offset = read_32bitLE(0x08, streamFile); /* always found even if not used */ /* 0x0c: always 0? */ /* 0x10: unknown, null if no entries */ @@ -285,14 +289,26 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) { index_entries = index_size / 0x08; index_header_size = 0x40; - /* parse index to get target subsong N = Nth header BAO */ + /* pre-load to avoid too much I/O back and forth */ + if (index_size > (10000*0x08)) { + VGM_LOG("BAO: index too big\n"); + goto fail; + } + index_buffer = malloc(index_size); + read_streamfile(index_buffer, index_header_size, index_size, streamFile); + + /* use smaller I/O buffer for performance, as this read lots of small BAO headers all over the place */ + streamTest = reopen_streamfile(streamFile, 0x100); + if (!streamTest) goto fail; + + /* parse index to get target subsong N = Nth audio header BAO */ bao_offset = index_header_size + index_size; for (i = 0; i < index_entries; i++) { - //uint32_t bao_id = read_32bitLE(index_header_size+0x08*i+0x00, streamFile); - size_t bao_size = read_32bitLE(index_header_size+0x08*i+0x04, streamFile); + //uint32_t bao_id = get_32bitLE(index_buffer + 0x08*i+ 0x00); + size_t bao_size = get_32bitLE(index_buffer + 0x08*i + 0x04); /* parse and continue to find out total_subsongs */ - if (!parse_bao(bao, streamFile, bao_offset)) + if (!parse_bao(bao, streamTest, bao_offset)) goto fail; bao_offset += bao_size; /* files simply concat BAOs */ @@ -389,10 +405,14 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) { goto fail; } - ;VGM_LOG("BAO stream: id=%x, offset=%"PRIx64", size=%x, res=%s\n", bao->stream_id, (off64_t)bao->stream_offset, bao->stream_size, (bao->is_external ? bao->resource_name : "internal")); + ;VGM_LOG("BAO stream: id=%x, offset=%x, size=%x, res=%s\n", bao->stream_id, (uint32_t)bao->stream_offset, bao->stream_size, (bao->is_external ? bao->resource_name : "internal")); + free(index_buffer); + close_streamfile(streamTest); return 1; fail: + free(index_buffer); + close_streamfile(streamTest); return 0; } @@ -405,14 +425,14 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) /* 0x00(1): class? usually 0x02 but older BAOs have 0x01 too */ - bao_version = read_32bitBE(offset + 0x00, streamFile) & 0x00FFFFFF; + bao_version = read_32bitBE(offset+0x00, streamFile) & 0x00FFFFFF; - /* detect endianness */ - if (read_32bitLE(offset+0x04, streamFile) < 0x0000FFFF) { - read_32bit = read_32bitLE; - } else { + /* this could be done once as all BAOs share endianness */ + if (guess_endianness32bit(offset+0x04, streamFile)) { read_32bit = read_32bitBE; bao->big_endian = 1; + } else { + read_32bit = read_32bitLE; } header_size = read_32bit(offset+0x04, streamFile); /* mainly 0x28, rarely 0x24 */ @@ -432,7 +452,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) case 0x70000000: bao->types_count[7]++; break; /* project info? (sometimes special id 0x7fffffff) */ case 0x80000000: bao->types_count[8]++; break; /* unknown (some id/info?) */ default: - VGM_LOG("UBI BAO: unknown type %x at %"PRIx64" + %x\n", descriptor_type, (off64_t)offset, 0x20); + VGM_LOG("UBI BAO: unknown type %x at %x + %x\n", descriptor_type, (uint32_t)offset, 0x20); goto fail; } @@ -451,7 +471,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) case 0x00000007: bao->subtypes_count[7]++; break; /* related to other header BAOs? */ case 0x00000008: bao->subtypes_count[8]++; break; /* ? (almost empty with some unknown value) */ default: - VGM_LOG("UBI BAO: unknown subtype %x at %"PRIx64" + %x\n", descriptor_subtype, (off64_t)offset, header_size+0x04); + VGM_LOG("UBI BAO: unknown subtype %x at %x + %x\n", descriptor_subtype, (uint32_t)offset, header_size+0x04); goto fail; } //;VGM_ASSERT(descriptor_subtype != 0x01, "UBI BAO: subtype %x at %lx (%lx)\n", descriptor_subtype, offset, offset+header_size+0x04); @@ -475,7 +495,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) * - channels, ?, sample rate, average bit rate?, samples, full stream_size?, codec, etc * - subtable entries, subtable size (may contain offsets/ids, cues, etc) * - extra data per codec (ex. XMA header in some versions) */ - ;VGM_LOG("BAO header at %"PRIx64"\n", (off64_t)offset); + ;VGM_LOG("BAO header at %x\n", (uint32_t)offset); bao->version = bao_version; switch(bao->version) { @@ -501,7 +521,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) case 0x03: bao->codec = UBI_ADPCM; break; case 0x05: bao->codec = RAW_XMA1; break; case 0x09: bao->codec = RAW_DSP; break; - default: VGM_LOG("UBI BAO: unknown codec at %"PRIx64"\n", (off64_t)offset); goto fail; + default: VGM_LOG("UBI BAO: unknown codec at %x\n", (uint32_t)offset); goto fail; } bao->prefetch_size = read_32bit(offset + header_size + 0x74, streamFile); @@ -533,11 +553,11 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) switch(bao->header_codec) { case 0x06: bao->codec = RAW_PSX; break; case 0x07: bao->codec = FMT_AT3; break; - default: VGM_LOG("UBI BAO: unknown codec at %"PRIx64"\n", (off64_t)offset); goto fail; + default: VGM_LOG("UBI BAO: unknown codec at %x\n", (uint32_t)offset); goto fail; } if (read_32bit(offset+header_size+0x20, streamFile) & 0x10) { - VGM_LOG("UBI BAO: possible full loop at %"PRIx64"\n", (off64_t)offset); + VGM_LOG("UBI BAO: possible full loop at %x\n", (uint32_t)offset); /* RIFFs may have "smpl" and this flag, even when data shouldn't loop... */ } @@ -562,7 +582,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) case 0x02: bao->codec = UBI_ADPCM; break; case 0x03: bao->codec = FMT_OGG; break; case 0x04: bao->codec = RAW_XMA2; break; - default: VGM_LOG("UBI BAO: unknown codec at %"PRIx64"\n", (off64_t)offset); goto fail; + default: VGM_LOG("UBI BAO: unknown codec at %x\n", (uint32_t)offset); goto fail; } bao->prefetch_size = read_32bit(offset+header_size+0x84, streamFile); @@ -596,7 +616,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) case 0x04: bao->codec = RAW_XMA2; break; case 0x05: bao->codec = RAW_PSX; break; case 0x06: bao->codec = RAW_AT3; break; - default: VGM_LOG("UBI BAO: unknown codec at %"PRIx64"\n", (off64_t)offset); goto fail; + default: VGM_LOG("UBI BAO: unknown codec at %x\n", (uint32_t)offset); goto fail; } bao->prefetch_size = read_32bit(offset + header_size + 0x78, streamFile); @@ -613,7 +633,7 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) case 0x00280306: /* Far Cry 3: Blood Dragon (X360)-file */ case 0x00290106: /* Splinter Cell Blacklist? */ default: /* others possibly using BAO: Avatar X360/PS3/PC, Just Dance, Watch_Dogs, Far Cry Primal, Far Cry 4 */ - VGM_LOG("UBI BAO: unknown BAO version at %"PRIx64"\n", (off64_t)offset); + VGM_LOG("UBI BAO: unknown BAO version at %x\n", (uint32_t)offset); goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c index a3b48435b..054c87142 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c @@ -1,7 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_jade_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end); /* Jade RIFF - from Ubisoft Jade engine games [Beyond Good & Evil (multi), Rayman Raving Rabbids 1/2 (multi)] */ @@ -231,7 +230,7 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) { if (read_32bitBE(start_offset, streamFile) != 0x4D534643) /* "MSF\43" */ goto fail; - temp_streamFile = setup_jade_streamfile(streamFile, start_offset, data_size, "msf"); + temp_streamFile = setup_subfile_streamfile(streamFile, start_offset, data_size, "msf"); if (!temp_streamFile) goto fail; temp_vgmstream = init_vgmstream_ps3_msf(temp_streamFile); @@ -362,7 +361,7 @@ VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE *streamFile) { subfile_size = read_32bitLE(subfile_offset+0x04,streamFile) + 0x04+0x04; - temp_streamFile = setup_jade_streamfile(streamFile, subfile_offset,subfile_size, NULL); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); if (!temp_streamFile) goto fail; if (check_extensions(streamFile,"xma")) { @@ -379,28 +378,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_jade_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - if (fake_ext) { - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - } - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c index 7387205a2..bf377de0e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c @@ -5,7 +5,7 @@ /* RAKI - Ubisoft audio format [Rayman Legends, Just Dance 2017 (multi)] */ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - off_t start_offset, off, fmt_offset; + off_t start_offset, offset, fmt_offset; size_t header_size, data_size; int big_endian; int loop_flag, channel_count, block_align, bits_per_sample; @@ -15,22 +15,24 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - /* basic checks */ - /* .rak: Just Dance 2017; .ckd: Rayman Legends (technically .wav.ckd/rak) */ - if (!check_extensions(streamFile,"rak,ckd")) goto fail; + /* checks */ + /* .rak: Just Dance 2017 + * .ckd: Rayman Legends (technically .wav.ckd/rak) */ + if (!check_extensions(streamFile,"rak,ckd")) + goto fail; /* some games (ex. Rayman Legends PS3) have a 32b file type before the RAKI data. However * offsets are absolute and expect the type exists, so it's part of the file and not an extraction defect. */ if ((read_32bitBE(0x00,streamFile) == 0x52414B49)) /* "RAKI" */ - off = 0x0; + offset = 0x00; else if ((read_32bitBE(0x04,streamFile) == 0x52414B49)) /* type varies between platforms (0x09, 0x0b) so ignore */ - off = 0x4; + offset = 0x04; else goto fail; /* 0x04: version? (0x00, 0x07, 0x0a, etc); */ - platform = read_32bitBE(off+0x08,streamFile); /* string */ - type = read_32bitBE(off+0x0c,streamFile); /* string */ + platform = read_32bitBE(offset+0x08,streamFile); /* string */ + type = read_32bitBE(offset+0x0c,streamFile); /* string */ switch(platform) { case 0x57696920: /* "Wii " */ @@ -48,15 +50,15 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { break; } - header_size = read_32bit(off+0x10,streamFile); - start_offset = read_32bit(off+0x14,streamFile); + header_size = read_32bit(offset+0x10,streamFile); + start_offset = read_32bit(offset+0x14,streamFile); /* 0x18: number of chunks */ /* 0x1c: unk */ /* the format has a chunk offset table, and the first one always "fmt" and points - * to a RIFF "fmt" chunk (even for WiiU or PS3) */ - if (read_32bitBE(off+0x20,streamFile) != 0x666D7420) goto fail; /*"fmt "*/ - fmt_offset = read_32bit(off+0x24,streamFile); + * to a RIFF "fmt"-style chunk (even for WiiU or PS3) */ + if (read_32bitBE(offset+0x20,streamFile) != 0x666D7420) goto fail; /* "fmt " */ + fmt_offset = read_32bit(offset+0x24,streamFile); //fmt_size = read_32bit(off+0x28,streamFile); loop_flag = 0; /* not seen */ @@ -106,7 +108,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { /* we need to know if the file uses "datL" and is full-interleave */ if (channel_count > 1) { - off_t chunk_off = off+ 0x20 + 0xc; /* after "fmt" */ + off_t chunk_off = offset+ 0x20 + 0xc; /* after "fmt" */ while (chunk_off < header_size) { if (read_32bitBE(chunk_off,streamFile) == 0x6461744C) { /*"datL" found */ size_t chunk_size = read_32bit(chunk_off+0x8,streamFile); @@ -122,7 +124,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { { /* get coef offsets; could check "dspL" and "dspR" chunks after "fmt " better but whatevs (only "dspL" if mono) */ - off_t dsp_coefs = read_32bitBE(off+0x30,streamFile); /* after "dspL"; spacing is consistent but could vary */ + off_t dsp_coefs = read_32bitBE(offset+0x30,streamFile); /* after "dspL"; spacing is consistent but could vary */ dsp_read_coefs(vgmstream,streamFile, dsp_coefs+0x1c, 0x60, big_endian); /* dsp_coefs + 0x00-0x1c: ? (special coefs or adpcm history?) */ } @@ -149,15 +151,16 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { int bytes, block_count; block_count = data_size / block_align + (data_size % block_align ? 1 : 0); - bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_align); - if (bytes <= 0) goto fail; + bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_align); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; vgmstream->num_samples = read_32bit(fmt_offset+0x18,streamFile); + + xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* should apply to num_samples? */ break; } #endif @@ -199,7 +202,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; { - off_t chunk_offset = off + 0x20 + 0xc; /* after "fmt" */ + off_t chunk_offset = offset + 0x20 + 0xc; /* after "fmt" */ while (chunk_offset < header_size) { if (read_32bitBE(chunk_offset,streamFile) == 0x4164496E) { /*"AdIn" additional info */ off_t adin_offset = read_32bitLE(chunk_offset+0x04,streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index 2782a7cf8..3183310dd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -2,8 +2,10 @@ #include "../coding/coding.h" -typedef enum { UBI_ADPCM, RAW_PCM, RAW_PSX, RAW_DSP, RAW_XBOX, FMT_VAG, FMT_AT3, FMT_OGG } ubi_sb_codec; +typedef enum { UBI_ADPCM, RAW_PCM, RAW_PSX, RAW_DSP, RAW_XBOX, FMT_VAG, FMT_AT3, RAW_AT3, FMT_XMA1, RAW_XMA1, FMT_OGG } ubi_sb_codec; +typedef enum { UBI_PC, UBI_PS2, UBI_XBOX, UBI_GC, UBI_X360, UBI_3DS, UBI_PS3, UBI_WII, UBI_PSP } ubi_sb_platform; typedef struct { + ubi_sb_platform platform; int big_endian; int total_streams; int is_external; @@ -15,33 +17,52 @@ typedef struct { size_t section1_num; size_t section2_num; size_t section3_num; + size_t section4_num; size_t extra_size; int flag1; int flag2; + /* maps data config */ + int is_map; + int map_version; + /* stream info config (format varies slightly per game) */ size_t section1_entry_size; size_t section2_entry_size; size_t section3_entry_size; + off_t stream_size_offset; + off_t extra_pointer_offset; + off_t stream_pointer_offset; off_t external_flag_offset; + off_t samples_flag_offset; off_t num_samples_offset; + off_t num_samples_offset2; off_t sample_rate_offset; off_t channels_offset; off_t stream_type_offset; off_t stream_name_offset; off_t extra_name_offset; size_t stream_name_size; - size_t stream_id_offset; + off_t stream_id_offset; + off_t xma_pointer_offset; int has_short_channels; int has_internal_names; int has_extra_name_flag; int has_rotating_ids; /* derived */ - size_t main_size; - size_t section1_size; - size_t section2_size; - size_t section3_size; + size_t section1_offset; + size_t section2_offset; + size_t section3_offset; + size_t section4_offset; + size_t extra_section_offset; + size_t sounds_offset; + + /* map info */ + off_t map_header_offset; + off_t map_num; + off_t map_offset; + char map_name[255]; /* stream info */ uint32_t header_id; @@ -50,61 +71,303 @@ typedef struct { off_t extra_offset; off_t stream_offset; uint32_t stream_id; + off_t xma_header_offset; int stream_samples; /* usually only for external resources */ int sample_rate; int channels; uint32_t stream_type; char stream_name[255]; + char extra_name[255]; + int header_idx; + off_t header_offset; - + int subtypes[16]; } ubi_sb_header; -static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile); +static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *streamFile); +static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int target_stream); static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile); - /* .SBx - banks from Ubisoft's sound engine ("DARE" / "UbiSound Driver") games in ~2000-2008 */ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE *streamData = NULL; - off_t start_offset; - int loop_flag = 0; - ubi_sb_header sb = {0}; + STREAMFILE *streamTest = NULL; + int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; + //int16_t(*read_16bit)(off_t, STREAMFILE*) = NULL; + ubi_sb_header sb = { 0 }; + int ok; + int target_stream = streamFile->stream_index; /* check extension (number represents the platform, see later) */ - if ( !check_extensions(streamFile,"sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7") ) + if (!check_extensions(streamFile, "sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7")) goto fail; + if (target_stream == 0) target_stream = 1; /* .sb0 (sound bank) is a small multisong format (loaded in memory?) that contains SFX data * but can also reference .ss0/ls0 (sound stream) external files for longer streams. * A companion .sp0 (sound project) describes files and if it uses BANKs (.sb0) or MAPs (.sm0). */ + /* sigh... PSP hijacks not one but *two* platform indexes */ + /* please add any PSP game versions under sb4 and sb5 sections so we can properly identify platform */ + sb.version = read_32bitLE(0x00, streamFile); + + if (check_extensions(streamFile, "sb0")) { + sb.platform = UBI_PC; + } else if (check_extensions(streamFile, "sb1")) { + sb.platform = UBI_PS2; + } else if (check_extensions(streamFile, "sb2")) { + sb.platform = UBI_XBOX; + } else if (check_extensions(streamFile, "sb3")) { + sb.platform = UBI_GC; + } else if (check_extensions(streamFile, "sb4")) { + switch (sb.version) { + case 0x0012000C: /* Prince of Persia: Revelations (2005) */ + sb.platform = UBI_PSP; + break; + default: + sb.platform = UBI_X360; + break; + } + } else if (check_extensions(streamFile, "sb5")) { + switch (sb.version) { + case 0x00180005: /* Prince of Persia: Rival Swords (2007) */ + case 0x00180006: /* Rainbow Six Vegas (2007) */ + sb.platform = UBI_PSP; + break; + default: + sb.platform = UBI_3DS; + break; + } + } else if (check_extensions(streamFile, "sb6")) { + sb.platform = UBI_PS3; + } else if (check_extensions(streamFile, "sb7")) { + sb.platform = UBI_WII; + } else { + goto fail; + } + + sb.big_endian = (sb.platform == UBI_GC || + sb.platform == UBI_PS3 || + sb.platform == UBI_X360 || + sb.platform == UBI_WII); + if (sb.big_endian) { + read_32bit = read_32bitBE; + //read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + //read_16bit = read_16bitLE; + } + + /* file layout is: base header, section1, section2, extra section, section3, data (all except base header can be null) */ + + sb.version = read_32bit(0x00, streamFile); /* 16b+16b major/minor version */ + sb.section1_num = read_32bit(0x04, streamFile); /* group headers? */ + sb.section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */ + sb.section3_num = read_32bit(0x0c, streamFile); /* internal streams table */ + sb.extra_size = read_32bit(0x10, streamFile); /* extra table, unknown (config for non-audio types) except with DSP = coefs */ + sb.flag1 = read_32bit(0x14, streamFile); /* unknown, usually -1 but can be others (0/1/2/etc) */ + sb.flag2 = read_32bit(0x18, streamFile); /* unknown, usually -1 but can be others */ + + ok = config_sb_header_version(&sb, streamFile); + if (!ok) { + VGM_LOG("UBI SB: unknown SB version+platform\n"); + goto fail; + } + + sb.section1_offset = 0x1c; + sb.section2_offset = sb.section1_offset + sb.section1_entry_size * sb.section1_num; + sb.extra_section_offset = sb.section2_offset + sb.section2_entry_size * sb.section2_num; + sb.section3_offset = sb.extra_section_offset + sb.extra_size; + sb.sounds_offset = sb.section3_offset + sb.section3_entry_size * sb.section3_num; + sb.is_map = 0; + + /* use smaller I/O buffer for performance, as this read lots of small headers all over the place */ + streamTest = reopen_streamfile(streamFile, 0x100); + if (!streamTest) goto fail; + /* main parse */ - if ( !parse_sb_header(&sb, streamFile) ) + if (!parse_sb_header(&sb, streamTest, target_stream)) goto fail; + close_streamfile(streamTest); + return init_vgmstream_ubi_sb_main(&sb, streamFile); + +fail: + close_streamfile(streamTest); + return NULL; +} + +/* .SMx - essentially a set of SBx files, one per map, compiled into one file */ +VGMSTREAM * init_vgmstream_ubi_sm(STREAMFILE *streamFile) { + STREAMFILE *streamTest = NULL; + int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; + //int16_t(*read_16bit)(off_t, STREAMFILE*) = NULL; + ubi_sb_header sb = { 0 }; + size_t map_entry_size; + int ok, i; + int target_stream = streamFile->stream_index; + + /* check extension (number represents the platform, see later) */ + if (!check_extensions(streamFile, "sm0,sm1,sm2,sm3,sm4,sm5,sm6,sm7,lm0,lm1,lm2,lm3,lm4,lm5,lm6,lm7")) + goto fail; + + if (target_stream == 0) target_stream = 1; + + /* sigh... PSP hijacks not one but *two* platform indexes */ + /* please add any PSP game versions under sb4 and sb5 sections so we can properly identify platform */ + sb.version = read_32bitLE(0x00, streamFile); + + if (check_extensions(streamFile, "sm0,lm0")) { + sb.platform = UBI_PC; + } else if (check_extensions(streamFile, "sm1,lm1")) { + sb.platform = UBI_PS2; + } else if (check_extensions(streamFile, "sm2,lm2")) { + sb.platform = UBI_XBOX; + } else if (check_extensions(streamFile, "sm3,lm3")) { + sb.platform = UBI_GC; + } else if (check_extensions(streamFile, "sm4,lm4")) { + switch (sb.version) { + case 0x0012000C: /* Splinter Cell: Essentials (2006) */ + sb.platform = UBI_PSP; + break; + default: + sb.platform = UBI_X360; + break; + } + } else if (check_extensions(streamFile, "sm5,lm5")) { + switch (sb.version) { + case 0x00190001: /* TMNT (2007) */ + case 0x00190005: /* Surf's Up (2007) */ + sb.platform = UBI_PSP; + break; + default: + sb.platform = UBI_3DS; + break; + } + } else if (check_extensions(streamFile, "sm6,lm6")) { + sb.platform = UBI_PS3; + } else if (check_extensions(streamFile, "sm7,lm7")) { + sb.platform = UBI_WII; + } else { + goto fail; + } + + sb.big_endian = (sb.platform == UBI_GC || + sb.platform == UBI_PS3 || + sb.platform == UBI_X360 || + sb.platform == UBI_WII); + if (sb.big_endian) { + read_32bit = read_32bitBE; + //read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + //read_16bit = read_16bitLE; + } + + sb.is_map = 1; + sb.version = read_32bit(0x00, streamFile); + sb.map_header_offset = read_32bit(0x04, streamFile); + sb.map_num = read_32bit(0x08, streamFile); + + ok = config_sb_header_version(&sb, streamFile); + if (!ok || sb.map_version == 0) { + VGM_LOG("UBI SB: unknown SM version+platform\n"); + goto fail; + } + + /* use smaller I/O buffer for performance, as this read lots of small headers all over the place */ + streamTest = reopen_streamfile(streamFile, 0x100); + if (!streamTest) goto fail; + + map_entry_size = (sb.map_version < 2) ? 0x30 : 0x34; + + for (i = 0; i < sb.map_num; i++) { + /* basic layout: + * 0x00 - map type + * 0x04 - zero + * 0x08 - map section offset + * 0x0c - map section size + * 0x10 - map name (20 byte) */ + off_t offset = sb.map_header_offset + i * map_entry_size; + sb.map_offset = read_32bit(offset + 0x08, streamFile); + read_string(sb.map_name, sizeof(sb.map_name), offset + 0x10, streamFile); + /* latest format has another unknown long here or maybe string buffer is 4 bytes bigger */ + + /* parse map section header */ + sb.section1_offset = read_32bit(sb.map_offset + 0x04, streamFile) + sb.map_offset; + sb.section1_num = read_32bit(sb.map_offset + 0x08, streamFile); + sb.section2_offset = read_32bit(sb.map_offset + 0x0c, streamFile) + sb.map_offset; + sb.section2_num = read_32bit(sb.map_offset + 0x10, streamFile); + + if (sb.map_version < 3) { + sb.section3_offset = read_32bit(sb.map_offset + 0x14, streamFile) + sb.map_offset; + sb.section3_num = read_32bit(sb.map_offset + 0x18, streamFile); + sb.extra_section_offset = read_32bit(sb.map_offset + 0x1c, streamFile) + sb.map_offset; + sb.extra_size = read_32bit(sb.map_offset + 0x20, streamFile); + } else { + /* latest map format has another section with sounds after section 2 */ + sb.section4_offset = read_32bit(sb.map_offset + 0x14, streamFile); + sb.section4_num = read_32bit(sb.map_offset + 0x18, streamFile); + sb.section3_offset = read_32bit(sb.map_offset + 0x1c, streamFile) + sb.map_offset; + sb.section3_num = read_32bit(sb.map_offset + 0x20, streamFile); + sb.extra_section_offset = read_32bit(sb.map_offset + 0x24, streamFile) + sb.map_offset; + sb.extra_size = read_32bit(sb.map_offset + 0x28, streamFile); + + /* Let's just merge it with section 2 */ + sb.section2_num += sb.section4_num; + + /* for some reason, this is relative to section 4 here */ + sb.extra_section_offset += sb.section4_offset; + } + + if (!parse_sb_header(&sb, streamTest, target_stream)) + goto fail; + } + + if (sb.total_streams == 0) { + VGM_LOG("UBI SB: no streams\n"); + goto fail; + } + + if (target_stream < 0 || target_stream > sb.total_streams) { + VGM_LOG("UBI SB: wrong target stream (target=%i, total=%i)\n", target_stream, sb.total_streams); + goto fail; + } + + close_streamfile(streamTest); + return init_vgmstream_ubi_sb_main(&sb, streamFile); + +fail: + close_streamfile(streamTest); + return NULL; +} + +static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *streamData = NULL; + off_t start_offset; + int loop_flag = 0; /* open external stream if needed */ - if (sb.autodetect_external) { /* works most of the time but could give false positives */ - VGM_LOG("UBI SB: autodetecting external stream '%s'\n", sb.stream_name); + if (sb->autodetect_external) { /* works most of the time but could give false positives */ + VGM_LOG("UBI SB: autodetecting external stream '%s'\n", sb->extra_name); - streamData = open_streamfile_by_filename(streamFile,sb.stream_name); + streamData = open_streamfile_by_filename(streamFile,sb->extra_name); if (!streamData) { streamData = streamFile; /* assume internal */ - if (sb.stream_size > get_streamfile_size(streamData)) { + if (sb->stream_size > get_streamfile_size(streamData)) { VGM_LOG("UBI SB: expected external stream\n"); goto fail; } } else { - sb.is_external = 1; + sb->is_external = 1; } } - else if (sb.is_external) { - streamData = open_streamfile_by_filename(streamFile,sb.stream_name); + else if (sb->is_external) { + streamData = open_streamfile_by_filename(streamFile,sb->extra_name); if (!streamData) { - VGM_LOG("UBI SB: external stream '%s' not found\n", sb.stream_name); + VGM_LOG("UBI SB: external stream '%s' not found\n", sb->extra_name); goto fail; } } @@ -112,62 +375,54 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { streamData = streamFile; } - /* final offset */ - if (sb.is_external) { - start_offset = sb.stream_offset; - } else { - start_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size; - start_offset += sb.stream_offset; - } - //;VGM_LOG("start offset=%lx, external=%i\n", start_offset, sb.is_external); - + start_offset = sb->stream_offset; + //;VGM_LOG("start offset=%lx, external=%i\n", start_offset, sb->is_external); /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(sb.channels,loop_flag); + vgmstream = allocate_vgmstream(sb->channels,loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = sb.sample_rate; - vgmstream->num_streams = sb.total_streams; - vgmstream->stream_size = sb.stream_size; + vgmstream->sample_rate = sb->sample_rate; + vgmstream->num_streams = sb->total_streams; + vgmstream->stream_size = sb->stream_size; vgmstream->meta_type = meta_UBI_SB; - switch(sb.codec) { - case UBI_ADPCM: { + switch(sb->codec) { + case UBI_ADPCM: vgmstream->coding_type = coding_UBI_IMA; vgmstream->layout_type = layout_none; - vgmstream->num_samples = ubi_ima_bytes_to_samples(sb.stream_size, sb.channels, streamData, start_offset); + vgmstream->num_samples = ubi_ima_bytes_to_samples(sb->stream_size, sb->channels, streamData, start_offset); break; - } case RAW_PCM: vgmstream->coding_type = coding_PCM16LE; /* always LE even on Wii */ vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x02; - vgmstream->num_samples = pcm_bytes_to_samples(sb.stream_size, sb.channels, 16); + vgmstream->num_samples = pcm_bytes_to_samples(sb->stream_size, sb->channels, 16); break; case RAW_PSX: vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = sb.stream_size / sb.channels; - vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels) ; + vgmstream->interleave_block_size = (sb->stream_type == 0x00) ? sb->stream_size / sb->channels : 0x10; /* TODO: needs testing */ + vgmstream->num_samples = ps_bytes_to_samples(sb->stream_size, sb->channels) ; break; case RAW_XBOX: vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; - vgmstream->num_samples = xbox_ima_bytes_to_samples(sb.stream_size, sb.channels); + vgmstream->num_samples = xbox_ima_bytes_to_samples(sb->stream_size, sb->channels); break; case RAW_DSP: vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = sb.stream_size / sb.channels; - vgmstream->num_samples = dsp_bytes_to_samples(sb.stream_size, sb.channels); + vgmstream->interleave_block_size = sb->stream_size / sb->channels; + vgmstream->num_samples = dsp_bytes_to_samples(sb->stream_size, sb->channels); { - off_t coefs_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_offset; + off_t coefs_offset = sb->extra_offset; coefs_offset += 0x10; /* entry size is 0x40 (first/last 0x10 = unknown), per channel */ dsp_read_coefs_be(vgmstream,streamFile,coefs_offset, 0x40); @@ -178,13 +433,13 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { /* skip VAG header (some sb4 use VAG and others raw PSX) */ if (read_32bitBE(start_offset, streamData) == 0x56414770) { /* "VAGp" */ start_offset += 0x30; - sb.stream_size -= 0x30; + sb->stream_size -= 0x30; } vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = sb.stream_size / sb.channels; - vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels); + vgmstream->interleave_block_size = sb->stream_size / sb->channels; + vgmstream->num_samples = ps_bytes_to_samples(sb->stream_size, sb->channels); break; @@ -195,20 +450,20 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { /* skip weird value (3, 4) in Brothers in Arms: D-Day (PSP) */ if (read_32bitBE(start_offset+0x04,streamData) == 0x52494646) { start_offset += 0x04; - sb.stream_size -= 0x04; + sb->stream_size -= 0x04; } - ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb.stream_size); + ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb->stream_size); if ( !ffmpeg_data ) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - if (sb.stream_samples == 0) /* sometimes not known */ - sb.stream_samples = ffmpeg_data->totalSamples; - vgmstream->num_samples = sb.stream_samples; - if (sb.stream_samples != ffmpeg_data->totalSamples) { - VGM_LOG("UBI SB: header samples differ (%i vs %i)\n", sb.stream_samples, (size_t)ffmpeg_data->totalSamples); + if (sb->stream_samples == 0) /* sometimes not known */ + sb->stream_samples = ffmpeg_data->totalSamples; + vgmstream->num_samples = sb->stream_samples; + if (sb->stream_samples != ffmpeg_data->totalSamples) { + VGM_LOG("UBI SB: header samples differ (%i vs %i)\n", sb->stream_samples, (size_t)ffmpeg_data->totalSamples); goto fail; } @@ -217,17 +472,103 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { break; } + case RAW_AT3: { + ffmpeg_codec_data *ffmpeg_data; + uint8_t buf[0x100]; + int32_t bytes, block_size, encoder_delay, joint_stereo; + + block_size = 0x98 * sb->channels; + joint_stereo = 0; + encoder_delay = 0x00; /* TODO: this is incorrect */ + + bytes = ffmpeg_make_riff_atrac3(buf, 0x100, sb->stream_samples, sb->stream_size, sb->channels, sb->sample_rate, block_size, joint_stereo, encoder_delay); + ffmpeg_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, sb->stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->num_samples = sb->stream_samples; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } + + case FMT_XMA1: { + ffmpeg_codec_data *ffmpeg_data; + uint8_t buf[0x100]; + uint32_t sec1_num, sec2_num, sec3_num, num_frames, bits_per_frame; + uint8_t flag; + size_t bytes, chunk_size, header_size, data_size; + off_t header_offset; + + chunk_size = 0x20; + + /* formatted XMA sounds have a strange custom header */ + header_offset = start_offset; /* XMA fmt chunk at the start */ + flag = read_8bit(header_offset + 0x20, streamData); + sec2_num = read_32bitBE(header_offset + 0x24, streamData); /* number of XMA frames */ + sec1_num = read_32bitBE(header_offset + 0x28, streamData); + sec3_num = read_32bitBE(header_offset + 0x2c, streamData); + num_frames = sec2_num; + bits_per_frame = 4; + + if (flag == 0x04) { + sec1_num--; + sec2_num += 4; + } else if (flag == 0x02) { + bits_per_frame = 2; + } + + header_size = 0x30; + header_size += sec1_num * 0x04; + header_size += align_size_to_block(sec2_num * bits_per_frame, 32) / 8; /* bitstream with 4 or 2 bits for each frame */ + header_size += sec3_num * 0x08; + start_offset += header_size; + data_size = num_frames * 0x800; + + bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, data_size, streamData, 1); + + ffmpeg_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, data_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = sb->stream_samples; + vgmstream->stream_size = data_size; + break; + } + + case RAW_XMA1: { + ffmpeg_codec_data *ffmpeg_data; + uint8_t buf[0x100]; + size_t bytes, chunk_size; + off_t header_offset; + + VGM_ASSERT(sb->is_external, "Ubi SB: Raw XMA used for external sound\n"); + + /* get XMA header from extra section */ + chunk_size = 0x20; + header_offset = sb->xma_header_offset; + bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, sb->stream_size, streamFile, 1); + + ffmpeg_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, sb->stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = sb->stream_samples; + break; + } + case FMT_OGG: { ffmpeg_codec_data *ffmpeg_data; - ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb.stream_size); + ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb->stream_size); if ( !ffmpeg_data ) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = sb.stream_samples; /* ffmpeg_data->totalSamples */ - VGM_ASSERT(sb.stream_samples != ffmpeg_data->totalSamples, "UBI SB: header samples differ\n"); + vgmstream->num_samples = sb->stream_samples; /* ffmpeg_data->totalSamples */ + VGM_ASSERT(sb->stream_samples != ffmpeg_data->totalSamples, "UBI SB: header samples differ\n"); break; } @@ -237,35 +578,202 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { goto fail; } - if (sb.has_internal_names || sb.is_external) { - strcpy(vgmstream->stream_name, sb.stream_name); - } - + strcpy(vgmstream->stream_name, sb->stream_name); /* open the file for reading (can be an external stream, different from the current .sb0) */ if ( !vgmstream_open_stream(vgmstream, streamData, start_offset) ) goto fail; - if (sb.is_external && streamData) close_streamfile(streamData); + if (sb->is_external && streamData) close_streamfile(streamData); return vgmstream; fail: - if (sb.is_external && streamData) close_streamfile(streamData); + if (sb->is_external && streamData) close_streamfile(streamData); close_vgmstream(vgmstream); return NULL; } -static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { +/* debug stuff, for now */ +static void parse_descriptor_subtype(ubi_sb_header * sb, uint32_t descriptor_subtype, off_t offset) { + + /* type may be flags? */ + /* all types may contain memory garbage, making it harder to identify */ + + switch(descriptor_subtype) { + /* standard audio */ + case 0x01: sb->subtypes[0x01]++; break; + + /* audio/garbage? [Splinter Cell: Chaos Theory] */ + /* audio/garbage? [Surf's Up-map] */ + /* audio/garbage? [TMNT-map] */ + /* config? [Brothers in Arms: D-Day] */ + /* config? [Surf's Up-bank] */ + case 0x02: sb->subtypes[0x02]++; break; + + /* audio/garbage? [Splinter Cell: Chaos Theory] */ + /* audio/garbage? [TMNT-map] */ + /* config? [Prince of Persia: The Two Thrones] */ + case 0x03: sb->subtypes[0x03]++; break; + + /* audio/garbage? [Splinter Cell: Chaos Theory] */ + /* audio/garbage? [TMNT-map] */ + /* config? [Rainbow Six 3] */ + /* config? [Prince of Persia: Warrior Within] */ + /* config? [Prince of Persia: The Two Thrones] */ + /* config? [TMNT-bank] */ + /* config? [Surf's Up-map] */ + /* audio/garbage? [Myst IV demo] */ + /* config? [Brothers in Arms: D-Day] */ + /* config? [Surf's Up-bank] */ + case 0x04: sb->subtypes[0x04]++; break; + + /* audio/garbage? [Splinter Cell: Chaos Theory] */ + /* audio/garbage? [TMNT-map] */ + /* config? [Prince of Persia: Warrior Within] */ + /* config? [Prince of Persia: The Two Thrones] */ + /* config? [Prince of Persia: Revelations] */ + /* config? [TMNT-bank] */ + case 0x05: sb->subtypes[0x05]++; break; + + /* layer? [Surf's Up-map] */ + /* layer [TMNT-bank] */ + /* layer [TMNT-map] */ + case 0x06: sb->subtypes[0x06]++; break; + + /* audio/garbage? [Splinter Cell: Chaos Theory] */ + /* config? [Brothers in Arms: D-Day] */ + /* config? [Surf's Up-bank] */ + case 0x07: sb->subtypes[0x07]++; break; + + /* audio/garbage? [Splinter Cell: Chaos Theory] */ + /* audio/garbage? [TMNT-map] */ + /* config? [Prince of Persia: Warrior Within] */ + /* config? [Prince of Persia: The Two Thrones] */ + /* config? [TMNT-bank] */ + /* config? [Surf's Up-map] */ + /* config? [Brothers in Arms: D-Day] */ + /* config? [Surf's Up-bank] */ + case 0x08: sb->subtypes[0x08]++; break; + + /* related to voices? [Prince of Persia: Sands of Time] */ + /* config? [Rainbow Six 3] */ + /* config? [Myst IV demo] */ + case 0x0a: sb->subtypes[0x0a]++; break; + + /* config? [Prince of Persia: Sands of Time] */ + /* config? [Rainbow Six 3] */ + case 0x0c: sb->subtypes[0x0c]++; break; + + /* layer [Prince of Persia: Sands of Time] */ + /* layer [Rainbow Six 3] */ + case 0x0d: sb->subtypes[0x0d]++; break; + + /* config? [Rainbow Six 3] */ + /* config? [Myst IV demo] */ + case 0x0f: sb->subtypes[0x0f]++; break; + + default: + VGM_LOG("UBI SB: unknown subtype %x at %x size %x\n", descriptor_subtype, (uint32_t)offset, sb->section2_entry_size); + break; //goto fail; + } + + //;VGM_ASSERT(descriptor_subtype != 0x01, "UBI SB: subtype %x at %x size %x\n", descriptor_subtype, (uint32_t)offset, sb->section2_entry_size); + + + /* 0x06 layer [TMNT-bank] */ + /* - subtype header: + * 0x1c: external flag? + * 0x20: layers/channels? + * 0x24: layers/channels? + * 0x28: config? same for all + * 0x2c: stream size + * 0x30: stream offset + * 0x38: always 0x037c + * (todo sample rate?) + * + * - layer header at stream_offset: + * 0x00: version? (0x08000B00) + * 0x04: 0x0e? + * 0x08: layers/channels? + * 0x0c: blocks count + * 0x10: block header size + * 0x14: size of header sizes + codec headers + * 0x18: block size + * - per layer: + * 0x00: layer header size + * - per layer + * 0x00~0x20: standard Ubi IMA header (version 0x05) + * + * - blocked data: + * 0x00: always 0x03 + * 0x04: block size + * - per layer: + * 0x00: layer data size (varies between blocks, and one layer may have more than other) + */ + + /* 0x06 layer [TMNT-map] */ + /* - subtype header: + * 0x20: layers/channels? + * 0x24: layers/channels * 2? + * 0x28: config? same for all + * 0x2c: stream size + * 0x30: stream offset + * 0x38: 0x01D0/0118/etc + * 0x40: external flag? + * 0x48: codec? + * 0x54: codec? + * (todo sample rate?) + * + * - layer header at stream_offset: + * - blocked data: + * same as TMNT-bank, but codec header size is 0 + */ + + //todo Surf's Up-map + + /* 0x0d layer [Prince of Persia: Sands of Time] */ + /* 0x0d layer [Rainbow Six 3] */ //todo also check layer header + /* - subtype header (bizarrely but thankfully doesn't change between platforms): + * 0x1c: sample rate * layers + * 0x20: layers/channels? + * 0x2c: external flag? + * 0x30: external name + * 0x58: stream offset + * 0x5c: original rate * layers? + * 0x60: stream size (not including padding) + * 0x64: number of samples + * + * - layer header at stream_offset: + * 0x00: version? (0x04000000) + * 0x04: layers + * 0x08: stream size (not including padding) + * 0x0c: blocks count + * 0x10: block header size + * 0x14: block size + * 0x18: ? + * 0x1c: size of next section? + * - per layer: + * 0x00: layer header size + * codec header per layer + * 0x00~0x20: standard Ubi IMA header (version 0x05) + * + * - blocked data: + * 0x00: block number (from 0x01 to block_count) + * 0x04: current offset (within stream_offset) + * 0x08: always 0x03 + * - per layer: + * 0x00: layer data size (varies between blocks, and one layer may have more than other) + */ + +} + +static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int target_stream) { int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - int i, ok, current_type = -1, current_id = -1; - int target_stream = streamFile->stream_index; + int i, j, k, current_type = -1, current_id = -1, bank_streams = 0, prev_streams; - if (target_stream == 0) target_stream = 1; - - sb->big_endian = check_extensions(streamFile, "sb3,sb6,sb7"); /* GC, PS3, Wii */ if (sb->big_endian) { read_32bit = read_32bitBE; read_16bit = read_16bitBE; @@ -274,83 +782,93 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { read_16bit = read_16bitLE; } - /* file layout is: base header, section1, section2, extra section, section3, data (all except base header can be null) */ - - sb->version = read_32bit(0x00, streamFile); /* 16b+16b major/minor version */ - sb->section1_num = read_32bit(0x04, streamFile); /* group headers? */ - sb->section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */ - sb->section3_num = read_32bit(0x0c, streamFile); /* internal streams table */ - sb->extra_size = read_32bit(0x10, streamFile); /* extra table, unknown (config for non-audio types) except with DSP = coefs */ - sb->flag1 = read_32bit(0x14, streamFile); /* unknown, usually -1 but can be others (0/1/2/etc) */ - sb->flag2 = read_32bit(0x18, streamFile); /* unknown, usually -1 but can be others */ - - ok = config_sb_header_version(sb, streamFile); - if (!ok) { - VGM_LOG("UBI SB: unknown SB version+platform\n"); - goto fail; - } - - sb->main_size = 0x1c; - sb->section1_size = sb->section1_entry_size * sb->section1_num; - sb->section2_size = sb->section2_entry_size * sb->section2_num; - sb->section3_size = sb->section3_entry_size * sb->section3_num; + prev_streams = sb->total_streams; /* find target stream info in section2 */ for (i = 0; i < sb->section2_num; i++) { - off_t offset = sb->main_size + sb->section1_size + sb->section2_entry_size*i; + off_t offset = sb->section2_offset + sb->section2_entry_size*i; + uint32_t descriptor_subtype; - /* ignore non-audio entry (other types seem to have config data) */ - if (read_32bit(offset + 0x04, streamFile) != 0x01) + descriptor_subtype = read_32bit(offset + 0x04, streamFile); + parse_descriptor_subtype(sb, descriptor_subtype, offset); + + /* ignore non-audio entries */ + if (descriptor_subtype != 0x01) continue; - //;VGM_LOG("SB at %lx\n", offset); + //;VGM_LOG("UBI SB: type at %lx\n", offset); /* weird case when there is no internal substream ID and just seem to rotate every time type changes, joy */ if (sb->has_rotating_ids) { /* assumes certain configs can't happen in this case */ int current_is_external = 0; int type = read_32bit(offset + sb->stream_type_offset, streamFile); - if (current_type == -1) - current_type = type; - if (current_id == -1) /* use first ID in section3 */ - current_id = read_32bit(sb->main_size + sb->section1_size + sb->section2_size + sb->extra_size + 0x00, streamFile); - if (sb->external_flag_offset) { current_is_external = read_32bit(offset + sb->external_flag_offset, streamFile); } else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) { current_is_external = 1; /* -1 in extra_name means internal */ } - if (!current_is_external) { - if (current_type != type) { - current_type = type; - current_id++; /* rotate */ - if (current_id >= sb->section3_num) - current_id = 0; /* reset */ - } + if (sb->is_map) { + if (current_type == -1) + current_type = type; + if (current_id == -1) /* they seem to always start with 0 in maps */ + current_id = 0x00; + if (!current_is_external) { + if (current_type != type) { + current_type = type; + current_id++; /* rotate */ + /* we'll warp it around later when parsing section 3 */ + } + } + } else { + if (current_type == -1) + current_type = type; + if (current_id == -1) /* use first ID in section3 */ + current_id = read_32bit(sb->section3_offset + 0x00, streamFile); + + if (!current_is_external) { + if (current_type != type) { + current_type = type; + current_id++; /* rotate */ + if (current_id >= sb->section3_num) + current_id = 0; /* reset */ + } + } + } } } /* update streams (total_stream also doubles as current) */ sb->total_streams++; + bank_streams++; if (sb->total_streams != target_stream) continue; //;VGM_LOG("target at offset=%lx (size=%x)\n", offset, sb->section2_entry_size); + /* parse audio entry based on config */ + sb->header_offset = offset; + sb->header_idx = i; + sb->header_id = read_32bit(offset + 0x00, streamFile); /* 16b+16b group+sound id */ sb->header_type = read_32bit(offset + 0x04, streamFile); - sb->stream_size = read_32bit(offset + 0x08, streamFile); - sb->extra_offset = read_32bit(offset + 0x0c, streamFile); /* within the extra section */ - sb->stream_offset = read_32bit(offset + 0x10, streamFile); /* within the data section */ + sb->stream_size = read_32bit(offset + sb->stream_size_offset, streamFile); + sb->extra_offset = read_32bit(offset + sb->extra_pointer_offset, streamFile) + sb->extra_section_offset; /* within the extra section */ + sb->stream_offset = read_32bit(offset + sb->stream_pointer_offset, streamFile); /* within the data section */ sb->channels = (sb->has_short_channels) ? (uint16_t)read_16bit(offset + sb->channels_offset, streamFile) : (uint32_t)read_32bit(offset + sb->channels_offset, streamFile); sb->sample_rate = read_32bit(offset + sb->sample_rate_offset, streamFile); sb->stream_type = read_32bit(offset + sb->stream_type_offset, streamFile); - if (sb->num_samples_offset) + /* Some games may store number of samples at different locations */ + if (sb->samples_flag_offset && + read_32bit(offset + sb->samples_flag_offset, streamFile) != 0) { + sb->stream_samples = read_32bit(offset + sb->num_samples_offset2, streamFile); + } else if (sb->num_samples_offset) { sb->stream_samples = read_32bit(offset + sb->num_samples_offset, streamFile); + } if (sb-> has_rotating_ids) { sb->stream_id = current_id; @@ -360,10 +878,10 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { /* external stream name can be found in the header (first versions) or the extra table (later versions) */ if (sb->stream_name_offset) { - read_string(sb->stream_name, sb->stream_name_size, offset + sb->stream_name_offset, streamFile); + read_string(sb->extra_name, sb->stream_name_size, offset + sb->stream_name_offset, streamFile); } else { sb->stream_name_offset = read_32bit(offset + sb->extra_name_offset, streamFile); - read_string(sb->stream_name, sb->stream_name_size, sb->main_size + sb->section1_size + sb->section2_size + sb->stream_name_offset, streamFile); + read_string(sb->extra_name, sb->stream_name_size, sb->extra_section_offset + sb->stream_name_offset, streamFile); } /* not always set and must be derived */ @@ -376,23 +894,52 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { } else { sb->autodetect_external = 1; - if (sb->stream_name[0] == '\0') + if (sb->extra_name[0] == '\0') sb->autodetect_external = 0; /* no name */ if (sb->extra_size > 0 && sb->stream_name_offset > sb->extra_size) sb->autodetect_external = 0; /* name outside extra table == is internal */ } - } - if (sb->total_streams == 0) { - VGM_LOG("UBI SB: no streams\n"); - goto fail; - } - if (target_stream < 0 || target_stream > sb->total_streams || sb->total_streams < 1) { - VGM_LOG("UBI SB: wrong target stream (target=%i, total=%i)\n", target_stream, sb->total_streams); - goto fail; + + /* build a full name for stream */ + if (sb->is_map) { + if (sb->extra_name[0]) { + snprintf(sb->stream_name, sizeof(sb->stream_name), "%s/%d/%s", sb->map_name, bank_streams, sb->extra_name); + } else { + snprintf(sb->stream_name, sizeof(sb->stream_name), "%s/%d", sb->map_name, bank_streams); + } + } else { + strncpy(sb->stream_name, sb->extra_name, sizeof(sb->stream_name)); + } } - if (!(sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) { - VGM_LOG("UBI SB: unexpected number of internal streams %i\n", sb->section3_num); +#if 0 + { + int i; + VGM_LOG("UBI subtypes: "); + for (i = 0; i < 16; i++) { + VGM_ASSERT(sb->subtypes[i], "%02x=%i ",i,sb->subtypes[i]); + } + VGM_LOG("\n"); + } +#endif + + if (sb->is_map) { + if (bank_streams == 0 || target_stream <= prev_streams || target_stream > sb->total_streams) + return 1; /* Target stream is not in this map */ + } else { + if (sb->total_streams == 0) { + VGM_LOG("UBI SB: no streams\n"); + goto fail; + } + + if (target_stream < 0 || target_stream > sb->total_streams) { + VGM_LOG("UBI SB: wrong target stream (target=%i, total=%i)\n", target_stream, sb->total_streams); + goto fail; + } + } + + if (!(sb->stream_id_offset || sb->has_rotating_ids || sb->is_map) && sb->section3_num > 1) { + VGM_LOG("UBI SB: unexpected number of internal stream groups %i\n", sb->section3_num); goto fail; } @@ -404,21 +951,47 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { } /* guess codec */ - switch(sb->stream_type) { + switch (sb->stream_type) { case 0x00: /* platform default (rarely external) */ - if ( check_extensions(streamFile, "sb0")) { - sb->codec = RAW_PCM; - } else if (check_extensions(streamFile, "sb1,sb5")) { - sb->codec = RAW_PSX; - } else if (check_extensions(streamFile, "sb2")) { - sb->codec = RAW_XBOX; - } else if (check_extensions(streamFile, "sb3,sb7")) { - sb->codec = RAW_DSP; - } else if (check_extensions(streamFile, "sb4")) { - sb->codec = FMT_VAG; - } else { - VGM_LOG("UBI SB: unknown internal format\n"); - goto fail; + switch (sb->platform) { + case UBI_PC: + sb->codec = RAW_PCM; + break; + + case UBI_PS2: + sb->codec = RAW_PSX; + break; + + case UBI_PSP: + if (check_extensions(streamFile, "sb4,sm4")) { + sb->codec = FMT_VAG; + } else { + sb->codec = RAW_PSX; + } + break; + + case UBI_XBOX: + sb->codec = RAW_XBOX; + break; + + case UBI_GC: + case UBI_WII: + sb->codec = RAW_DSP; + break; + + case UBI_X360: + sb->codec = RAW_XMA1; + break; +#if 0 + case UBI_PS3: + /* Need to confirm */ + sb->codec = RAW_AT3; + break; +#endif + default: + VGM_LOG("UBI SB: unknown internal format\n"); + goto fail; + } break; @@ -426,6 +999,10 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { sb->codec = RAW_PCM; break; + case 0x02: /* PS ADPCM (PS3) */ + sb->codec = RAW_PSX; + break; + case 0x03: /* Ubi ADPCM (main external stream codec, has subtypes) */ sb->codec = UBI_ADPCM; break; @@ -434,7 +1011,30 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { sb->codec = FMT_OGG; break; - case 0x05: /* AT3 (PSP, PS3) */ + case 0x05: /* AT3 (PSP, PS3) or XMA1 (X360) */ + switch (sb->platform) { + case UBI_X360: + sb->codec = FMT_XMA1; + break; + case UBI_PS3: + case UBI_PSP: + sb->codec = FMT_AT3; + break; + default: + VGM_LOG("UBI SB: unknown codec for stream_type %x\n", sb->stream_type); + goto fail; + } + break; + + case 0x06: /* PS ADPCM (later PS3 games?) */ + sb->codec = RAW_PSX; + break; + + case 0x07: + sb->codec = RAW_AT3; + break; + + case 0x08: sb->codec = FMT_AT3; break; @@ -443,21 +1043,76 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { goto fail; } + if (sb->codec == RAW_XMA1) { + /* this field is only seen in X360 games, points at XMA1 header in extra section */ + sb->xma_header_offset = read_32bit(sb->header_offset + sb->xma_pointer_offset, streamFile) + sb->extra_section_offset; + } + /* uncommon but possible */ //VGM_ASSERT(sb->is_external && sb->section3_num != 0, "UBI SS: mixed external and internal streams\n"); /* seems that can be safely ignored */ //VGM_ASSERT(sb->is_external && sb->stream_id_offset && sb->stream_id > 0, "UBI SB: unexpected external stream with stream id\n"); - /* section 3: substreams within the file, adjust stream offset (rarely used but table is always present) */ - if (!sb->is_external && (sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) { - for (i = 0; i < sb->section3_num; i++) { - off_t offset = sb->main_size + sb->section1_size + sb->section2_size + sb->extra_size + sb->section3_entry_size * i; + /* section 3: internal stream info */ + if (!sb->is_external) { + if (sb->is_map) { + /* maps store internal sounds offsets in a separate table, find the matching entry */ + for (i = 0; i < sb->section3_num; i++) { + off_t offset = sb->section3_offset + 0x14 * i; + off_t table_offset = read_32bit(offset + 0x04, streamFile) + sb->section3_offset; + uint32_t table_num = read_32bit(offset + 0x08, streamFile); + off_t table2_offset = read_32bit(offset + 0x0c, streamFile) + sb->section3_offset; + uint32_t table2_num = read_32bit(offset + 0x10, streamFile); - /* table has unordered ids+size, so if our id doesn't match current data offset must be beyond */ - if (read_32bit(offset + 0x00, streamFile) == sb->stream_id) - break; - sb->stream_offset += read_32bit(offset + 0x04, streamFile); + for (j = 0; j < table_num; j++) { + int idx = read_32bit(table_offset + 0x08 * j + 0x00, streamFile) & 0x0000FFFF; + + if (idx == sb->header_idx) { + if (!(sb->stream_id_offset || sb->has_rotating_ids) && table2_num > 1) { + VGM_LOG("UBI SB: unexpected number of internal stream groups %i\n", table2_num); + goto fail; + } + + if (sb->has_rotating_ids) { + sb->stream_id %= table2_num; + } + + sb->stream_offset = read_32bit(table_offset + 0x08 * j + 0x04, streamFile); + for (k = 0; k < table2_num; k++) { + /* entry layout: + * 0x00 - group ID + * 0x04 - size with padding included + * 0x08 - size without padding + * 0x0c - absolute offset */ + uint32_t id = read_32bit(table2_offset + 0x10 * k + 0x00, streamFile); + if (id == sb->stream_id) { + sb->stream_offset += read_32bit(table2_offset + 0x10 * k + 0x0c, streamFile); + break; + } + } + break; + } + } + + if (sb->stream_offset) + break; + } + } else { + sb->stream_offset += sb->sounds_offset; + + if ((sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) { + /* internal sounds are split into groups based on their type with their offsets being relative to group start + * this table contains sizes of each group, adjust offset based on group ID of our sound */ + for (i = 0; i < sb->section3_num; i++) { + off_t offset = sb->section3_offset + sb->section3_entry_size * i; + + /* table has unordered ids+size, so if our id doesn't match current data offset must be beyond */ + if (read_32bit(offset + 0x00, streamFile) == sb->stream_id) + break; + sb->stream_offset += read_32bit(offset + 0x04, streamFile); + } + } } } @@ -468,15 +1123,6 @@ fail: static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) { - /* meh... */ - int is_sb0 = check_extensions(streamFile, "sb0"); /* PC */ - int is_sb1 = check_extensions(streamFile, "sb1"); /* PS2 */ - int is_sb2 = check_extensions(streamFile, "sb2"); /* Xbox */ - int is_sb3 = check_extensions(streamFile, "sb3"); /* GC */ - int is_sb4 = check_extensions(streamFile, "sb4"); /* PSP, X360? */ - int is_sb5 = check_extensions(streamFile, "sb5"); /* PSP, 3DS? */ - //int is_sb6 = check_extensions(streamFile, "sb6"); /* PS3? */ - int is_sb7 = check_extensions(streamFile, "sb7"); /* Wii */ int is_biadd_psp = 0; @@ -500,9 +1146,73 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section3_entry_size = 0x08; sb->stream_name_size = 0x24; /* maybe 0x28 or 0x20 for some but ok enough (null terminated) */ - /* Prince of Persia: Sands of Time (2003)(PC) */ - if ((sb->version == 0x000A0002 && is_sb0) || /* (not sure if exists, just in case) */ - (sb->version == 0x000A0004 && is_sb0)) { /* main game */ + /* this is same in all games since ~2003 */ + sb->stream_size_offset = 0x08; + sb->extra_pointer_offset = 0x0c; + sb->stream_pointer_offset = 0x10; + +#if 0 + /* Donald Duck: Goin' Quackers (2002)(GC)-map */ + if (sb->version == 0x00000003 && sb->platform == UBI_GC) { + /* Stream types: + * 0x01: Nintendo DSP ADPCM + * 0x08: unsupported codec, looks like standard IMA with custom 0x29 bytes header + */ + sb->section1_entry_size = 0x40; + sb->section2_entry_size = 0x6c; + + sb->map_version = 1; + + sb->stream_size_offset = 0x0c; + sb->extra_pointer_offset = 0x10; + sb->stream_pointer_offset = 0x14; + + sb->external_flag_offset = 0x30; + sb->stream_id_offset = 0x34; + sb->num_samples_offset = 0x48; + sb->sample_rate_offset = 0x50; + sb->channels_offset = 0x56; + sb->stream_type_offset = 0x58; + sb->stream_name_offset = 0x5c; + + sb->has_short_channels = 1; + return 1; + } + + /* Splinter Cell (2002)(PC)-map */ + /* Splinter Cell: Pandora Tomorrow (2004)(PC)-map */ + if (sb->version == 0x00000007 && sb->platform == UBI_PC) { + /* Stream types: + * 0x01: PCM + * 0x02: unsupported codec, appears to be another version of Ubi IMA + * 0x04: Ubi IMA v3 (not Vorbis) + */ + sb->section1_entry_size = 0x58; + sb->section2_entry_size = 0x80; + + sb->map_version = 1; + + sb->stream_size_offset = 0x0c; + sb->extra_pointer_offset = 0x10; + sb->stream_pointer_offset = 0x14; + + sb->external_flag_offset = 0x28; + sb->stream_id_offset = 0x2c; + sb->num_samples_offset = 0x30; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4a; + sb->stream_type_offset = 0x4c; + sb->stream_name_offset = 0x50; + + sb->has_short_channels = 1; + sb->has_internal_names = 1; + return 1; + } +#endif + + /* Prince of Persia: Sands of Time (2003)(PC)-bank */ + if ((sb->version == 0x000A0002 && sb->platform == UBI_PC) || /* (not sure if exists, just in case) */ + (sb->version == 0x000A0004 && sb->platform == UBI_PC)) { /* main game */ sb->section1_entry_size = 0x64; sb->section2_entry_size = 0x80; @@ -518,9 +1228,9 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Sands of Time (2003)(PS2) */ - if ((sb->version == 0x000A0002 && is_sb1) || /* Prince of Persia 1 port */ - (sb->version == 0x000A0004 && is_sb1)) { /* main game */ + /* Prince of Persia: Sands of Time (2003)(PS2)-bank */ + if ((sb->version == 0x000A0002 && sb->platform == UBI_PS2) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && sb->platform == UBI_PS2)) { /* main game */ sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; @@ -534,9 +1244,9 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Sands of Time (2003)(Xbox) */ - if ((sb->version == 0x000A0002 && is_sb2) || /* Prince of Persia 1 port */ - (sb->version == 0x000A0004 && is_sb2)) { /* main game */ + /* Prince of Persia: Sands of Time (2003)(Xbox)-bank */ + if ((sb->version == 0x000A0002 && sb->platform == UBI_XBOX) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && sb->platform == UBI_XBOX)) { /* main game */ sb->section1_entry_size = 0x64; sb->section2_entry_size = 0x78; @@ -552,8 +1262,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Tom Clancy's Rainbow Six 3 (2003)(PS2) */ - if (sb->version == 0x000A0007 && is_sb1) { + /* Tom Clancy's Rainbow Six 3 (2003)(PS2)-bank */ + if (sb->version == 0x000A0007 && sb->platform == UBI_PS2) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; @@ -567,9 +1277,9 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Sands of Time (2003)(GC) */ - if ((sb->version == 0x000A0002 && is_sb3) || /* Prince of Persia 1 port */ - (sb->version == 0x000A0004 && is_sb3)) { /* main game */ + /* Prince of Persia: Sands of Time (2003)(GC)-bank */ + if ((sb->version == 0x000A0002 && sb->platform == UBI_GC) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && sb->platform == UBI_GC)) { /* main game */ sb->section1_entry_size = 0x64; sb->section2_entry_size = 0x74; @@ -584,8 +1294,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Myst IV Demo (2004)(PC) (final game is different) */ - if (sb->version == 0x00100000 && is_sb0) { + /* Myst IV Demo (2004)(PC) (final game is different)-bank */ + if (sb->version == 0x00100000 && sb->platform == UBI_PC) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0xa4; @@ -600,8 +1310,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Warrior Within (2004)(PC) */ - if (sb->version == 0x00120009 && is_sb0) { + /* Prince of Persia: Warrior Within (2004)(PC)-bank */ + if (sb->version == 0x00120009 && sb->platform == UBI_PC) { sb->section1_entry_size = 0x6c; sb->section2_entry_size = 0x84; @@ -616,8 +1326,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Warrior Within (2004)(PS2) */ - if (sb->version == 0x00120009 && is_sb1) { + /* Prince of Persia: Warrior Within (2004)(PS2)-bank */ + if (sb->version == 0x00120009 && sb->platform == UBI_PS2) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; @@ -631,8 +1341,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Warrior Within (2004)(Xbox) */ - if (sb->version == 0x00120009 && is_sb2) { + /* Prince of Persia: Warrior Within (2004)(Xbox)-bank */ + if (sb->version == 0x00120009 && sb->platform == UBI_XBOX) { sb->section1_entry_size = 0x6c; sb->section2_entry_size = 0x90; @@ -647,8 +1357,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: Warrior Within (2004)(GC) */ - if (sb->version == 0x00120009 && is_sb3) { + /* Prince of Persia: Warrior Within (2004)(GC)-bank */ + if (sb->version == 0x00120009 && sb->platform == UBI_GC) { sb->section1_entry_size = 0x6c; sb->section2_entry_size = 0x78; @@ -663,7 +1373,7 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) } /* two games with same id; use project file as identifier */ - if (sb->version == 0x0012000C && is_sb4) { + if (sb->version == 0x0012000C && sb->platform == UBI_PSP) { STREAMFILE * streamTest = open_streamfile_by_filename(streamFile, "BIAAUDIO.SP4"); if (streamTest) { is_biadd_psp = 1; @@ -671,11 +1381,14 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) } } - /* Prince of Persia: Revelations (2005)(PSP) */ - if (sb->version == 0x0012000C && is_sb4 && !is_biadd_psp) { + /* Prince of Persia: Revelations (2005)(PSP)-bank */ + /* Splinter Cell: Essentials (2006)(PSP)-map */ + if (sb->version == 0x0012000C && sb->platform == UBI_PSP && !is_biadd_psp) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x84; + sb->map_version = 2; + sb->external_flag_offset = 0x24; sb->num_samples_offset = 0x30; sb->sample_rate_offset = 0x44; @@ -687,14 +1400,16 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Brothers in Arms - D-Day (2006)(PSP) */ - if (sb->version == 0x0012000C && is_sb4 && is_biadd_psp) { + /* Brothers in Arms - D-Day (2006)(PSP)-bank */ + if (sb->version == 0x0012000C && sb->platform == UBI_PSP && is_biadd_psp) { sb->section1_entry_size = 0x80; sb->section2_entry_size = 0x94; - sb->stream_id_offset = 0x0; //todo 0x1C or 0x20? table seems problematic + sb->stream_id_offset = 0x2c; sb->external_flag_offset = 0x24; - sb->num_samples_offset = 0; /* variable? */ + sb->samples_flag_offset = 0x28; + sb->num_samples_offset = 0x30; + sb->num_samples_offset2 = 0x38; sb->sample_rate_offset = 0x44; sb->channels_offset = 0x4c; sb->stream_type_offset = 0x50; @@ -704,8 +1419,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: The Two Thrones (2005)(PC) */ - if (sb->version == 0x00150000 && is_sb0) { + /* Prince of Persia: The Two Thrones (2005)(PC)-bank */ + if (sb->version == 0x00150000 && sb->platform == UBI_PC) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x78; @@ -721,8 +1436,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: The Two Thrones (2005)(PS2) */ - if (sb->version == 0x00150000 && is_sb1) { + /* Prince of Persia: The Two Thrones (2005)(PS2)-bank */ + if (sb->version == 0x00150000 && sb->platform == UBI_PS2) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x5c; @@ -737,8 +1452,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: The Two Thrones (2005)(Xbox) */ - if (sb->version == 0x00150000 && is_sb2) { + /* Prince of Persia: The Two Thrones (2005)(Xbox)-bank */ + if (sb->version == 0x00150000 && sb->platform == UBI_XBOX) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x58; @@ -755,8 +1470,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Prince of Persia: The Two Thrones (2005)(GC) */ - if (sb->version == 0x00150000 && is_sb3) { + /* Prince of Persia: The Two Thrones (2005)(GC)-bank */ + if (sb->version == 0x00150000 && sb->platform == UBI_GC) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x6c; @@ -769,9 +1484,47 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } + + /* Splinter Cell: Chaos Theory (2005)(PC)-map */ + if (sb->version == 0x00120012 && sb->platform == UBI_PC) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x60; + + sb->map_version = 2; + + sb->external_flag_offset = 0x24; + sb->num_samples_offset = 0x30; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4c; + sb->stream_type_offset = 0x50; + sb->extra_name_offset = 0x54; + + return 1; + } + + /* Splinter Cell: Chaos Theory (2005)(Xbox)-map */ + if (sb->version == 0x00120012 && sb->platform == UBI_XBOX) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x4c; + + sb->map_version = 2; + + sb->external_flag_offset = 0; + sb->num_samples_offset = 0x18; + sb->stream_id_offset = 0; + sb->sample_rate_offset = 0x30; + sb->channels_offset = 0x38; + sb->stream_type_offset = 0x3c; + sb->extra_name_offset = 0x40; + + sb->has_extra_name_flag = 1; + sb->has_rotating_ids = 1; + return 1; + } + #if 0 - /* Far cry: Instincts - Evolution (2006)(Xbox) */ - if (sb->version == 0x00170000 && is_sb2) { + /* Far cry: Instincts - Evolution (2006)(Xbox)-bank */ + if (sb->version == 0x00170000 && sb->platform == UBI_XBOX) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; @@ -787,8 +1540,101 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) } #endif - /* Prince of Persia: Rival Swords (2007)(PSP) */ - if (sb->version == 0x00180005 && is_sb5) { + /* Red Steel (2006)(Wii)-bank */ + if (sb->version == 0x00180006 && sb->platform == UBI_WII) { /* same as 0x00150000 */ + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x6c; + + sb->external_flag_offset = 0x28; /* maybe 0x2c */ + sb->num_samples_offset = 0x3c; + sb->sample_rate_offset = 0x50; + sb->channels_offset = 0x58; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x60; + + return 1; + } + + /* Splinter Cell: Double Agent (2006)(PC)-map */ + if (sb->version == 0x00180006 && sb->platform == UBI_PC) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x7c; + + sb->map_version = 3; + + sb->external_flag_offset = 0x2c; + sb->stream_id_offset = 0x34; + sb->channels_offset = 0x5c; + sb->sample_rate_offset = 0x54; + sb->num_samples_offset = 0x40; + sb->num_samples_offset2 = 0x48; + sb->stream_type_offset = 0x60; + sb->extra_name_offset = 0x64; + + return 1; + } + + /* Splinter Cell: Double Agent (2006)(X360)-map */ + if (sb->version == 0x00180006 && sb->platform == UBI_X360) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x78; + + sb->map_version = 3; + + sb->external_flag_offset = 0x2c; + sb->stream_id_offset = 0x30; + sb->samples_flag_offset = 0x34; + sb->channels_offset = 0x5c; + sb->sample_rate_offset = 0x54; + sb->num_samples_offset = 0x40; + sb->num_samples_offset2 = 0x48; + sb->stream_type_offset = 0x60; + sb->extra_name_offset = 0x64; + sb->xma_pointer_offset = 0x70; + + return 1; + } + + /* Splinter Cell: Double Agent (2006)(Xbox)-map */ + if (sb->version == 0x00160002 && sb->platform == UBI_XBOX) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x58; + + sb->map_version = 3; + + sb->external_flag_offset = 0; + sb->num_samples_offset = 0x28; + sb->stream_id_offset = 0; + sb->sample_rate_offset = 0x3c; + sb->channels_offset = 0x44; + sb->stream_type_offset = 0x48; + sb->extra_name_offset = 0x4c; + + sb->has_extra_name_flag = 1; + sb->has_rotating_ids = 1; + return 1; + } + + /* Splinter Cell: Double Agent (2006)(GC)-map */ + if (sb->version == 0x00160002 && sb->platform == UBI_GC) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x6c; + + sb->map_version = 3; + + sb->external_flag_offset = 0x28; + sb->stream_id_offset = 0x2c; + sb->num_samples_offset = 0x3c; + sb->sample_rate_offset = 0x50; + sb->channels_offset = 0x58; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x60; + + return 1; + } + + /* Prince of Persia: Rival Swords (2007)(PSP)-bank */ + if (sb->version == 0x00180005 && sb->platform == UBI_PSP) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x54; @@ -804,8 +1650,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) } #if 0 - /* Rainbow Six Vegas (2007)(PSP) */ - if (sb->version == 0x00180006 && is_sb5) { + /* Rainbow Six Vegas (2007)(PSP)-bank */ + if (sb->version == 0x00180006 && sb->platform == UBI_PSP) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x54; @@ -833,23 +1679,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) */ #endif - /* Red Steel (2006)(Wii) */ - if (sb->version == 0x00180006 && is_sb7) { /* same as 0x00150000 */ - sb->section1_entry_size = 0x68; - sb->section2_entry_size = 0x6c; - - sb->external_flag_offset = 0x28; /* maybe 0x2c */ - sb->num_samples_offset = 0x3c; - sb->sample_rate_offset = 0x50; - sb->channels_offset = 0x58; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x60; - - return 1; - } - - /* Prince of Persia: Rival Swords (2007)(Wii) */ - if (sb->version == 0x00190003 && is_sb7) { + /* Prince of Persia: Rival Swords (2007)(Wii)-bank */ + if (sb->version == 0x00190003 && sb->platform == UBI_WII) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x70; @@ -862,9 +1693,25 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } + + /* TMNT (2007)(PC)-bank */ + if (sb->version == 0x00190002 && sb->platform == UBI_PC) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x74; - /* TMNT (2007)(PS2) */ - if (sb->version == 0x00190002 && is_sb1) { + sb->external_flag_offset = 0x28; + sb->stream_id_offset = 0x2c; + sb->channels_offset = 0x3c; + sb->sample_rate_offset = 0x40; + sb->num_samples_offset = 0x48; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x58; + + return 1; + } + + /* TMNT (2007)(PS2)-bank */ + if (sb->version == 0x00190002 && sb->platform == UBI_PS2) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x5c; @@ -879,8 +1726,8 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* TMNT (2007)(GC) */ - if (sb->version == 0x00190002 && is_sb3) { /* same as 0x00190003 */ + /* TMNT (2007)(GC)-bank */ + if (sb->version == 0x00190002 && sb->platform == UBI_GC) { /* same as 0x00190003 */ sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x6c; @@ -894,8 +1741,44 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } - /* Surf's Up (2007)(PC) */ - if (sb->version == 0x00190005 && is_sb0) { + /* TMNT (2007)(X360)-bank */ + if (sb->version == 0x00190002 && sb->platform == UBI_X360) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x70; + + sb->external_flag_offset = 0x28; + sb->samples_flag_offset = 0x30; + sb->channels_offset = 0x3c; + sb->sample_rate_offset = 0x40; + sb->num_samples_offset = 0x48; + sb->num_samples_offset2 = 0x50; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x58; + sb->xma_pointer_offset = 0x6c; + + return 1; + } + + /* TMNT (2007)(PSP)-map */ + if (sb->version == 0x00190001 && sb->platform == UBI_PSP) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x58; + + sb->map_version = 3; + + sb->external_flag_offset = 0; + sb->channels_offset = 0x28; + sb->sample_rate_offset = 0x2c; + sb->num_samples_offset = 0x34; + sb->stream_type_offset = 0x48; + sb->extra_name_offset = 0x44; + + sb->has_extra_name_flag = 1; + return 1; + } + + /* Surf's Up (2007)(PC)-bank */ + if (sb->version == 0x00190005 && sb->platform == UBI_PC) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x74; @@ -906,9 +1789,83 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->stream_type_offset = 0x5c; sb->extra_name_offset = 0x58; + return 1; + } + + /* Surf's Up (2007)(PS3)-bank */ + /* Splinter Cell: Double Agent (2007)(PS3)-map */ + if (sb->version == 0x00190005 && sb->platform == UBI_PS3) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x70; + + sb->map_version = 3; + + sb->external_flag_offset = 0x28; + sb->stream_id_offset = 0x2c; + sb->channels_offset = 0x3c; + sb->sample_rate_offset = 0x40; + sb->num_samples_offset = 0x48; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x58; + + return 1; + } + + /* Surf's Up (2007)(X360)-bank */ + if (sb->version == 0x00190005 && sb->platform == UBI_X360) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x70; + + sb->external_flag_offset = 0x28; + sb->samples_flag_offset = 0x30; + sb->channels_offset = 0x3c; + sb->sample_rate_offset = 0x40; + sb->num_samples_offset = 0x48; + sb->num_samples_offset2 = 0x50; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x58; + sb->xma_pointer_offset = 0x6c; + + return 1; + } + + /* Surf's Up (2007)(PSP)-map */ + if (sb->version == 0x00190005 && sb->platform == UBI_PSP) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x58; + + sb->map_version = 3; + + sb->external_flag_offset = 0; + sb->channels_offset = 0x28; + sb->sample_rate_offset = 0x2c; + sb->num_samples_offset = 0x34; + sb->stream_type_offset = 0x48; + sb->extra_name_offset = 0x44; + sb->has_extra_name_flag = 1; return 1; } + /* Splinter Cell Classic Trilogy HD (2011)(PS3)-map */ + if (sb->version == 0x001d0000 && sb->platform == UBI_PS3) { + sb->section1_entry_size = 0x5c; + sb->section2_entry_size = 0x80; + + sb->map_version = 3; + + sb->external_flag_offset = 0x28; + sb->stream_id_offset = 0x30; + sb->samples_flag_offset = 0x34; + sb->channels_offset = 0x44; + sb->sample_rate_offset = 0x4c; + sb->num_samples_offset = 0x54; + sb->num_samples_offset2 = 0x5c; + sb->stream_type_offset = 0x68; + sb->extra_name_offset = 0x64; + + return 1; + } + return 0; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c b/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c index 6e13f5a72..b3a3e489d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c @@ -26,11 +26,6 @@ VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) { /* 0x0f(2): frame count */ loop_flag = 0; - /* UE4Opus encodes 60ms (music) or 120ms (voice) frames, and encoder delay seems 1/8 - * of samples per frame (may be more complex but wave looks ok-ish) */ - //todo does UE4 actually care about encoder delay? - skip = (60 * 48000 / 1000) / 8; /* 48000 is the internal/resampled rate */ - start_offset = 0x11; data_size = get_streamfile_size(streamFile) - start_offset; @@ -41,18 +36,17 @@ VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) { vgmstream->meta_type = meta_UE4OPUS; vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples - skip; #ifdef VGM_USE_FFMPEG { + /* usually uses 60ms for music (delay of 360 samples) */ + skip = ue4_opus_get_encoder_delay(start_offset, streamFile); + vgmstream->num_samples = num_samples - skip; + vgmstream->codec_data = init_ffmpeg_ue4_opus(streamFile, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - - if (vgmstream->num_samples == 0) { - vgmstream->num_samples = ue4_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile) - skip; - } } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vawx.c b/Frameworks/vgmstream/vgmstream/src/meta/vawx.c index 02a689ca8..8771cc6be 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vawx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vawx.c @@ -36,9 +36,9 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { vgmstream->meta_type = meta_VAWX; switch(codec) { - case 2: /* VAG */ + case 2: /* PS-ADPCM */ vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave ; + vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave; vgmstream->interleave_block_size = 0x10; vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); @@ -66,6 +66,8 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile); + /* may be only applying end_skip to num_samples? */ + xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); break; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vs.c b/Frameworks/vgmstream/vgmstream/src/meta/vs.c index d36aee6f3..57589cff0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vs.c @@ -1,75 +1,52 @@ #include "meta.h" #include "../layout/layout.h" -#include "../util.h" +#include "../coding/coding.h" -/* VS (from Men in Black) */ +/* .VS - from Melbourne House games [Men in Black II (PS2), Grand Prix Challenge (PS2) */ VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - - char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag = 0; - int channel_count; - int i; + int loop_flag, channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("vs",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0xC8000000) /* "0xC8000000" */ + /* checks */ + if (!check_extensions(streamFile, "vs")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0xC8000000) goto fail; loop_flag = 0; channel_count = 2; - - /* build the VGMSTREAM */ + start_offset = 0x08; + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x08; - vgmstream->channels = channel_count; - vgmstream->interleave_block_size=0x10; + vgmstream->meta_type = meta_VS; vgmstream->sample_rate = read_32bitLE(0x04,streamFile); vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_vs; -#if 0 - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-start_offset); - } -#endif + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; - vgmstream->layout_type = layout_blocked_vs; - vgmstream->meta_type = meta_VS; - - - /* open the file for reading */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[i].streamfile) goto fail; + /* calc num_samples */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); } + while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); + block_update(start_offset, vgmstream); + } - - /* Calc num_samples */ - block_update_vs(start_offset,vgmstream); - vgmstream->num_samples=0; - - do { - vgmstream->num_samples += vgmstream->current_block_size*28/16; - block_update_vs(vgmstream->next_block_offset,vgmstream); - } while (vgmstream->next_block_offsetmeta_type = meta_VS_SQUARE; + vgmstream->sample_rate = round10((48000 * pitch) / 4096); /* needed for rare files */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_vs_square; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + + /* calc num_samples */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); + } + while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); + block_update(start_offset, vgmstream); + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_strlr.c b/Frameworks/vgmstream/vgmstream/src/meta/vs_str.c similarity index 87% rename from Frameworks/vgmstream/vgmstream/src/meta/ps2_strlr.c rename to Frameworks/vgmstream/vgmstream/src/meta/vs_str.c index 83770fc47..a6002b364 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_strlr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vs_str.c @@ -3,7 +3,7 @@ #include "../coding/coding.h" /* .vs/STRx - from The Bouncer (PS2) */ -VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; int channel_count, loop_flag; off_t start_offset; @@ -29,10 +29,10 @@ VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE *streamFile) { vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_PS2_STRLR; + vgmstream->meta_type = meta_VS_STR; vgmstream->sample_rate = 44100; vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_blocked_ps2_strlr; + vgmstream->layout_type = layout_blocked_vs_str; if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c index f78b12425..0a17ccd45 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c @@ -19,6 +19,7 @@ typedef struct { size_t fmt_size; off_t data_offset; size_t data_size; + off_t chunk_offset; /* standard fmt stuff */ wwise_codec codec; @@ -104,9 +105,9 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { ww.format = (uint16_t)read_16bit(ww.fmt_offset+0x00,streamFile); if (ww.format == 0x0165) { /* XMA2WAVEFORMAT (always "fmt"+"XMA2", unlike .xma that may only have "XMA2") */ - off_t xma2_offset; - if (!find_chunk(streamFile, 0x584D4132,first_offset,0, &xma2_offset,NULL, ww.big_endian, 0)) goto fail; - xma2_parse_xma2_chunk(streamFile, xma2_offset,&ww.channels,&ww.sample_rate, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample); + if (!find_chunk(streamFile, 0x584D4132,first_offset,0, &ww.chunk_offset,NULL, ww.big_endian, 0)) + goto fail; + xma2_parse_xma2_chunk(streamFile, ww.chunk_offset,&ww.channels,&ww.sample_rate, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample); } else { /* WAVEFORMATEX */ ww.channels = read_16bit(ww.fmt_offset+0x02,streamFile); ww.sample_rate = read_32bit(ww.fmt_offset+0x04,streamFile); @@ -122,9 +123,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { /* find loop info */ if (ww.format == 0x0166) { /* XMA2WAVEFORMATEX */ - xma2_parse_fmt_chunk_extra(streamFile, ww.fmt_offset, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample, ww.big_endian); + ww.chunk_offset = ww.fmt_offset; + xma2_parse_fmt_chunk_extra(streamFile, ww.chunk_offset, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample, ww.big_endian); } - else if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl". common */ + else if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl", common */ if (loop_size >= 0x34 && read_32bit(loop_offset+0x1c, streamFile)==1 /*loop count*/ && read_32bit(loop_offset+0x24+4, streamFile)==0) { @@ -139,7 +141,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { //} /* other Wwise specific: */ - //"JUNK": optional padding for usually aligment (0-size JUNK exists too) + //"JUNK": optional padding for aligment (0-size JUNK exists too) //"akd ": seem to store extra info for Wwise editor (wave peaks/loudness/HDR envelope?) } @@ -147,13 +149,14 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { switch(ww.format) { case 0x0001: ww.codec = PCM; break; /* older Wwise */ case 0x0002: ww.codec = IMA; break; /* newer Wwise (conflicts with MSADPCM, probably means "platform's ADPCM") */ - //case 0x0011: ww.codec = IMA; break; /* older Wwise (used?) */ + //case 0x0011: ww.codec = IMA; break; /* older Wwise (used?) */ case 0x0069: ww.codec = IMA; break; /* older Wwise (Spiderman Web of Shadows X360, LotR Conquest PC) */ case 0x0161: ww.codec = XWMA; break; /* WMAv2 */ case 0x0162: ww.codec = XWMA; break; /* WMAPro */ case 0x0165: ww.codec = XMA2; break; /* always with the "XMA2" chunk, Wwise doesn't use XMA1 */ case 0x0166: ww.codec = XMA2; break; - case 0x3039: ww.codec = OPUS; break; + case 0x3039: ww.codec = OPUS; break; /* later renamed to "OPUSNX" */ + //case 0x3040: ww.codec = OPUS; break; /* same for other platforms, supposedly */ case 0xAAC0: ww.codec = AAC; break; case 0xFFF0: ww.codec = DSP; break; case 0xFFFB: ww.codec = HEVAG; break; @@ -161,7 +164,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { case 0xFFFE: ww.codec = PCM; break; /* "PCM for Wwise Authoring" */ case 0xFFFF: ww.codec = VORBIS; break; default: - VGM_LOG("WWISE: unknown codec 0x%x \n", ww.format); goto fail; } @@ -184,7 +186,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { * We'll add basic support to avoid complaints of this or that .wem not playing */ if (ww.data_size > ww.file_size) { //VGM_LOG("WWISE: truncated data size (prefetch): (real=0x%x > riff=0x%x)\n", ww.data_size, ww.file_size); - if (ww.codec == IMA || ww.codec == VORBIS) /* only seen those, probably others exist */ + if (ww.codec == IMA || ww.codec == VORBIS || ww.codec == XMA2) /* only seen those, probably others exist */ ww.truncated = 1; else goto fail; @@ -228,8 +230,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { vgmstream->interleave_block_size = ww.block_align / ww.channels; vgmstream->codec_endian = ww.big_endian; - if (ww.truncated) /* enough to get real samples */ + /* enough to get real samples */ + if (ww.truncated) { ww.data_size = ww.file_size - ww.data_offset; + } vgmstream->num_samples = xbox_ima_bytes_to_samples(ww.data_size, ww.channels); break; @@ -247,7 +251,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { if (ww.block_align != 0 || ww.bits_per_sample != 0) goto fail; /* always 0 for Worbis */ - /* autodetect format (field are mostly common, see the end of the file) */ + /* autodetect format (fields are mostly common, see the end of the file) */ if (find_chunk(streamFile, 0x766F7262,first_offset,0, &vorb_offset,&vorb_size, ww.big_endian, 0)) { /*"vorb"*/ /* older Wwise (~<2012) */ @@ -270,7 +274,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { cfg.setup_type = WWV_EXTERNAL_CODEBOOKS; /* setup_type will be corrected later */ break; - case 0x2a: /* uncommon (mid 2011), [inFamous 2 (PS3)] */ + case 0x2a: /* uncommon (mid 2011) [inFamous 2 (PS3)] */ data_offsets = 0x10; block_offsets = 0x28; cfg.header_type = WWV_TYPE_2; @@ -293,9 +297,9 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { ww.data_size -= audio_offset; /* detect setup type: - * - full inline: ~2009, ex. The King of Fighters XII X360, The Saboteur PC - * - trimmed inline: ~2010, ex. Army of Two: 40 days X360 (some multiplayer files) - * - external: ~2010, ex. Assassin's Creed Brotherhood X360, Dead Nation X360 */ + * - full inline: ~2009, ex. The King of Fighters XII (X360), The Saboteur (PC) + * - trimmed inline: ~2010, ex. Army of Two: 40 days (X360) some multiplayer files + * - external: ~2010, ex. Assassin's Creed Brotherhood (X360), Dead Nation (X360) */ if (vorb_size == 0x34) { size_t setup_size = (uint16_t)read_16bit(start_offset + setup_offset, streamFile); uint32_t id = (uint32_t)read_32bitBE(start_offset + setup_offset + 0x06, streamFile); @@ -326,12 +330,12 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { cfg.packet_type = WWV_MODIFIED; /* setup not detectable by header, so we'll try both; hopefully libvorbis will reject wrong codebooks - * - standard: early (<2012), ex. The King of Fighters XIII X360 (2011/11), .ogg (cbs are from aoTuV, too) - * - aoTuV603: later (>2012), ex. Sonic & All-Stars Racing Transformed PC (2012/11), .wem */ + * - standard: early (<2012), ex. The King of Fighters XIII (X360)-2011/11, .ogg (cbs are from aoTuV, too) + * - aoTuV603: later (>2012), ex. Sonic & All-Stars Racing Transformed (PC)-2012/11, .wem */ cfg.setup_type = is_wem ? WWV_AOTUV603_CODEBOOKS : WWV_EXTERNAL_CODEBOOKS; /* aoTuV came along .wem */ break; - //case 0x2a: /* Rocksmith 2011 X360? */ + //case 0x2a: /* Rocksmith 2011 (X360)? */ //non mod packets? TYPE_06? (possibly detectable by checking setup's granule, should be 0) default: VGM_LOG("WWISE: unknown extra size 0x%x\n", vorb_size); @@ -345,10 +349,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { cfg.blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */ ww.data_size -= audio_offset; - /* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! PSV). They are hard to detect (decoding + /* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! (PSV)). They are hard to detect (decoding * will mostly work with garbage results) but we'll try. Setup size and "fmt" bitrate fields may matter too. */ if (ww.extra_size == 0x30) { - /* all blocksizes I've seen are 0x08+0x0B except Oddworld PSV, that uses 0x09+0x09 + /* all blocksizes I've seen are 0x08+0x0B except Oddworld (PSV), that uses 0x09+0x09 * (maybe lower spec machines = needs simpler packets) */ if (cfg.blocksize_0_exp == cfg.blocksize_1_exp) cfg.packet_type = WWV_STANDARD; @@ -369,9 +373,11 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { start_offset += audio_offset; - /* Vorbis is VBR so this is very approximate, meh */ - if (ww.truncated) - vgmstream->num_samples = vgmstream->num_samples * (ww.file_size - start_offset) / ww.data_size; + /* Vorbis is VBR so this is very approximate percent, meh */ + if (ww.truncated) { + vgmstream->num_samples = (int32_t)(vgmstream->num_samples * + (double)(ww.file_size - start_offset) / (double)ww.data_size); + } break; } @@ -390,7 +396,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { vgmstream->interleave_block_size = 0x08; /* ww.block_align = 0x8 in older Wwise, samples per block in newer Wwise */ /* find coef position */ - if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH"*/ /* older Wwise */ + if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH", older Wwise */ vgmstream->num_samples = dsp_bytes_to_samples(ww.data_size, ww.channels); if (wiih_size != 0x2e * ww.channels) goto fail; } @@ -437,11 +443,20 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { vgmstream->num_samples = ww.num_samples; /* set while parsing XMAWAVEFORMATs */ + /* Wwise loops are always pre-adjusted (old or new) and only num_samples is off */ + xma_fix_raw_samples(vgmstream, streamFile, ww.data_offset,ww.data_size, ww.chunk_offset, 1,0); + /* "XMAc": rare Wwise extension, XMA2 physical loop regions (loop_start_b, loop_end_b, loop_subframe_data) * Can appear even in the file doesn't loop, maybe it's meant to be the playable physical region */ //VGM_ASSERT(find_chunk(streamFile, 0x584D4163,first_offset,0, NULL,NULL, ww.big_endian, 0), "WWISE: XMAc chunk found\n"); /* other chunks: "seek", regular XMA2 seek table */ + /* XMA is VBR so this is very approximate percent, meh */ + if (ww.truncated) { + vgmstream->num_samples = (int32_t)(vgmstream->num_samples * + (double)(ww.file_size - start_offset) / (double)ww.data_size); + } + break; } @@ -501,8 +516,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { break; } - case OPUS: { /* Switch */ - size_t skip = 0; /* Wwise doesn't seem to use it? (0x138 /0x3E8 ~default) */ + case OPUS: { /* Switch */ + size_t skip; /* values up to 0x14 seem fixed and similar to HEVAG's (block_align 0x02/04, bits_per_sample 0x10) */ if (ww.fmt_size == 0x28) { @@ -519,6 +534,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { goto fail; } + skip = switch_opus_get_encoder_delay(start_offset, streamFile); /* should be 120 */ + vgmstream->codec_data = init_ffmpeg_switch_opus(streamFile, start_offset,ww.data_size, vgmstream->channels, skip, vgmstream->sample_rate); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360_ast.c b/Frameworks/vgmstream/vgmstream/src/meta/x360_ast.c index 89af1015d..68a331f83 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/x360_ast.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360_ast.c @@ -55,7 +55,6 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) { vgmstream->num_samples = msd.num_samples; vgmstream->loop_start_sample = msd.loop_start_sample; vgmstream->loop_end_sample = msd.loop_end_sample; - //skip_samples = msd.skip_samples; //todo add skip samples } #ifdef VGM_USE_FFMPEG @@ -68,12 +67,12 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) { /* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */ bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1); - if (bytes <= 0) goto fail; - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, fmt_offset, 1,1); } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360_cxs.c b/Frameworks/vgmstream/vgmstream/src/meta/x360_cxs.c index 311cdbc95..5e5df7280 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/x360_cxs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360_cxs.c @@ -1,31 +1,29 @@ #include "meta.h" #include "../coding/coding.h" -/* CXS - found in Eternal Sonata (Xbox 360) */ +/* CXS - found in Eternal Sonata (X360) */ VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; - /* check extension, case insensitive */ + /* checks */ if ( !check_extensions(streamFile,"cxs")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x43585320) /* "CXS " */ goto fail; loop_flag = read_32bitBE(0x18,streamFile) > 0; channel_count = read_32bitBE(0x0c,streamFile); + start_offset = read_32bitBE(0x04,streamFile) + read_32bitBE(0x28,streamFile); /* assumed, seek table always at 0x800 */ - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - start_offset = read_32bitBE(0x04,streamFile) + read_32bitBE(0x28,streamFile); /* assumed, seek table always at 0x800 */ /* 0x04: data start? */ vgmstream->sample_rate = read_32bitBE(0x08,streamFile); - vgmstream->channels = channel_count; /*0x0c*/ - vgmstream->num_samples = read_32bitBE(0x10,streamFile) + 576; /*todo add proper encoder_delay*/ + vgmstream->num_samples = read_32bitBE(0x10,streamFile); vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); /* 0x1c: below */ @@ -50,6 +48,8 @@ VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) { vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,1); /* num samples are ok */ } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c b/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c index bee4fdbf8..44d6819fb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c @@ -10,10 +10,9 @@ VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) { int num_samples, loop_start_sample, loop_end_sample; - /* check extension, case insensitive */ + /* checks */ if ( !check_extensions(streamFile,"past")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */ goto fail; @@ -51,6 +50,8 @@ VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) { if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c b/Frameworks/vgmstream/vgmstream/src/meta/xa.c similarity index 97% rename from Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c rename to Frameworks/vgmstream/vgmstream/src/meta/xa.c index 612b5adf3..5c919dacf 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xa.c @@ -2,14 +2,15 @@ #include "../layout/layout.h" #include "../coding/coding.h" -/* CD-XA - from Sony PS1 CDs */ -VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile) { +/* CD-XA - from Sony PS1 and Philips CD-i CD audio */ +VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag = 0, channel_count, sample_rate; int is_blocked; size_t file_size = get_streamfile_size(streamFile); + /* checks * .xa: common, .str: sometimes (mainly videos) * .adp: Phantasy Star Collection (SAT) raw XA */ @@ -53,7 +54,7 @@ VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile) { for (i = 0; i < (sector_size/block_size); i++) { /* XA headers checks: filter indexes should be 0..3, and shifts 0..C */ for (j = 0; j < 16; j++) { - uint8_t header = (uint8_t)read_8bit(test_offset + i, streamFile); + uint8_t header = (uint8_t)read_8bit(test_offset + j, streamFile); if (((header >> 4) & 0xF) > 0x03) goto fail; if (((header >> 0) & 0xF) > 0x0c) @@ -145,7 +146,7 @@ VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile) { vgmstream->sample_rate = sample_rate; - vgmstream->meta_type = meta_PSX_XA; + vgmstream->meta_type = meta_XA; vgmstream->coding_type = coding_XA; vgmstream->layout_type = is_blocked ? layout_blocked_xa : layout_none; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xma.c b/Frameworks/vgmstream/vgmstream/src/meta/xma.c index 119cfb3a6..7aade3001 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xma.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xma.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -/* XMA - Microsoft format derived from WMAPRO, found in X360/XBone games */ +/* XMA - Microsoft format derived from RIFF, found in X360/XBone games */ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset, chunk_offset, first_offset = 0xc; @@ -11,8 +11,11 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { int fmt_be = 0; - /* check extension, case insensitive */ - /* .xma2: Skullgirls, .nps: Beautiful Katamari (renamed .xma), .str: Sonic & Sega All Stars Racing */ + /* checks */ + /* .xma: standard + * .xma2: Skullgirls (X360) + * .nps: Beautiful Katamari (X360) + * .str: Sonic & Sega All Stars Racing (X360) */ if ( !check_extensions(streamFile, "xma,xma2,nps,str") ) goto fail; @@ -66,7 +69,7 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { goto fail; - /* fix samples; for now only XMA1 is fixed, but XMA2 num_samples don't include skip samples and xmaencode.exe doesn't use it */ + /* get xma1 samples, later fixed */ if (is_xma1) { ms_sample_data msd = {0}; @@ -86,7 +89,6 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { num_samples = msd.num_samples; loop_start_sample = msd.loop_start_sample; loop_end_sample = msd.loop_end_sample; - /* XMA2 loop/num_samples don't seem to use msd.skip_samples */ } @@ -94,12 +96,11 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; + vgmstream->meta_type = meta_XMA_RIFF; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; vgmstream->loop_start_sample = loop_start_sample; vgmstream->loop_end_sample = loop_end_sample; - vgmstream->meta_type = meta_XMA_RIFF; - #ifdef VGM_USE_FFMPEG { @@ -111,26 +112,19 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { } else { bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, fmt_be); } - if (bytes <= 0) goto fail; vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); } #else goto fail; #endif -#if 0 - //not active due to a FFmpeg bug that misses some of the last packet samples and decodes - // garbage if asked for more samples (always happens but more apparent with skip_samples active) - /* fix encoder delay */ - if (data->skipSamples==0) - ffmpeg_set_skip_samples(data, xma.skip_samples); -#endif - /* open the file for reading */ if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xnb.c b/Frameworks/vgmstream/vgmstream/src/meta/xnb.c index c20efb11f..3e2191f0c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xnb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xnb.c @@ -4,18 +4,16 @@ /* XNB - Microsoft XNA Game Studio 4.0 format */ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - off_t start_offset; + off_t start_offset, xma_chunk_offset = 0; int loop_flag = 0, channel_count, num_samples = 0, loop_start = 0, loop_end = 0; int big_endian, flags, codec, sample_rate, block_size, bps; size_t data_size; char platform; - /* check extension, case insensitive */ - if ( !check_extensions(streamFile,"xnb")) + /* checks */ + if (!check_extensions(streamFile,"xnb")) goto fail; - - /* check header */ if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */ goto fail; @@ -24,7 +22,7 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { platform = read_8bit(0x03,streamFile); big_endian = (platform == 'x'); - if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */ + if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */ goto fail; flags = read_8bit(0x05,streamFile); @@ -82,6 +80,7 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { if (codec == 0x166) { xma2_parse_fmt_chunk_extra(streamFile, current_offset, &loop_flag, &num_samples, &loop_start, &loop_end, big_endian); + xma_chunk_offset = current_offset; } } @@ -138,8 +137,6 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { block_count = data_size / block_size + (data_size % block_size ? 1 : 0); bytes = ffmpeg_make_riff_xma2(buf,0x100, num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; @@ -148,6 +145,8 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { vgmstream->num_samples = num_samples; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, xma_chunk_offset, 1,1); break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xopus.c b/Frameworks/vgmstream/vgmstream/src/meta/xopus.c new file mode 100644 index 000000000..8ef98813a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xopus.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* XOPUS - from Exient games [Angry Birds: Transformers (Android), Angry Birds: Go (Android)] */ +VGMSTREAM * init_vgmstream_xopus(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channel_count, sample_rate, num_samples, skip; + size_t data_size; + int entries; + + + /* checks*/ + if (!check_extensions(streamFile, "xopus")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x584F7075) /* "XOpu" */ + goto fail; + + /* 0x04: always 0x01? */ + channel_count = read_8bit(0x05, streamFile); + /* 0x06: always 0x30? */ + /* 0x08: always 0xc8? max allowed packet size? */ + num_samples = read_32bitLE(0x0c, streamFile); + skip = read_32bitLE(0x10, streamFile); + entries = read_32bitLE(0x14, streamFile); + data_size = read_32bitLE(0x18, streamFile); + /* 0x1c: unused */ + /* 0x20+: packet sizes table */ + + sample_rate = 48000; + loop_flag = 0; + + start_offset = 0x20 + 0x02*entries; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_XOPUS; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + +#ifdef VGM_USE_FFMPEG + { + vgmstream->codec_data = init_ffmpeg_x_opus(streamFile, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + } +#else + goto fail; +#endif + + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xpcm.c b/Frameworks/vgmstream/vgmstream/src/meta/xpcm.c new file mode 100644 index 000000000..9635bdd22 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xpcm.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* XPCM - from Circus games [Eternal Fantasy (PC), D.C. White Season (PC)] */ +VGMSTREAM * init_vgmstream_xpcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + size_t decompressed_size; + int loop_flag, channel_count, codec, subcodec, sample_rate; + + + /* checks */ + if (!check_extensions(streamFile, "pcm")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x5850434D) /* "XPCM" "*/ + goto fail; + + decompressed_size = read_32bitLE(0x04,streamFile); /* (data_size for PCM) */ + codec = read_8bit(0x08, streamFile); + subcodec = read_8bit(0x09, streamFile); + /* 0x0a: always null */ + /* 0x0c: always 0x01 (PCM codec) */ + channel_count = read_16bitLE(0x0e,streamFile); + sample_rate = read_32bitLE(0x10,streamFile); + /* 0x14: average bitrate */ + /* 0x18: block size */ + /* 0x1a: output bits (16) */ + start_offset = 0x1c; /* compressed size in codec 0x01/03 */ + + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_XPCM; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = decompressed_size / sizeof(int16_t) / channel_count; + + switch(codec) { + case 0x00: + if (subcodec != 0) goto fail; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + break; + case 0x02: + if (subcodec != 0) goto fail; + vgmstream->coding_type = coding_CIRCUS_ADPCM; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x01; + break; + + case 0x01: /* LZSS + VQ */ + case 0x03: /* unknown */ + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xps.c b/Frameworks/vgmstream/vgmstream/src/meta/xps.c new file mode 100644 index 000000000..da84fbb55 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xps.c @@ -0,0 +1,223 @@ +#include "meta.h" +#include "../coding/coding.h" + +static void read_xps_name(VGMSTREAM *vgmstream, STREAMFILE *streamFile, int file_id); + +/* .XPS+DAT - From Software games streams [Metal Wolf Chaos (Xbox), Otogi (Xbox)] */ +VGMSTREAM * init_vgmstream_xps_dat(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamData = NULL; + off_t start_offset, header_offset; + size_t stream_size; + int loop_flag, channel_count, sample_rate, codec, loop_start_sample, loop_end_sample, file_id; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* checks */ + if (!check_extensions(streamFile, "xps")) + goto fail; + + if (read_32bitLE(0x00,streamFile) != get_streamfile_size(streamFile)) + goto fail; + if (read_32bitBE(0x0c,streamFile) != 0x64696666) /* "diff" */ + goto fail; + + /* handle .xps+dat (bank .xps are done below) */ + streamData = open_streamfile_by_ext(streamFile, "dat"); + if (!streamData) goto fail; + + /* 0x00: approximate file size */ + + total_subsongs = read_32bitLE(0x04,streamData); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + header_offset = 0x20 + 0x94*(target_subsong-1); /* could start at 0x0c too */ + + file_id = read_32bitLE(header_offset+0x00,streamData); + start_offset = read_32bitLE(header_offset+0x04,streamData); + stream_size = read_32bitLE(header_offset+0x08,streamData); + /* 0x0c: loop start offset? */ + /* 0x10: loop end offset? */ + /* 0x14: always null? */ + codec = read_16bitLE(header_offset+0x18,streamData); + channel_count = read_16bitLE(header_offset+0x1a,streamData); + sample_rate = read_32bitLE(header_offset+0x1c,streamData); + /* 0x20: average bitrate */ + /* 0x24: block size, bps */ + loop_flag = read_32bitLE(header_offset+0x5c,streamData); + loop_start_sample = read_32bitLE(header_offset+0x6c,streamData); + loop_end_sample = read_32bitLE(header_offset+0x70,streamData) + 1; /* a "smpl" chunk basically */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->meta_type = meta_XPS_DAT; + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + switch(codec) { + case 0x01: + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); + break; + + case 0x69: + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count); + break; + + default: + goto fail; + } + + read_xps_name(vgmstream, streamFile, file_id); + + if (!vgmstream_open_stream(vgmstream,streamData,start_offset)) + goto fail; + + close_streamfile(streamData); + return vgmstream; + +fail: + close_streamfile(streamData); + close_vgmstream(vgmstream); + return NULL; +} + +static void read_xps_name(VGMSTREAM *vgmstream, STREAMFILE *streamFile, int file_id) { + int i, entries; + int name_id = -1, udss_name_id; + off_t entry_offset = 0x10; + + + /* main section + stream sections (usually same number but not always) */ + entries = read_32bitLE(0x04,streamFile); + + /* "sid\0" entries: find name_id of file_id */ + for (i = 0; i < entries; i++) { + off_t entry_base = entry_offset; + size_t entry_size = read_32bitLE(entry_base+0x00,streamFile); + uint32_t entry_id = read_32bitBE(entry_base+0x04,streamFile); + size_t entry_pad = read_32bitLE(entry_base+0x08,streamFile); + /* 0x0c: always null, rest: entry (format varies) */ + + entry_offset += entry_size + entry_pad + 0x10; + + /* sound info entry */ + if (entry_id == 0x73696400) { /* "sid\0" */ + int entry_file_id = read_32bitLE(entry_base+0x10,streamFile); + int entry_name_id = read_32bitLE(entry_base+0x14,streamFile); + if (entry_file_id == file_id && name_id == -1) { + name_id = entry_name_id; + } + continue; + } + + /* sound stream entry, otherwise no good */ + if (entry_id != 0x75647373) { /* "udss" */ + goto fail; + } + + udss_name_id = read_32bitLE(entry_base+0x10,streamFile); + if (udss_name_id == name_id) { + off_t name_offset = entry_base + 0x10 + 0x08; + size_t name_size = entry_size - 0x08; /* includes null */ + read_string(vgmstream->stream_name,name_size, name_offset,streamFile); + return; + } + } + +fail: + return; +} + +/* .XPS - From Software games banks [Metal Wolf Chaos (Xbox), Otogi (Xbox)] */ +VGMSTREAM * init_vgmstream_xps(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamData = NULL; + int i, entries; + off_t entry_offset = 0x10; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* checks */ + if (!check_extensions(streamFile, "xps")) + goto fail; + + if (read_32bitLE(0x00,streamFile) != get_streamfile_size(streamFile)) + goto fail; + if (read_32bitBE(0x0c,streamFile) != 0x64696666) /* "diff" */ + goto fail; + + /* handle .xps alone (stream .xps+data are done above) */ + streamData = open_streamfile_by_ext(streamFile, "dat"); + if (streamData) goto fail; + + /* main section + bank sections (usually same number but not always) */ + entries = read_32bitLE(0x04,streamFile); + + total_subsongs = 0; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 /*|| target_subsong > total_subsongs || total_subsongs < 1*/) goto fail; + + + /* parse entries: skip (there is probably a stream/bank flag here) */ + for (i = 0; i < entries; i++) { + off_t entry_base = entry_offset; + size_t entry_size = read_32bitLE(entry_base+0x00,streamFile); + uint32_t entry_id = read_32bitBE(entry_base+0x04,streamFile); + size_t entry_pad = read_32bitLE(entry_base+0x08,streamFile); + /* 0x0c: always null, rest: entry (format varies) */ + + entry_offset += entry_size + entry_pad + 0x10; + + /* sound info entry */ + if (entry_id == 0x73696400) { /* "sid\0" */ + /* keep looking for sound banks */ + continue; + } + + /* sound bank entry, otherwise no good */ + if (entry_id != 0x75647362) { /* "udsb" */ + goto fail; + } + + total_subsongs++; + + /* open internal RIFF */ + if (target_subsong == total_subsongs && vgmstream == NULL) { + STREAMFILE* temp_streamFile; + off_t subsong_offset = entry_base+0x18; + size_t subsong_size = read_32bitLE(entry_base+0x14,streamFile); + + temp_streamFile = setup_subfile_streamfile(streamFile, subsong_offset,subsong_size, "wav"); + if (!temp_streamFile) goto fail; + + vgmstream = init_vgmstream_riff(temp_streamFile); + close_streamfile(temp_streamFile); + if (!vgmstream) goto fail; + + } + } + + /* subsong not found */ + if (!vgmstream) + goto fail; + + vgmstream->num_streams = total_subsongs; + return vgmstream; + +fail: + close_streamfile(streamData); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xvag.c b/Frameworks/vgmstream/vgmstream/src/meta/xvag.c index 27614b610..2f0796062 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xvag.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xvag.c @@ -106,6 +106,15 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) { xvag.loop_end = ps_bytes_to_samples(file_size - start_offset, xvag.channels); } + /* May use 'MP3 Surround' for multichannel [Twisted Metal (PS3), The Last of Us (PS4) test file] + * It's a mutant MP3 that decodes as 2ch but output can be routed to 6ch somehow, if manually + * activated. Fraunhofer IIS's MP3sPlayer can do it, as can PS3 (fw v2.40+) but no others seems to. + * So simply play as 2ch, they sound ok with slightly wider feel. No XVAG/MP3 flag exists to detect, + * can be found in v0x60 (without layers/subsongs) and v0x61 (with them set as 1) */ + if (xvag.codec == 0x08 && xvag.channels == 6 && xvag.layers == 1) { + xvag.channels = 2; + } + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(xvag.channels,xvag.loop_flag); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index 7f6f9f14f..7a8be9c79 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -67,10 +67,13 @@ typedef struct { uint32_t loop_end; uint32_t loop_start_sample; uint32_t loop_end_sample; + + int is_crackdown; + int fix_xma_num_samples; + int fix_xma_loop_samples; } xwb_header; static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile); -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); /* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */ @@ -84,8 +87,9 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { /* checks */ /* .xwb: standard - * .xna: Touhou Makukasai ~ Fantasy Danmaku Festival (PC) */ - if (!check_extensions(streamFile,"xwb,xna")) + * .xna: Touhou Makukasai ~ Fantasy Danmaku Festival (PC) + * (extensionless): Grabbed by the Ghoulies (Xbox) */ + if (!check_extensions(streamFile,"xwb,xna,")) goto fail; if ((read_32bitBE(0x00,streamFile) != 0x57424E44) && /* "WBND" (LE) */ (read_32bitBE(0x00,streamFile) != 0x444E4257)) /* "DNBW" (BE) */ @@ -102,9 +106,11 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { /* read main header (WAVEBANKHEADER) */ xwb.version = read_32bit(0x04, streamFile); /* XACT3: 0x04=tool version, 0x08=header version */ - /* Crackdown 1 X360, essentially XACT2 but may have split header in some cases */ - if (xwb.version == XACT_CRACKDOWN) + /* Crackdown 1 (X360), essentially XACT2 but may have split header in some cases */ + if (xwb.version == XACT_CRACKDOWN) { xwb.version = XACT2_2_MAX; + xwb.is_crackdown = 1; + } /* read segment offsets (SEGIDX) */ if (xwb.version <= XACT1_0_MAX) { @@ -222,7 +228,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.stream_offset = xwb.data_offset + (uint32_t)read_32bit(off+0x08, streamFile); xwb.stream_size = (uint32_t)read_32bit(off+0x0c, streamFile); - if (xwb.version <= XACT2_1_MAX) { /* LoopRegion (bytes) */ + if (xwb.version <= XACT2_1_MAX) { /* LoopRegion (bytes) */ xwb.loop_start = (uint32_t)read_32bit(off+0x10, streamFile); xwb.loop_end = (uint32_t)read_32bit(off+0x14, streamFile);//length (LoopRegion) or offset (XMALoopRegion in late XACT2) } else { /* LoopRegion (samples) */ @@ -363,9 +369,9 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.loop_start_sample = msadpcm_bytes_to_samples(xwb.loop_start, block_size, xwb.channels); xwb.loop_end_sample = msadpcm_bytes_to_samples(xwb.loop_start + xwb.loop_end, block_size, xwb.channels); } - else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { - /* v38: byte offset, v40+: sample offset, v39: ? */ - /* need to manually find sample offsets, thanks to Microsoft dumb headers */ + else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { + /* v38: byte offset, v40+: sample offset, v39: ? */ + /* need to manually find sample offsets, thanks to Microsoft's dumb headers */ ms_sample_data msd = {0}; msd.xma_version = xwb.codec == XMA1 ? 1 : 2; @@ -383,25 +389,27 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.loop_start_sample = msd.loop_start_sample; xwb.loop_end_sample = msd.loop_end_sample; + /* if provided, xwb.num_samples is equal to msd.num_samples after proper adjustments (+ 128 - start_skip - end_skip) */ + xwb.fix_xma_loop_samples = 1; + xwb.fix_xma_num_samples = 0; + /* for XWB v22 (and below?) this seems normal [Project Gotham Racing (X360)] */ - if (xwb.num_samples == 0) + if (xwb.num_samples == 0) { xwb.num_samples = msd.num_samples; - - // todo fix properly (XWB loop_start/end seem to count padding samples while XMA1 RIFF doesn't) - //this doesn't seem ok because can fall within 0 to 512 (ie.- first frame, 384) - //if (xwb.loop_start_sample) xwb.loop_start_sample -= 512; - //if (xwb.loop_end_sample) xwb.loop_end_sample -= 512; - - //add padding back until it's fixed (affects looping) - // (in rare cases this causes a glitch in FFmpeg since it has a bug where it's missing some samples) - xwb.num_samples += 64 + 512; + xwb.fix_xma_num_samples = 1; + } } else if ((xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { - /* seems to be needed by some edge cases, ex. Crackdown */ - //add padding, see above - xwb.num_samples += 64 + 512; - } + /* unlike prev versions, xwb.num_samples is the full size without adjustments */ + xwb.fix_xma_loop_samples = 1; + xwb.fix_xma_num_samples = 1; + /* Crackdown does use xwb.num_samples after adjustments (but not loops) */ + if (xwb.is_crackdown) { + xwb.fix_xma_num_samples = 0; + } + } +VGM_LOG("fix: num=%i, loop=%i\n", xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(xwb.channels,xwb.loop_flag); @@ -437,37 +445,44 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case XMA1: { /* Kameo (X360) */ - uint8_t buf[100]; + uint8_t buf[0x100]; int bytes; - bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, 0); - if (bytes <= 0) goto fail; - + bytes = ffmpeg_make_riff_xma1(buf,0x100, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, 0); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, xwb.stream_offset,xwb.stream_size, 0, xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples); + + /* this fixes some XMA1, perhaps the above isn't reading end_skip correctly (doesn't happen for all files though) */ + if (vgmstream->loop_flag && + vgmstream->loop_end_sample > vgmstream->num_samples) { + VGM_LOG("XWB: fix XMA1 looping\n"); + vgmstream->loop_end_sample = vgmstream->num_samples; + } break; } case XMA2: { /* Blue Dragon (X360) */ - uint8_t buf[100]; + uint8_t buf[0x100]; int bytes, block_size, block_count; block_size = 0x10000; /* XACT default */ block_count = xwb.stream_size / block_size + (xwb.stream_size % block_size ? 1 : 0); - bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - + bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, xwb.stream_offset,xwb.stream_size, 0, xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples); break; } - case WMA: { /* WMAudio1 (WMA v1): Prince of Persia 2 port (Xbox) */ + case WMA: { /* WMAudio1 (WMA v2): Prince of Persia 2 port (Xbox) */ ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_data = init_ffmpeg_offset(streamFile, xwb.stream_offset,xwb.stream_size); @@ -483,10 +498,10 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { } case XWMA: { /* WMAudio2 (WMA v2): BlazBlue (X360), WMAudio3 (WMA Pro): Bullet Witch (PC) voices */ - uint8_t buf[100]; + uint8_t buf[0x100]; int bytes, bps_index, block_align, block_index, avg_bps, wma_codec; - bps_index = (xwb.block_align >> 5); /* upper 3b bytes-per-second index */ //docs say 2b+6b but are wrong + bps_index = (xwb.block_align >> 5); /* upper 3b bytes-per-second index (docs say 2b+6b but are wrong) */ block_index = (xwb.block_align) & 0x1F; /*lower 5b block alignment index */ if (bps_index >= 7) goto fail; if (block_index >= 17) goto fail; @@ -495,9 +510,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { block_align = wma_block_align_index[block_index]; wma_codec = xwb.bits_per_sample ? 0x162 : 0x161; /* 0=WMAudio2, 1=WMAudio3 */ - bytes = ffmpeg_make_riff_xwma(buf, 100, wma_codec, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align); - if (bytes <= 0) goto fail; - + bytes = ffmpeg_make_riff_xwma(buf,0x100, wma_codec, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; @@ -506,16 +519,14 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { } case ATRAC3: { /* Techland PS3 extension [Sniper Ghost Warrior (PS3)] */ - uint8_t buf[200]; + uint8_t buf[0x100]; int bytes; int block_size = xwb.block_align * vgmstream->channels; int joint_stereo = xwb.block_align == 0x60; /* untested, ATRAC3 default */ int skip_samples = 0; /* unknown */ - bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples); - if (bytes <= 0) goto fail; - + bytes = ffmpeg_make_riff_atrac3(buf,0x100, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; @@ -585,31 +596,6 @@ fail: /* ****************************************************************************** */ -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -/* ****************************************************************************** */ - /* try to get the stream name in the .xwb, though they are very rarely included */ static int get_xwb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile) { size_t read; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwc.c b/Frameworks/vgmstream/vgmstream/src/meta/xwc.c index fbc5c28ef..fec7a6219 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwc.c @@ -8,7 +8,9 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { size_t data_size; int loop_flag, channel_count, codec, num_samples; - /* check extensions (.xwc is the extension of the bigfile, individual files don't have one) */ + + /* checks */ + /* .xwc: extension of the bigfile, individual files don't have one */ if ( !check_extensions(streamFile,"xwc")) goto fail; @@ -16,7 +18,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { /* version */ if (read_32bitBE(0x00,streamFile) == 0x00030000 && read_32bitBE(0x04,streamFile) == 0x00900000) { /* The Darkness */ - data_size = read_32bitLE(0x08, streamFile); /* including subheader */ + data_size = read_32bitLE(0x08, streamFile) + 0x1c; /* not including subheader */ channel_count = read_32bitLE(0x0c, streamFile); /* 0x10: num_samples */ /* 0x14: 0x8000? */ @@ -28,7 +30,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { } else if (read_32bitBE(0x00,streamFile) == 0x00040000 && read_32bitBE(0x04,streamFile) == 0x00900000) { /* Riddick, Syndicate */ - data_size = read_32bitLE(0x08, streamFile); /* including subheader */ + data_size = read_32bitLE(0x08, streamFile) + 0x24; /* not including subheader */ channel_count = read_32bitLE(0x0c, streamFile); /* 0x10: num_samples */ /* 0x14: 0x8000? */ @@ -42,15 +44,15 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { goto fail; } - loop_flag = 0; /* seemingly not in the file */ + loop_flag = 0; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - vgmstream->num_samples = num_samples; vgmstream->meta_type = meta_XWC; + vgmstream->num_samples = num_samples; switch(codec) { #ifdef VGM_USE_MPEG @@ -59,7 +61,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { start_offset = 0x800; vgmstream->num_samples = read_32bitLE(extra_offset+0x00, streamFile); /* with encoder delay */ //todo improve - cfg.data_size = read_32bitLE(extra_offset+0x04, streamFile); //data_size - 0x28; + cfg.data_size = read_32bitLE(extra_offset+0x04, streamFile); /* without padding */ vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg); if (!vgmstream->codec_data) goto fail; @@ -77,6 +79,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { seek_size = read_32bitLE(extra_offset+0x00, streamFile); start_offset = extra_offset+0x04 + seek_size + read_32bitLE(extra_offset+0x04+seek_size, streamFile) + 0x08; start_offset += (start_offset % 0x800) ? 0x800 - (start_offset % 0x800) : 0; /* padded */ + data_size = data_size - start_offset; sample_rate = read_32bitBE(extra_offset+0x04+seek_size+0x10, streamFile); block_size = read_32bitBE(extra_offset+0x04+seek_size+0x1c, streamFile); @@ -84,21 +87,22 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { /* others: scrambled RIFF fmt BE values */ bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size - start_offset - 0x28); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; vgmstream->sample_rate = sample_rate; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok, fix delay */ break; } case 0x564F5242: { /* "VORB" (PC) */ start_offset = 0x30; + data_size = data_size - start_offset; - vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset, data_size - start_offset - 0x28); + vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset,data_size); if ( !vgmstream->codec_data ) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwma.c b/Frameworks/vgmstream/vgmstream/src/meta/xwma.c new file mode 100644 index 000000000..689fefa0e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwma.c @@ -0,0 +1,87 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* XWMA - Microsoft WMA container [The Elder Scrolls: Skyrim (PC/X360), Hydrophobia (PC)] */ +VGMSTREAM * init_vgmstream_xwma(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t fmt_offset, data_offset, first_offset = 0xc; + size_t fmt_size, data_size; + int loop_flag, channel_count; + + + /* checks */ + /* .xwma: standard + * .xwm: The Elder Scrolls: Skyrim (PC), Blade Arcus from Shining (PC) */ + if (!check_extensions(streamFile, "xwma,xwm")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x58574D41) /* "XWMA" */ + goto fail; + + if ( !find_chunk_le(streamFile, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size) ) /* "fmt "*/ + goto fail; + if ( !find_chunk_le(streamFile, 0x64617461,first_offset,0, &data_offset,&data_size) ) /* "data"*/ + goto fail; + + channel_count = read_16bitLE(fmt_offset+0x02,streamFile); + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(fmt_offset+0x04, streamFile); + vgmstream->meta_type = meta_XWMA; + + /* the main purpose of this meta is redoing the XWMA header to: + * - redo header to fix XWMA with buggy bit rates so FFmpeg can play them ok + * - skip seek table to fix FFmpeg buggy XWMA seeking (see init_seek) + * - read num_samples correctly + */ + +#ifdef VGM_USE_FFMPEG + { + uint8_t buf[0x100]; + int bytes, avg_bps, block_align, wma_codec; + + avg_bps = read_32bitLE(fmt_offset+0x08, streamFile); + block_align = (uint16_t)read_16bitLE(fmt_offset+0x0c, streamFile); + wma_codec = (uint16_t)read_16bitLE(fmt_offset+0x00, streamFile); + + bytes = ffmpeg_make_riff_xwma(buf,0x100, wma_codec, data_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, data_offset,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + /* manually find total samples, why don't they put this in the header is beyond me */ + { + ms_sample_data msd = {0}; + + msd.channels = vgmstream->channels; + msd.data_offset = data_offset; + msd.data_size = data_size; + + if (wma_codec == 0x0162) + wmapro_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x00E0); + else + wma_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x001F); + + vgmstream->num_samples = msd.num_samples; + if (vgmstream->num_samples == 0) + vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */ + //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 + } + } +#else + goto fail; +#endif + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c b/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c new file mode 100644 index 000000000..63d1e9b78 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c @@ -0,0 +1,224 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "zsnd_streamfile.h" + + +/* ZSND - Vicarious Visions games [X-Men Legends II (multi), Marvel Ultimate Alliance (multi)] */ +VGMSTREAM * init_vgmstream_zsnd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t start_offset, name_offset; + size_t stream_size, name_size; + int loop_flag, channel_count, sample_rate, layers; + uint32_t codec; + int total_subsongs, target_subsong = streamFile->stream_index; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + /* .zss/zsm: standard, .ens/enm: same for PS2 */ + if (!check_extensions(streamFile, "zss,zsm,ens,enm")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x5A534E44) /* "ZSND" */ + goto fail; + /* probably zss=stream, zsm=memory; no diffs other than size */ + + codec = read_32bitBE(0x04,streamFile); + /* 0x08: file size, but slightly bigger (+0x01~04) in some platforms */ + /* 0x0c: header end/first stream start (unneeded as all offsets are absolute) */ + + if (codec == 0x47435542) { /* "GCUB" */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } + else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + + /* parse header tables (7*0x0c) */ + { + off_t header2_offset, header3_offset; + + /* table2: stream head */ + int table2_entries = read_32bit(0x1c,streamFile); + //off_t table2_head = read_32bit(0x20,streamFile); + off_t table2_body = read_32bit(0x24,streamFile); + + /* table3: stream body */ + int table3_entries = read_32bit(0x28,streamFile); + //off_t table3_head = read_32bit(0x2c,streamFile); + off_t table3_body = read_32bit(0x30,streamFile); + + /* table1: stream cues? (entry=0x18) + * tables 4-7 seem reserved with 0 entries and offsets to header end, + * though table5 can be seen in boss4_m.zsm (1 entry) */ + + /* table heads are always 0x08 * entries */ + /* 0x00 = ? (varies between tables but consistent between platforms) */ + /* 0x04 = id? (also in table2_body at 0x00?) */ + + /* table1 may have more entries than table2/3 */ + if (table2_entries != table3_entries) { + VGM_LOG("ZSND: table2/3 entries don't match\n"); + goto fail; + } + + + total_subsongs = table2_entries; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + switch (codec) { + case 0x50432020: /* "PC " */ + header2_offset = table2_body + 0x18*(target_subsong-1); + header3_offset = table3_body + 0x4c*(target_subsong-1); + + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + name_offset = header3_offset + 0x0c; + name_size = 0x40; + break; + + case 0x58424F58: /* "XBOX" */ + header2_offset = table2_body + 0x1c*(target_subsong-1); + header3_offset = table3_body + 0x54*(target_subsong-1); + + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + name_offset = header3_offset + 0x14; + name_size = 0x40; + break; + + case 0x50533220: /* "PS2 " (also for PSP) */ + header2_offset = table2_body + 0x10*(target_subsong-1); + header3_offset = table3_body + 0x08*(target_subsong-1); + + sample_rate = read_16bit(header2_offset + 0x02,streamFile); + layers = read_16bit(header2_offset + 0x04,streamFile); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + name_offset = 0; + name_size = 0; + switch(sample_rate) { + case 0x0800: sample_rate = 22050; break; + case 0x0687: sample_rate = 18000; break; + case 0x05ce: sample_rate = 16000; break; + case 0x0400: sample_rate = 11025; break; + default: + VGM_LOG("ZSND: unknown sample_rate %x at %x\n", sample_rate, (uint32_t)header2_offset); + goto fail; + } + break; + + case 0x47435542: /* "GCUB" (also for Wii) */ + header2_offset = table2_body + 0x18*(target_subsong-1); + header3_offset = table3_body + 0x0c*(target_subsong-1); + + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + /* 0x08: "DSP " for some reason */ + name_offset = 0; + name_size = 0; + break; + + default: + goto fail; + } + + /* maybe flags? */ + switch (layers) { + case 0x00: channel_count = 1; break; + case 0x01: channel_count = 1; break; /* related to looping? */ + case 0x02: channel_count = 2; break; + case 0x22: channel_count = 4; break; + default: + VGM_LOG("ZSND: unknown layers\n"); + goto fail; + } + + loop_flag = 0; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_ZSND; + vgmstream->sample_rate = sample_rate; + + switch (codec) { + case 0x50432020: /* "PC " */ + vgmstream->coding_type = coding_IMA; + vgmstream->layout_type = layout_none; + //todo interleaved stereo (needs to adapt decoder) + //vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/ + //vgmstream->interleave_block_size = 0x2000 * 2 / channel_count; + + vgmstream->num_samples = ima_bytes_to_samples(stream_size, channel_count); + break; + + case 0x58424F58: /* "XBOX" */ + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/ + vgmstream->interleave_block_size = 0x9000 * 2 / channel_count; + + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count); + break; + + case 0x50533220: /* "PS2 " (also for PSP) */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x800; + + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); + break; + + case 0x47435542: /* "GCUB" (also for Wii) */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + + /* has a full DSP header, but num_samples may vary slighly between channels, so calc manually */ + dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c,0x60); + dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, 0x60); + start_offset += 0x60*channel_count; + stream_size -= 0x60*channel_count; + + vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count); + break; + + default: + goto fail; + } + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + if (name_offset) { + read_string(vgmstream->stream_name,name_size, name_offset,streamFile); + } + + + temp_streamFile = setup_zsnd_streamfile(streamFile, start_offset, stream_size); /* fixes last interleave reads */ + if (!temp_streamFile) goto fail; + + if (!vgmstream_open_stream(vgmstream,temp_streamFile,start_offset)) + goto fail; + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/zsnd_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/zsnd_streamfile.h new file mode 100644 index 000000000..950c49be9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/zsnd_streamfile.h @@ -0,0 +1,58 @@ +#ifndef _ZSND_STREAMFILE_H_ +#define _ZSND_STREAMFILE_H_ +#include "../streamfile.h" + +typedef struct { + off_t max_offset; +} zsnd_io_data; + +static size_t zsnd_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, zsnd_io_data* data) { + size_t bytes_read, bytes_to_do; + int i; + + /* clamp reads */ + bytes_to_do = length; + if (offset > data->max_offset) + offset = data->max_offset; + if (offset + length > data->max_offset) + bytes_to_do = data->max_offset - offset; + + bytes_read = streamfile->read(streamfile, dest, offset, bytes_to_do); + + /* pretend we got data after max_offset */ + if (bytes_read < length) { + for (i = bytes_read; i < length; i++) { + dest[i] = 0; + } + bytes_read = length; + } + + return bytes_read; +} + +/* ZSND removes last interleave data from the file if blank, but codecs still need to read after it. + * This data could be from next stream or from EOF, so return blank data instead. */ +static STREAMFILE* setup_zsnd_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t stream_size) { + STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; + zsnd_io_data io_data = {0}; + size_t io_data_size = sizeof(zsnd_io_data); + + io_data.max_offset = start_offset + stream_size; + + /* setup custom streamfile */ + new_streamFile = open_wrap_streamfile(streamFile); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, zsnd_io_read,NULL); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + return temp_streamFile; + +fail: + close_streamfile(temp_streamFile); + return NULL; +} + +#endif /* _ZSND_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.c b/Frameworks/vgmstream/vgmstream/src/streamfile.c index 6723274d0..aa1767902 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.c +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.c @@ -53,7 +53,7 @@ static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offse /* ignore requests at EOF */ if (offset >= streamfile->filesize) { //offset = streamfile->filesize; /* seems fseek doesn't clamp offset */ - VGM_ASSERT_ONCE(offset > streamfile->filesize, "STDIO: reading over filesize 0x%x @ 0x%"PRIx64" + 0x%x\n", streamfile->filesize, (off64_t)offset, length); + VGM_ASSERT_ONCE(offset > streamfile->filesize, "STDIO: reading over filesize 0x%x @ 0x%x + 0x%x\n", streamfile->filesize, (uint32_t)offset, length); break; } @@ -254,7 +254,7 @@ static size_t buffer_read(BUFFER_STREAMFILE *streamfile, uint8_t * dest, off_t o /* ignore requests at EOF */ if (offset >= streamfile->filesize) { //offset = streamfile->filesize; /* seems fseek doesn't clamp offset */ - VGM_ASSERT_ONCE(offset > streamfile->filesize, "BUFFER: reading over filesize 0x%x @ 0x%"PRIx64" + 0x%x\n", streamfile->filesize, (off64_t)offset, length); + VGM_ASSERT_ONCE(offset > streamfile->filesize, "BUFFER: reading over filesize 0x%x @ 0x%x + 0x%x\n", streamfile->filesize, (uint32_t)offset, length); break; } @@ -800,6 +800,15 @@ STREAMFILE * open_streamfile_by_filename(STREAMFILE *streamFile, const char * na return streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); } +STREAMFILE * reopen_streamfile(STREAMFILE *streamFile, size_t buffer_size) { + char pathname[PATH_LIMIT]; + + if (buffer_size == 0) + buffer_size = STREAMFILE_DEFAULT_BUFFER_SIZE; + streamFile->get_name(streamFile,pathname,sizeof(pathname)); + return streamFile->open(streamFile,pathname,buffer_size); +} + /* Read a line into dst. The source files are lines separated by CRLF (Windows) / LF (Unux) / CR (Mac). * The line will be null-terminated and CR/LF removed if found. @@ -955,6 +964,17 @@ fail: return 0; } +/* hack to allow relative paths in various OSs */ +void fix_dir_separators(char * filename) { + char c; + int i = 0; + while ((c = filename[i]) != '\0') { + if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\')) + filename[i] = DIR_SEPARATOR; + i++; + } +} + /** * Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix"). diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.h b/Frameworks/vgmstream/vgmstream/src/streamfile.h index 85f964747..a18493254 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.h @@ -123,6 +123,10 @@ STREAMFILE * open_streamfile_by_ext(STREAMFILE *streamFile, const char * ext); * Can be used to get companion files. */ STREAMFILE * open_streamfile_by_filename(STREAMFILE *streamFile, const char * filename); +/* Reopen a STREAMFILE with a different buffer size, for fine-tuned bigfile parsing. + * Uses default buffer size when buffer_size is 0 */ +STREAMFILE * reopen_streamfile(STREAMFILE *streamFile, size_t buffer_size); + /* close a file, destroy the STREAMFILE object */ static inline void close_streamfile(STREAMFILE * streamfile) { @@ -198,6 +202,12 @@ static inline int guess_endianness32bit(off_t offset, STREAMFILE * streamfile) { return ((uint32_t)read_32bitLE(offset,streamfile) > (uint32_t)read_32bitBE(offset,streamfile)) ? 1 : 0; } +static inline size_t align_size_to_block(size_t value, size_t block_align) { + size_t extra_size = value % block_align; + if (extra_size == 0) return value; + return (value + block_align - extra_size); +} + /* various STREAMFILE helpers functions */ size_t get_streamfile_text_line(int dst_length, char * dst, off_t offset, STREAMFILE * streamfile, int *line_done_ptr); @@ -206,6 +216,8 @@ size_t read_string(char * buf, size_t bufsize, off_t offset, STREAMFILE *streamF size_t read_key_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile); +void fix_dir_separators(char * filename); + int check_extensions(STREAMFILE *streamFile, const char * cmp_exts); int find_chunk_be(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size); diff --git a/Frameworks/vgmstream/vgmstream/src/streamtypes.h b/Frameworks/vgmstream/vgmstream/src/streamtypes.h index 3b2cca352..c4be0d310 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamtypes.h +++ b/Frameworks/vgmstream/vgmstream/src/streamtypes.h @@ -14,7 +14,10 @@ #include #endif /* (_MSC_VER >= 1600) */ +#ifndef inline /* (_MSC_VER < 1900)? */ #define inline _inline +#endif + #define strcasecmp _stricmp #define strncasecmp _strnicmp diff --git a/Frameworks/vgmstream/vgmstream/src/util.h b/Frameworks/vgmstream/vgmstream/src/util.h index c5469cf4f..4f2d03684 100644 --- a/Frameworks/vgmstream/vgmstream/src/util.h +++ b/Frameworks/vgmstream/vgmstream/src/util.h @@ -67,6 +67,14 @@ static inline int clamp16(int32_t val) { return val; } +static inline int round10(int val) { + int round_val = val % 10; + if (round_val < 5) /* half-down rounding */ + return val - round_val; + else + return val + (10 - round_val); +} + /* return a file's extension (a pointer to the first character of the * extension in the original filename or the ending null byte if no extension */ const char * filename_extension(const char * filename); diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 35f1cfecb..0ad83efd8 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -39,7 +39,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_ads, init_vgmstream_ps2_npsf, init_vgmstream_rwsd, - init_vgmstream_cdxa, + init_vgmstream_xa, init_vgmstream_ps2_rxws, init_vgmstream_ps2_rxw, init_vgmstream_ngc_dsp_stm, @@ -84,6 +84,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_pos, init_vgmstream_nwa, init_vgmstream_ea_1snh, + init_vgmstream_ea_eacs, init_vgmstream_xss, init_vgmstream_sl3, init_vgmstream_hgc1, @@ -150,7 +151,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ngc_ymf, init_vgmstream_sadl, init_vgmstream_ps2_ccc, - init_vgmstream_psx_fag, + init_vgmstream_fag, init_vgmstream_ps2_mihb, init_vgmstream_ngc_pdt_split, init_vgmstream_ngc_pdt, @@ -192,8 +193,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_vgs, init_vgmstream_dc_dcsw_dcs, init_vgmstream_wii_smp, - init_vgmstream_emff_ps2, - init_vgmstream_emff_ngc, + init_vgmstream_mul, init_vgmstream_thp, init_vgmstream_wii_sts, init_vgmstream_ps2_p2bt, @@ -213,7 +213,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_mcg, init_vgmstream_zsd, init_vgmstream_ps2_vgs, - init_vgmstream_RedSpark, + init_vgmstream_redspark, init_vgmstream_ivaud, init_vgmstream_wii_wsd, init_vgmstream_wii_ndp, @@ -290,7 +290,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_spm, init_vgmstream_x360_tra, init_vgmstream_ps2_iab, - init_vgmstream_ps2_strlr, + init_vgmstream_vs_str, init_vgmstream_lsf_n1nj4n, init_vgmstream_vawx, init_vgmstream_ps2_wmus, @@ -345,6 +345,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ta_aac_mobile, init_vgmstream_ta_aac_mobile_vorbis, init_vgmstream_ta_aac_vita, + init_vgmstream_va3, init_vgmstream_ps3_mta2, init_vgmstream_ngc_ulw, init_vgmstream_pc_xa30, @@ -352,7 +353,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ea_bnk, init_vgmstream_ea_abk, init_vgmstream_ea_hdr_dat, - init_vgmstream_ea_idx_big, + init_vgmstream_ea_map_mus, + init_vgmstream_ea_mpf_mus, init_vgmstream_ea_schl_fixed, init_vgmstream_sk_aud, init_vgmstream_stm, @@ -364,18 +366,20 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_opus_nop, init_vgmstream_opus_shinen, init_vgmstream_opus_nus3, - init_vgmstream_opus_nlsd, + init_vgmstream_opus_sps_n1, init_vgmstream_opus_nxa, init_vgmstream_pc_al2, init_vgmstream_pc_ast, init_vgmstream_naac, init_vgmstream_ubi_sb, + init_vgmstream_ubi_sm, init_vgmstream_ezw, init_vgmstream_vxn, init_vgmstream_ea_snr_sns, init_vgmstream_ea_sps, init_vgmstream_ea_abk_new, init_vgmstream_ea_hdr_sth_dat, + init_vgmstream_ea_mpf_mus_new, init_vgmstream_ngc_vid1, init_vgmstream_flx, init_vgmstream_mogg, @@ -405,7 +409,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_smc_smh, init_vgmstream_ea_sps_fb, init_vgmstream_ppst, - init_vgmstream_opus_ppp, + init_vgmstream_opus_sps_n1_segmented, init_vgmstream_ubi_bao_pk, init_vgmstream_dsp_switch_audio, init_vgmstream_sadf, @@ -422,7 +426,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_bnk_sony, init_vgmstream_nus3bank, init_vgmstream_scd_sscf, - init_vgmstream_dsp_vag, + init_vgmstream_dsp_sps_n1, init_vgmstream_dsp_itl_ch, init_vgmstream_a2m, init_vgmstream_ahv, @@ -441,7 +445,23 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_utk, init_vgmstream_adpcm_capcom, init_vgmstream_ue4opus, - + init_vgmstream_xwma, + init_vgmstream_xopus, + init_vgmstream_vs_square, + init_vgmstream_msf_banpresto_wmsf, + init_vgmstream_msf_banpresto_2msf, + init_vgmstream_nwav, + init_vgmstream_xpcm, + init_vgmstream_msf_tamasoft, + init_vgmstream_xps_dat, + init_vgmstream_xps, + init_vgmstream_zsnd, + init_vgmstream_opus_opusx, + init_vgmstream_dsp_adpcmx, + init_vgmstream_ogg_opus, + init_vgmstream_nus3audio, + init_vgmstream_imc, + init_vgmstream_imc_container, /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ @@ -990,8 +1010,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_blocked_matx: case layout_blocked_dec: case layout_blocked_vs: - case layout_blocked_emff_ps2: - case layout_blocked_emff_ngc: + case layout_blocked_mul: case layout_blocked_gsb: case layout_blocked_xvas: case layout_blocked_thp: @@ -1002,7 +1021,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_blocked_bdsp: case layout_blocked_tra: case layout_blocked_ps2_iab: - case layout_blocked_ps2_strlr: + case layout_blocked_vs_str: case layout_blocked_rws: case layout_blocked_hwas: case layout_blocked_ea_sns: @@ -1015,6 +1034,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_blocked_sthd: case layout_blocked_h4m: case layout_blocked_xa_aiff: + case layout_blocked_vs_square: render_vgmstream_blocked(buffer,sample_count,vgmstream); break; case layout_aix: @@ -1116,6 +1136,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_DERF: case coding_NWA: case coding_SASSC: + case coding_CIRCUS_ADPCM: return 1; case coding_IMA: @@ -1129,6 +1150,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_3DS_IMA: case coding_WV6_IMA: case coding_ALP_IMA: + case coding_FFTA2_IMA: + case coding_PCFX: return 2; case coding_XBOX_IMA: case coding_XBOX_IMA_mch: @@ -1290,6 +1313,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_DERF: case coding_NWA: case coding_SASSC: + case coding_CIRCUS_ADPCM: return 0x01; case coding_IMA: @@ -1299,6 +1323,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_3DS_IMA: case coding_WV6_IMA: case coding_ALP_IMA: + case coding_FFTA2_IMA: + case coding_PCFX: return 0x01; case coding_MS_IMA: case coding_RAD_IMA: @@ -1733,6 +1759,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to vgmstream->channels,vgmstream->samples_into_block,samples_to_do); } break; + case coding_CIRCUS_ADPCM: + for (ch = 0; ch < vgmstream->channels; ch++) { + decode_circus_adpcm(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, + vgmstream->channels,vgmstream->samples_into_block,samples_to_do); + } + break; case coding_IMA: case coding_IMA_int: @@ -1766,6 +1798,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to vgmstream->channels,vgmstream->samples_into_block,samples_to_do); } break; + case coding_FFTA2_IMA: + for (ch = 0; ch < vgmstream->channels; ch++) { + decode_ffta2_ima(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, + vgmstream->channels,vgmstream->samples_into_block,samples_to_do); + } + break; case coding_APPLE_IMA4: for (ch = 0; ch < vgmstream->channels; ch++) { @@ -1986,6 +2024,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to vgmstream->interleave_block_size); } break; + case coding_PCFX: + for (ch = 0; ch < vgmstream->channels; ch++) { + decode_pcfx(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, + vgmstream->channels,vgmstream->samples_into_block,samples_to_do, vgmstream->codec_config); + } + break; + case coding_EA_MT: for (ch = 0; ch < vgmstream->channels; ch++) { decode_ea_mt(vgmstream, buffer+samples_written*vgmstream->channels+ch, @@ -2160,7 +2205,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { /* Write a description of the stream into array pointed by desc, which must be length bytes long. * Will always be null-terminated if length > 0 */ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { -#define TEMPSIZE 256 +#define TEMPSIZE (256+32) char temp[TEMPSIZE]; const char* description; @@ -2308,12 +2353,13 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { concatn(length,desc,temp); } - if (vgmstream->num_streams > 1 && vgmstream->stream_index > 0) { + if (vgmstream->num_streams > 1) { snprintf(temp,TEMPSIZE, "\nstream index: %d", - vgmstream->stream_index); + vgmstream->stream_index == 0 ? 1 : vgmstream->stream_index); concatn(length,desc,temp); } + if (vgmstream->stream_name[0] != '\0') { snprintf(temp,TEMPSIZE, "\nstream name: %s", diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 5c8941ab1..02f8020f5 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -122,6 +122,7 @@ typedef enum { coding_OTNS_IMA, /* Omikron The Nomad Soul IMA ADPCM */ coding_WV6_IMA, /* Gorilla Systems WV6 4-bit IMA ADPCM */ coding_ALP_IMA, /* High Voltage ALP 4-bit IMA ADPCM */ + coding_FFTA2_IMA, /* Final Fantasy Tactics A2 4-bit IMA ADPCM */ coding_MS_IMA, /* Microsoft IMA ADPCM */ coding_XBOX_IMA, /* XBOX IMA ADPCM */ @@ -155,6 +156,7 @@ typedef enum { coding_FADPCM, /* FMOD FADPCM 4-bit ADPCM */ coding_ASF, /* Argonaut ASF 4-bit ADPCM */ coding_XMD, /* Konami XMD 4-bit ADPCM */ + coding_PCFX, /* PC-FX 4-bit ADPCM */ /* others */ coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression DPCM */ @@ -165,6 +167,7 @@ typedef enum { coding_DERF, /* DERF 8-bit DPCM */ coding_ACM, /* InterPlay ACM */ coding_NWA, /* VisualArt's NWA */ + coding_CIRCUS_ADPCM, /* Circus 8-bit ADPCM */ coding_EA_MT, /* Electronic Arts MicroTalk (linear-predictive speech codec) */ @@ -234,8 +237,7 @@ typedef enum { layout_blocked_dec, layout_blocked_xvas, layout_blocked_vs, - layout_blocked_emff_ps2, - layout_blocked_emff_ngc, + layout_blocked_mul, layout_blocked_gsb, layout_blocked_thp, layout_blocked_filp, @@ -246,7 +248,7 @@ typedef enum { layout_blocked_ivaud, /* GTA IV .ivaud blocks */ layout_blocked_tra, /* DefJam Rapstar .tra blocks */ layout_blocked_ps2_iab, - layout_blocked_ps2_strlr, + layout_blocked_vs_str, layout_blocked_rws, layout_blocked_hwas, layout_blocked_ea_sns, /* newest Electronic Arts blocks, found in SNS/SNU/SPS/etc formats */ @@ -259,6 +261,7 @@ typedef enum { layout_blocked_sthd, /* Dream Factory STHD */ layout_blocked_h4m, /* H4M video */ layout_blocked_xa_aiff, /* XA in AIFF files [Crusader: No Remorse (SAT), Road Rash (3DO)] */ + layout_blocked_vs_square, /* otherwise odd */ layout_aix, /* CRI AIX's wheels within wheels */ @@ -326,7 +329,7 @@ typedef enum { meta_HIS, /* Her Ineractive .his */ meta_BNSF, /* Bandai Namco Sound Format */ - meta_PSX_XA, /* CD-ROM XA */ + meta_XA, /* CD-ROM XA */ meta_PS2_SShd, /* .ADS with SShd header */ meta_PS2_NPSF, /* Namco Production Sound File */ meta_PS2_RXWS, /* Sony games (Genji, Okage Shadow King, Arc The Lad Twilight of Spirits) */ @@ -347,7 +350,7 @@ typedef enum { meta_PS2_BMDX, /* Beatmania thing */ meta_PS2_IVB, /* Langrisser 3 IVB */ meta_PS2_SND, /* some Might & Magics SSND header */ - meta_PS2_SVS, /* Square SVS */ + meta_SVS, /* Square SVS */ meta_XSS, /* Dino Crisis 3 */ meta_SL3, /* Test Drive Unlimited */ meta_HGC1, /* Knights of the Temple 2 */ @@ -410,7 +413,7 @@ typedef enum { meta_NGC_YMF, /* WWE WrestleMania X8 */ meta_SADL, /* .sad */ meta_PS2_CCC, /* Tokyo Xtreme Racer DRIFT 2 */ - meta_PSX_FAG, /* Jackie Chan - Stuntmaster */ + meta_FAG, /* Jackie Chan - Stuntmaster */ meta_PS2_MIHB, /* Merged MIH+MIB */ meta_NGC_PDT, /* Mario Party 6 */ meta_DC_ASD, /* Miss Moonligh */ @@ -437,8 +440,7 @@ typedef enum { meta_RSD6WMA, /* RSD6WMA */ meta_PS2_ASS, /* ASS */ - meta_PS2_SEG, /* Eragon */ - meta_XBOX_SEG, /* Eragon */ + meta_SEG, /* Eragon */ meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */ meta_STR_ASR, /* Donkey Kong Jet Race */ meta_ZWDSP, /* Zack and Wiki */ @@ -446,8 +448,7 @@ typedef enum { meta_DC_DCSW_DCS, /* Evil Twin - Cypriens Chronicles (DC) */ meta_WII_SMP, /* Mushroom Men - The Spore Wars */ meta_WII_SNG, /* Excite Trucks */ - meta_EMFF_PS2, /* Eidos Music File Format for PS2*/ - meta_EMFF_NGC, /* Eidos Music File Format for NGC/WII */ + meta_MUL, meta_SAT_BAKA, /* Crypt Killer */ meta_PS2_VSF, /* Musashi: Samurai Legend */ meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ @@ -468,6 +469,7 @@ typedef enum { meta_EA_SCHL_fixed, /* Electronic Arts SCHl with fixed header */ meta_EA_BNK, /* Electronic Arts BNK */ meta_EA_1SNH, /* Electronic Arts 1SNh/EACS */ + meta_EA_EACS, meta_RAW, /* RAW PCM file */ @@ -507,8 +509,8 @@ typedef enum { meta_PS2_TK5, /* Tekken 5 Stream Files */ meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */ meta_ZSD, /* Dragon Booster ZSD */ - meta_RedSpark, /* "RedSpark" RSD (MadWorld) */ - meta_IVAUD, /* .ivaud GTA IV */ + meta_REDSPARK, /* "RedSpark" RSD (MadWorld) */ + meta_IVAUD, /* .ivaud GTA IV */ meta_NDS_HWAS, /* Spider-Man 3, Tony Hawk's Downhill Jam, possibly more... */ meta_NGC_LPS, /* Rave Master (Groove Adventure Rave)(GC) */ meta_NAOMI_ADPCM, /* NAOMI/NAOMI2 ARcade games */ @@ -572,7 +574,7 @@ typedef enum { meta_X360_TRA, /* Def Jam Rapstar */ meta_PS2_VGS, /* Princess Soft PS2 games */ meta_PS2_IAB, /* Ueki no Housoku - Taosu ze Robert Juudan!! (PS2) */ - meta_PS2_STRLR, /* The Bouncer */ + meta_VS_STR, /* The Bouncer */ meta_LSF_N1NJ4N, /* .lsf n1nj4n Fastlane Street Racing (iPhone) */ meta_VAWX, /* feelplus: No More Heroes Heroes Paradise, Moon Diver */ meta_PC_SNDS, /* Incredibles PC .snds */ @@ -646,18 +648,14 @@ typedef enum { meta_MOGG, /* Harmonix Music Systems MOGG Vorbis */ meta_OGG_VORBIS, /* Ogg Vorbis */ meta_OGG_SLI, /* Ogg Vorbis file w/ companion .sli for looping */ - meta_OGG_SLI2, /* Ogg Vorbis file w/ different styled .sli for looping */ + meta_OPUS_SLI, /* Ogg Opus file w/ companion .sli for looping */ meta_OGG_SFL, /* Ogg Vorbis file w/ .sfl (RIFF SFPL) for looping */ - meta_OGG_UM3, /* Ogg Vorbis with optional encryption */ - meta_OGG_KOVS, /* Ogg Vorbis with encryption (Koei Tecmo Games) */ - meta_OGG_PSYCHIC, /* Ogg Vorbis with encryption */ - meta_OGG_SNGW, /* Ogg Vorbis with optional encryption (Capcom PC games) */ - meta_OGG_ISD, /* Ogg Vorbis with encryption (Azure Striker Gunvolt PC) */ + meta_OGG_KOVS, /* Ogg Vorbis with header and encryption (Koei Tecmo Games) */ + meta_OGG_encrypted, /* Ogg Vorbis with encryption */ meta_KMA9, /* Koei Tecmo [Nobunaga no Yabou - Souzou (Vita)] */ meta_XWC, /* Starbreeze games */ meta_SQEX_SAB, /* Square-Enix newest middleware (sound) */ meta_SQEX_MAB, /* Square-Enix newest middleware (music) */ - meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */ meta_WAF, /* KID WAF [Ever 17 (PC)] */ meta_WAVE, /* EngineBlack games [Mighty Switch Force! (3DS)] */ meta_WAVE_segmented, /* EngineBlack games, segmented [Shantae and the Pirate's Curse (PC)] */ @@ -671,19 +669,14 @@ typedef enum { meta_DSP_MCADPCM, /* Skyrim (Switch) */ meta_UBI_LYN, /* Ubisoft LyN engine [The Adventures of Tintin (multi)] */ meta_MSB_MSH, /* sfx companion of MIH+MIB */ - meta_OGG_RPGMV, /* Ogg Vorbis with encryption [RPG Maker MV games (PC)] */ - meta_OGG_ENO, /* Ogg Vorbis with encryption [Metronomicon (PC)] */ meta_TXTP, /* generic text playlist */ meta_SMC_SMH, /* Wangan Midnight (System 246) */ - meta_OGG_YS8, /* Ogg Vorbis with encryption (Ys VIII PC) */ meta_PPST, /* PPST [Parappa the Rapper (PSP)] */ meta_OPUS_PPP, /* .at9 Opus [Penny-Punching Princess (Switch)] */ meta_UBI_BAO, /* Ubisoft BAO */ meta_DSP_SWITCH_AUDIO, /* Gal Gun 2 (Switch) */ meta_TA_AAC_VITA, /* tri-Ace AAC (Judas Code) */ - meta_OGG_GWM, /* Ogg Vorbis with encryption [Metronomicon (PC)] */ meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */ - meta_OGG_MUS, /* Ogg Vorbis with encryption [Redux - Dark Matters (PC)] */ meta_ASF, /* Argonaut ASF [Croc 2 (PC)] */ meta_XMD, /* Konami XMD [Silent Hill 4 (Xbox), Castlevania: Curse of Darkness (Xbox)] */ meta_CKS, /* Cricket Audio stream [Part Time UFO (Android), Mega Man 1-6 (Android)] */ @@ -713,6 +706,18 @@ typedef enum { meta_NXA, meta_ADPCM_CAPCOM, meta_UE4OPUS, + meta_XWMA, + meta_VA3, /* DDR Supernova 2 AC */ + meta_XOPUS, + meta_VS_SQUARE, + meta_NWAV, + meta_XPCM, + meta_MSF_TAMASOFT, + meta_XPS_DAT, + meta_ZSND, + meta_DSP_ADPCMX, + meta_OGG_OPUS, + meta_IMC, } meta_t; @@ -955,7 +960,8 @@ typedef enum { MPEG_EAL32P, /* EALayer3 v2 "PCM", custom frames with v2 header + bigger PCM blocks? */ MPEG_EAL32S, /* EALayer3 v2 "Spike", custom frames with v2 header + smaller PCM blocks? */ MPEG_LYN, /* N streams of fixed interleave */ - MPEG_AWC /* N streams in block layout (music) or absolute offsets (sfx) */ + MPEG_AWC, /* N streams in block layout (music) or absolute offsets (sfx) */ + MPEG_EAMP3 /* custom frame header + MPEG frame + PCM blocks */ } mpeg_custom_t; /* config for the above modes */ @@ -1038,7 +1044,6 @@ typedef struct { typedef struct { sample buffer[960]; void *handle; - int16_t *code_buffer; } g719_codec_data; #endif