const readxml = require("./xml"); const {readFile, writeFile} = require("fs/promises"); /** @param {string} tr */ const readItem = tr => { let ret = {}, start = 0, token = null, state = 0, tmp = null; do{ if( tr.charAt(start) === '"') { let end = tr.indexOf('"', start + 1); if( end < 0 ) throw new SyntaxError(`no match quito [${tr}]`); token = tr.slice(start+1, end); start = end + 2; } else { let end = tr.indexOf(" ", start); if( end < 0 ) break; token = tr.slice(start, end); start = end + 1; } if( state === 0 ){ tmp = token; state = 1; } else { ret[ tmp ] = token; state = 0; } }while( true ); if( state == 0 ) throw new SyntaxError(`invalid at [${tr}], ret is ${JSON.stringify(ret)}`); ret[ tmp ] = tr.slice( start ); ret.name = ret.name.slice(0, -4); return ret; } const readDat = s => { return s.match( /^\trom\s.*$/mg ).map( r => readItem( r.slice(1+"rom ( ".length, r.length-" )".length) ) ); } const start = async() => { const data = await readFile("/root/oafb-tool/material/gba.xml"); const xml = readxml( data.toString() ); const rom = await readFile("./cover.dat"); const roms = readDat( rom.toString() ); const romidx = roms.reduce( (r, v) => { r[ `${v.crc.toLowerCase().padStart(8,"0")}${v.sha1.toLowerCase()}` ] = v; return r; }, {}); const db = {}; for( let rom of xml.children ){ const rominfo = rom.children; const description = rominfo.find( t => t.name === "description" )?.children[0]; const publisher = rominfo.find( t => t.name === "publisher" )?.children[0]; const year = rominfo.find( t => t.name === "year" )?.children[0]; const serial = rominfo.find( t => t.name === "info" && t.attributes.name === "serial" )?.attributes.value; const part = rominfo.find( t => t.name === "part" )?.children.find( t => t.name === "dataarea" && t.attributes.name === "rom" )?.children[0]; if( part && serial ){ let ren = romidx[ `${part.attributes.crc.toLowerCase().padStart(8, "0")}${part.attributes.sha1.toLowerCase()}` ]; if( ren ){ let out = { file: ren.name, publisher, year, name: rom.attributes.name }; serial.match(/AGB-[A-Z0-9]{4}/g)?.forEach( ser => db[ser.slice(-4)] = out ); } else console.error( "no match rom", rom.attributes.name );// 可以手动修复 } else console.error( "invalid rom", rom.attributes.name );// 不做修复 } await writeFile("/root/oafb-tool/material/webdb.json", JSON.stringify(db, 0)); } start();