@@ -52,7 +52,7 @@ function createTransferStatus(overrides = {}) {
5252const defaultConfig = {
5353 address : '192.168.0.100' ,
5454 storage : '/data' ,
55- connections : 4 ,
55+ connections : 6 ,
5656 ftp_connections : 6 ,
5757 use_temp : false ,
5858 auto_connect : false ,
@@ -1403,6 +1403,22 @@ function payloadPathIsElf(filepath) {
14031403 return ext === '.elf' || ext === '.bin' ;
14041404}
14051405
1406+ function findLocalPayloadElf ( ) {
1407+ const candidates = [
1408+ path . resolve ( __dirname , '../payload/ps5upload.elf' ) ,
1409+ path . resolve ( process . cwd ( ) , 'payload/ps5upload.elf' ) ,
1410+ path . resolve ( process . cwd ( ) , 'ps5upload.elf' ) ,
1411+ ] ;
1412+ for ( const p of candidates ) {
1413+ try {
1414+ if ( fs . existsSync ( p ) && payloadPathIsElf ( p ) ) return p ;
1415+ } catch {
1416+ // ignore
1417+ }
1418+ }
1419+ return null ;
1420+ }
1421+
14061422function probePayloadFile ( filepath ) {
14071423 if ( ! payloadPathIsElf ( filepath ) ) {
14081424 return { is_ps5upload : false , code : 'payload_probe_invalid_ext' } ;
@@ -1435,6 +1451,26 @@ async function sendPayloadFile(ip, filepath) {
14351451 } ) ;
14361452}
14371453
1454+ async function waitForPayloadStartup ( ip , expectedVersion = null , timeoutMs = 15000 , pollMs = 500 ) {
1455+ const startedAt = Date . now ( ) ;
1456+ let lastErr = null ;
1457+ while ( Date . now ( ) - startedAt < timeoutMs ) {
1458+ try {
1459+ const version = await getPayloadVersion ( ip , TRANSFER_PORT ) ;
1460+ if ( ! expectedVersion || String ( version ) === String ( expectedVersion ) ) {
1461+ return { ok : true , version } ;
1462+ }
1463+ return { ok : false , version, error : `Running ${ version } , expected ${ expectedVersion } ` } ;
1464+ } catch ( err ) {
1465+ lastErr = err ;
1466+ }
1467+ // eslint-disable-next-line no-await-in-loop
1468+ // eslint-disable-next-line no-await-in-loop
1469+ await new Promise ( ( resolve ) => setTimeout ( resolve , Math . max ( 100 , Number ( pollMs ) || 500 ) ) ) ;
1470+ }
1471+ return { ok : false , version : null , error : `Payload did not start in ${ Math . round ( timeoutMs / 1000 ) } s: ${ lastErr && lastErr . message ? lastErr . message : String ( lastErr || 'timeout' ) } ` } ;
1472+ }
1473+
14381474function compareVersions ( a , b ) {
14391475 const ma = String ( a || '' ) . match ( VERSION_RE ) ;
14401476 const mb = String ( b || '' ) . match ( VERSION_RE ) ;
@@ -1728,12 +1764,31 @@ async function handleInvoke(cmd, args, runtime) {
17281764 const filepath = ( args && args . path ? String ( args . path ) : '' ) . trim ( ) ;
17291765 if ( ! ip ) throw new Error ( 'Enter a PS5 address first.' ) ;
17301766 if ( ! filepath ) throw new Error ( 'Select a payload (.elf/.bin) file first.' ) ;
1731- return sendPayloadFile ( ip , filepath ) ;
1767+ const sent = await sendPayloadFile ( ip , filepath ) ;
1768+ const probe = probePayloadFile ( filepath ) ;
1769+ if ( probe && probe . is_ps5upload ) {
1770+ const startup = await waitForPayloadStartup ( ip , runtime . version , 15000 , 500 ) ;
1771+ if ( ! startup . ok ) {
1772+ throw new Error ( `Payload upload completed but startup verification failed: ${ startup . error } ` ) ;
1773+ }
1774+ }
1775+ return sent ;
17321776 }
17331777 case 'payload_download_and_send' : {
17341778 const ip = ( args && args . ip ? String ( args . ip ) : '' ) . trim ( ) ;
17351779 const fetchMode = ( args && args . fetch ? String ( args . fetch ) : 'latest' ) . trim ( ) ;
17361780 if ( ! ip ) throw new Error ( 'Enter a PS5 address first.' ) ;
1781+ if ( fetchMode === 'current' ) {
1782+ const localPayload = findLocalPayloadElf ( ) ;
1783+ if ( localPayload ) {
1784+ const sent = await sendPayloadFile ( ip , localPayload ) ;
1785+ const startup = await waitForPayloadStartup ( ip , runtime . version , 15000 , 500 ) ;
1786+ if ( ! startup . ok ) {
1787+ throw new Error ( `Payload upload completed but startup verification failed: ${ startup . error } ` ) ;
1788+ }
1789+ return sent ;
1790+ }
1791+ }
17371792 let release ;
17381793 if ( fetchMode === 'current' ) {
17391794 try {
@@ -1750,7 +1805,13 @@ async function handleInvoke(cmd, args, runtime) {
17501805 if ( ! asset || ! asset . browser_download_url ) throw new Error ( 'Payload asset not found in release' ) ;
17511806 const tmpPath = path . join ( os . tmpdir ( ) , `ps5upload_${ fetchMode } .elf` ) ;
17521807 await downloadAsset ( asset . browser_download_url , tmpPath ) ;
1753- return sendPayloadFile ( ip , tmpPath ) ;
1808+ const sent = await sendPayloadFile ( ip , tmpPath ) ;
1809+ const expected = fetchMode === 'current' ? runtime . version : null ;
1810+ const startup = await waitForPayloadStartup ( ip , expected , 15000 , 500 ) ;
1811+ if ( ! startup . ok ) {
1812+ throw new Error ( `Payload upload completed but startup verification failed: ${ startup . error } ` ) ;
1813+ }
1814+ return sent ;
17541815 }
17551816 case 'payload_check' : {
17561817 const ip = ( args && args . ip ? String ( args . ip ) : '' ) . trim ( ) ;
0 commit comments