@@ -32,9 +32,11 @@ static void storeU32(uint32_t value, uint8_t* buffer) {
3232    buffer[3 ] = (value >> 24 ) & 0xff ;
3333}
3434
35- //  make sure to call this with a sector that's memset to 0
36- static  void  getSector (uint8_t  data[2048 ], uint32_t  lba, uint32_t  exeSize, uint32_t  exeOffset = 19 ) {
35+ //  make sure to call this with a sector that's memset to 0, as it relies on zeros being
36+ //  in the right place.
37+ static  void  getSectorMinimal (uint8_t  data[2048 ], uint32_t  lba, uint32_t  exeSize, uint32_t  exeOffset = 19 ) {
3738    switch  (lba) {
39+         //  Minimal PVD
3840        case  16 :
3941            data[0 ] = 1 ;
4042            data[1 ] = ' C' 
@@ -46,11 +48,13 @@ static void getSector(uint8_t data[2048], uint32_t lba, uint32_t exeSize, uint32
4648            storeU32 (17 , data + 140 );
4749            storeU32 (18 , data + 158 );
4850            break ;
51+         //  Minimal path table
4952        case  17 :
5053            data[0 ] = 1 ;
5154            data[2 ] = 18 ;
5255            data[6 ] = 1 ;
5356            break ;
57+         //  Minimal root directory
5458        case  18 :
5559            data[0 ] = 42 ;
5660            storeU32 (exeOffset, data + 2 );
@@ -69,16 +73,20 @@ static void getSector(uint8_t data[2048], uint32_t lba, uint32_t exeSize, uint32
6973    }
7074}
7175
72- //  make sure to call this with a sector that's memset to 0, as it relies on zeros being
73- //  in the right place.
74- static  void  makeHeader (uint8_t  sector[2352 ], uint32_t  lba) {
75-     PCSX::IEC60908b::MSF time (lba + 150 );
76+ //  Call this once on a sector that's been memset to 0,
77+ //  in order to set all of the immutable data.
78+ static  void  makeHeaderOnce (uint8_t  sector[2352 ]) {
7679    memset (sector + 1 , 0xff , 10 );
77-     time.toBCD (sector + 12 );
7880    sector[15 ] = 2 ;
7981    sector[18 ] = sector[22 ] = 8 ;
8082}
8183
84+ //  This function sets the LBA in the header of the sector.
85+ static  void  makeHeader (uint8_t  sector[2352 ], uint32_t  lba) {
86+     PCSX::IEC60908b::MSF time (lba + 150 );
87+     time.toBCD (sector + 12 );
88+ }
89+ 
8290int  main (int  argc, char ** argv) {
8391    CommandLine::args args (argc, argv);
8492
@@ -96,12 +104,14 @@ exe2iso by Nicolas "Pixel" Noble
96104    const  bool  pad = args.get <bool >(" pad" value_or (false );
97105    const  bool  regen = args.get <bool >(" regen" value_or (false );
98106    const  auto  license = args.get <std::string>(" license" 
107+     const  auto  data = args.get <std::string>(" data" 
99108    if  (asksForHelp || !oneInput || !hasOutput) {
100109        fmt::print (R"( 
101110Usage: {} input.ps-exe [-offset value] [-pad] [-regen] [-license file] -o output.bin 
102111  input.ps-exe      mandatory: specify the input ps-exe file. 
103112  -o output.bin     mandatory: name of the output file. 
104113  -offset value     optional: move the exe data by value sectors. 
114+   -data filename    optional: insert this file into the iso after the exe. 
105115  -pad              optional: pads the iso with 150 blank sectors. 
106116  -regen            optional: generates proper ECC/EDC. 
107117  -license file     optional: use this license file. 
@@ -114,17 +124,29 @@ Usage: {} input.ps-exe [-offset value] [-pad] [-regen] [-license file] -o output
114124    auto & input = inputs[0 ];
115125    PCSX::IO<PCSX::File> file (new  PCSX::PosixFile (input));
116126    if  (file->failed ()) {
117-         fmt::print (" Unable to open  file:  {}\n " 
127+         fmt::print (" Error opening input  file {}\n " 
118128        return  -1 ;
119129    }
120130    PCSX::IO<PCSX::File> licenseFile (new  PCSX::FailedFile);
131+     PCSX::IO<PCSX::File> dataFile (new  PCSX::FailedFile);
121132    PCSX::IO<PCSX::File> out (new  PCSX::PosixFile (output.value (), PCSX::FileOps::TRUNCATE));
122133    if  (out->failed ()) {
123134        fmt::print (" Error opening output file {}\n " value ());
124135        return  -1 ;
125136    }
126137    if  (license.has_value ()) {
127138        licenseFile.setFile (new  PCSX::PosixFile (license.value ()));
139+         if  (licenseFile->failed ()) {
140+             fmt::print (" Error opening license file {}\n " value ());
141+             return  -1 ;
142+         }
143+     }
144+     if  (data.has_value ()) {
145+         dataFile.setFile (new  PCSX::PosixFile (data.value ()));
146+         if  (dataFile->failed ()) {
147+             fmt::print (" Error opening data file {}\n " value ());
148+             return  -1 ;
149+         }
128150    }
129151
130152    uint32_t  exeSize = file->size ();
@@ -134,77 +156,80 @@ Usage: {} input.ps-exe [-offset value] [-pad] [-regen] [-license file] -o output
134156    uint32_t  exeOffset = 19  + offset;
135157
136158    uint8_t  sector[2352 ];
159+     memset (sector, 0 , sizeof (sector));
160+     makeHeaderOnce (sector);
137161    bool  wroteLicense = false ;
162+     unsigned  LBA = 0 ;
163+     auto  writeSector = [&]() {
164+         makeHeader (sector, LBA++);
165+         if  (regen) compute_edcecc (sector);
166+         out->write (sector, sizeof (sector));
167+     };
138168    //  Sectors 0-15 are the license. We can keep it to zeroes and it'll work most everywhere.
139169    if  (licenseFile && !licenseFile->failed ()) {
140170        uint8_t  licenseData[2352  * 16 ];
141171        memset (licenseData, 0 , sizeof (licenseData));
142172        licenseFile->read (licenseData, sizeof (licenseData));
143-         if  (licenseData[0x2492 ] == ' L' 
173+         if  ((licenseFile-> size () ==  2336  *  16 ) && ( licenseData[0x2492 ] == ' L' ) ) {
144174            //  official license file from the sdk, in 2336 bytes per sector.
145175            for  (unsigned  i = 0 ; i < 16 ; i++) {
146-                 memset (sector, 0 , sizeof (sector));
147176                memcpy (sector + 16 , licenseData + 2336  * i, 2336 );
148-                 makeHeader (sector, i);
149-                 if  (regen) compute_edcecc (sector);
150-                 out->write (sector, sizeof (sector));
177+                 writeSector ();
151178            }
152179            wroteLicense = true ;
153180        } else  if  (licenseData[0x24e2 ] == ' L' 
154181            //  looks like an iso file itself
155182            for  (unsigned  i = 0 ; i < 16 ; i++) {
156183                memcpy (sector, licenseData + 2352  * i, 2352 );
157-                 makeHeader (sector, i);
158-                 if  (regen) compute_edcecc (sector);
159-                 out->write (sector, sizeof (sector));
184+                 makeHeaderOnce (sector);
185+                 writeSector ();
160186            }
161187            wroteLicense = true ;
162188        } else  {
163189            fmt::print (" Unrecognized LICENSE file format {}\n " value ());
164190        }
165191    }
166192    if  (!wroteLicense) {
193+         memset (sector, 0 , sizeof (sector));
167194        for  (unsigned  i = 0 ; i < 16 ; i++) {
168-             memset (sector, 0 , sizeof (sector));
169-             makeHeader (sector, i);
170-             if  (regen) compute_edcecc (sector);
171-             out->write (sector, sizeof (sector));
195+             writeSector ();
172196        }
173197    }
174198    //  The actual structure of the iso. We're only generating 3 sectors,
175199    //  from 16 to 18, as it's the only things necessary for the PS1 bios.
176-     for  (unsigned  i = 16 ; i < 19 ; i++) {
200+     for  (unsigned  i = 0 ; i < 3 ; i++) {
177201        memset (sector, 0 , sizeof (sector));
178-         makeHeader (sector, i );
202+         makeHeaderOnce (sector);
179203        //  This function will fill the sector with the right data, as
180204        //  necessary for the PS1 bios.
181-         getSector (sector + 24 , i, exeSize, exeOffset);
182-         if  (regen) compute_edcecc (sector);
183-         out->write (sector, sizeof (sector));
205+         getSectorMinimal (sector + 24 , LBA, exeSize, exeOffset);
206+         writeSector ();
184207    }
185208    //  Potential padding before the start of the exe.
186-     for  (unsigned  i = 19 ; i < exeOffset; i++) {
187-         memset (sector, 0 , sizeof (sector));
188-         makeHeader (sector, i);
189-         if  (regen) compute_edcecc (sector);
190-         out->write (sector, sizeof (sector));
209+     memset (sector, 0 , sizeof (sector));
210+     makeHeaderOnce (sector);
211+     for  (unsigned  i = 0 ; i < offset; i++) {
212+         writeSector ();
191213    }
192-     unsigned  LBA = exeOffset;
193214    //  The actual exe.
194215    for  (unsigned  i = 0 ; i < exeSize; i += 2048 ) {
195-         memset (sector, 0 , sizeof (sector));
196-         makeHeader (sector, LBA++);
197216        file->read (sector + 24 , 2048 );
198-         if  (regen) compute_edcecc (sector);
199-         out->write (sector, sizeof (sector));
217+         writeSector ();
218+     }
219+     if  (dataFile && !dataFile->failed ()) {
220+         //  The additional data file.
221+         unsigned  sectors = (dataFile->size () + 2047 ) / 2048 ;
222+         for  (unsigned  i = 0 ; i < sectors; i++) {
223+             dataFile->read (sector + 24 , 2048 );
224+             writeSector ();
225+         }
200226    }
227+     memset (sector, 0 , sizeof (sector));
228+     makeHeaderOnce (sector);
201229    if  (pad) {
202230        //  150 sectors padding.
203231        for  (unsigned  i = 0 ; i < 150 ; i++) {
204-             memset (sector, 0 , sizeof (sector));
205-             makeHeader (sector, LBA++);
206-             if  (regen) compute_edcecc (sector);
207-             out->write (sector, sizeof (sector));
232+             writeSector ();
208233        }
209234    }
210235    fmt::print (" Done." 
0 commit comments