import ArrayBufferSlice from "../../ArrayBufferSlice" ; import * as BHD5 from "../bhd5" ; import * as MSB from "../msb" ; import * as BYML from "../../byml" ; import { readFileSync , openSync , readSync , closeSync , fstat , writeFileSync } from "fs" ; function fetchDataSync ( path ) { const b = readFileSync ( path ) ; return new ArrayBufferSlice ( b . buffer ) ; } function fetchDataFragmentSync ( path , byteOffset , byteLength ) { const fd = openSync ( path , 'r' ) ; const b = Buffer . alloc ( byteLength ) ; readSync ( fd , b , 0 , byteLength , byteOffset ) ; closeSync ( fd ) ; return new ArrayBufferSlice ( b . buffer ) ; } const pathBaseIn = `../../../data/dks_raw` ; const pathBaseOut = `../../../data/dks` ; function hashString ( str ) { let h = 0 ; str = str . toLowerCase ( ) ; for ( let i = 0 ; i < str . length ; i ++ ) { const c = str . charCodeAt ( i ) ; h = ( ( 37 * h + c ) & 0xFFFFFFFF ) >>> 0 ; } return h ; } class ResourceSystem { public hashToRecord = new Map < number , BHD5 . FileRecord > ( ) ; public hashToDataFilename = new Map < number , string > ( ) ; public mountBHD5 ( bhd5 , dataFilename ) { const records = bhd5 . fileRecords ; for ( let i = 0 ; i < records . length ; i ++ ) { this . hashToRecord . set ( records [ i ] . nameHash , records [ i ] ) ; this . hashToDataFilename . set ( records [ i ] . nameHash , dataFilename ) ; } } public fileExists ( filename ) { const nameHash = hashString ( filename ) ; return this . hashToRecord . has ( nameHash ) ; } public fetchDataFromFilename ( filename ) { const nameHash = hashString ( filename ) ; const record = this . hashToRecord . get ( nameHash ) ; const dataFilename = this . hashToDataFilename . get ( nameHash ) ; return fetchDataFragmentSync ( dataFilename , record . byteOffset , record . byteSize ) ; } } function pushFile ( filenames , r , f ) { if ( r . fileExists ( f ) ) filenames . add ( f ) ; else console . warn ( "Missing file" , f ) ; } function gatherMapArchive ( filenames , r , mapID ) { const mapFilename = `/map/MapStudio/${ mapID }.msb` ; pushFile ( filenames , r , mapFilename ) ; const mapKey = mapID . slice ( 0 , 3 ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0000.tpfbhd` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0000.tpfbdt` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0001.tpfbhd` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0001.tpfbdt` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0002.tpfbhd` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0002.tpfbdt` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0003.tpfbhd` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_0003.tpfbdt` ) ; pushFile ( filenames , r , `/map/${ mapKey }/${ mapKey }_9999.tpf.dcx` ) ; const msb = MSB . parse ( r . fetchDataFromFilename ( mapFilename ) , mapID ) ; for ( let i = 0 ; i < msb . models . length ; i ++ ) if ( msb . models [ i ] . type === 0x00 ) pushFile ( filenames , r , msb . models [ i ] . flverPath ) ; } function buildMapCRG1 ( r , mapID , mapFilenames ) { const files = { } ; const sortedFilenames = [ ... mapFilenames . keys ( ) ] ; for ( let i = 0 ; i < sortedFilenames . length ; i ++ ) files [ sortedFilenames [ i ] ] = r . fetchDataFromFilename ( sortedFilenames [ i ] ) ; const arc = { MapID : mapID , Files : files , } ; return BYML . write ( arc , BYML . FileType . CRG1 ) ; } function extractMap ( r , mapID ) { const filenames = new Set < string > ( ) ; console . log ( "Gathering" ) ; gatherMapArchive ( filenames , r , mapID ) ; console . log ( "Building" ) ; const data = buildMapCRG1 ( r , mapID , filenames ) ; console . log ( "Writing" ) ; writeFileSync ( `${ pathBaseOut }/${ mapID }_arc.crg1` , Buffer . from ( data ) ) ; console . log ( "Done" , mapID ) ; } function mountBHD5 ( r , archiveName ) { const recordsBuffer = fetchDataSync ( `${ pathBaseIn }/${ archiveName }.bhd5` ) ; const dataFilename = `${ pathBaseIn }/${ archiveName }.bdt` ; const bhd5 = BHD5 . parse ( recordsBuffer ) ; r . mountBHD5 ( bhd5 , dataFilename ) ; } function main ( ) { const r = new ResourceSystem ( ) ; mountBHD5 ( r , 'dvdbnd0' ) ; mountBHD5 ( r , 'dvdbnd1' ) ; extractMap ( r , 'm10_01_00_00' ) ; extractMap ( r , 'm10_00_00_00' ) ; extractMap ( r , 'm10_02_00_00' ) ; extractMap ( r , 'm11_00_00_00' ) ; extractMap ( r , 'm12_00_00_00' ) ; extractMap ( r , 'm12_00_00_01' ) ; extractMap ( r , 'm12_01_00_00' ) ; extractMap ( r , 'm13_00_00_00' ) ; extractMap ( r , 'm13_01_00_00' ) ; extractMap ( r , 'm13_02_00_00' ) ; extractMap ( r , 'm14_00_00_00' ) ; extractMap ( r , 'm14_01_00_00' ) ; extractMap ( r , 'm15_00_00_00' ) ; extractMap ( r , 'm15_01_00_00' ) ; extractMap ( r , 'm16_00_00_00' ) ; extractMap ( r , 'm17_00_00_00' ) ; extractMap ( r , 'm18_00_00_00' ) ; extractMap ( r , 'm18_01_00_00' ) ; } main ( ) ;