@@ -2569,6 +2569,13 @@ static void do_extract_cd(parameters_map ¶ms)
2569
2569
2570
2570
// GDIs will always output as split bin
2571
2571
bool is_splitbin = mode == MODE_GDI || params.find (OPTION_OUTPUT_SPLIT) != params.end ();
2572
+ if (!is_splitbin && cdrom->is_gdrom () && mode == MODE_CUEBIN)
2573
+ {
2574
+ // GD-ROM cue/bin is in Redump format which should always be split by tracks
2575
+ util::stream_format (std::cout, " Warning: --%s is required for this specific combination of input disc type and output format, enabling automatically\n " , OPTION_OUTPUT_SPLIT);
2576
+ is_splitbin = true ;
2577
+ }
2578
+
2572
2579
if (is_splitbin)
2573
2580
{
2574
2581
if (mode == MODE_GDI)
@@ -2612,11 +2619,6 @@ static void do_extract_cd(parameters_map ¶ms)
2612
2619
std::string trackbin_name;
2613
2620
try
2614
2621
{
2615
- if (cdrom->is_gdrom () && (mode == MODE_CUEBIN))
2616
- {
2617
- util::stream_format (std::cout, " Warning: extracting GD-ROM CHDs as bin/cue is not fully supported and will result in an unusable CD-ROM cue file.\n " );
2618
- }
2619
-
2620
2622
// process output file
2621
2623
std::error_condition filerr = util::core_file::open (*output_file_str->second , OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file);
2622
2624
if (filerr)
@@ -2736,6 +2738,55 @@ static void do_extract_cd(parameters_map ¶ms)
2736
2738
output_toc_file->printf (" CD_ROM\n\n\n " );
2737
2739
}
2738
2740
2741
+ if (cdrom->is_gdrom () && mode == MODE_CUEBIN)
2742
+ {
2743
+ // modify TOC to match Redump cue/bin format as best as possible
2744
+ cdrom_file::toc *trackinfo = (cdrom_file::toc*)&toc;
2745
+
2746
+ // TOSEC GDI-based CHDs have the padframes field set to non-0 where the pregaps for the next track would be
2747
+ const bool has_physical_pregap = trackinfo->tracks [0 ].padframes == 0 ;
2748
+
2749
+ for (int tracknum = 1 ; tracknum < toc.numtrks ; tracknum++)
2750
+ {
2751
+ // pgdatasize should never be set in GD-ROMs currently, so if it is set then assume the TOC has proper pregap values
2752
+ if (trackinfo->tracks [tracknum].pgdatasize != 0 )
2753
+ break ;
2754
+
2755
+ // don't adjust the first track of the single-density and high-density areas
2756
+ if (toc.tracks [tracknum].physframeofs == 45000 )
2757
+ continue ;
2758
+
2759
+ if (!has_physical_pregap)
2760
+ {
2761
+ // NOTE: This will generate a cue with PREGAP commands instead of INDEX 00 because the pregap data isn't baked into the bins
2762
+ trackinfo->tracks [tracknum].pregap += trackinfo->tracks [tracknum-1 ].padframes ;
2763
+
2764
+ if (tracknum + 1 >= toc.numtrks && toc.tracks [tracknum].trktype != cdrom_file::CD_TRACK_AUDIO)
2765
+ {
2766
+ // TODO: These 75 frames are actually included at the end of the previous track so should be written
2767
+ // It's currently not possible to format it as expected without hacky code because the 150 pregap for the last track
2768
+ // is sandwiched between these 75 frames and the actual track data.
2769
+ // The 75 frames seems to normally be 0s so this should be ok for now until a use case is found.
2770
+ trackinfo->tracks [tracknum-1 ].frames -= 75 ;
2771
+ trackinfo->tracks [tracknum].pregap += 75 ;
2772
+ }
2773
+ }
2774
+ else
2775
+ {
2776
+ int curextra = 150 ; // 00:02:00
2777
+ if (tracknum + 1 >= toc.numtrks && toc.tracks [tracknum+1 ].trktype != cdrom_file::CD_TRACK_AUDIO)
2778
+ curextra += 75 ; // 00:01:00, special case when last track is data
2779
+
2780
+ trackinfo->tracks [tracknum-1 ].padframes = curextra;
2781
+
2782
+ trackinfo->tracks [tracknum].pregap += curextra;
2783
+ trackinfo->tracks [tracknum].splitframes = curextra;
2784
+ trackinfo->tracks [tracknum].pgdatasize = trackinfo->tracks [tracknum].datasize ;
2785
+ trackinfo->tracks [tracknum].pgtype = trackinfo->tracks [tracknum].trktype ;
2786
+ }
2787
+ }
2788
+ }
2789
+
2739
2790
// iterate over tracks and copy all data
2740
2791
uint64_t totaloutputoffs = 0 ;
2741
2792
uint64_t outputoffs = 0 ;
@@ -2766,6 +2817,14 @@ static void do_extract_cd(parameters_map ¶ms)
2766
2817
output_bin_filenames.push_back (trackbin_name);
2767
2818
}
2768
2819
2820
+ if (cdrom->is_gdrom () && mode == MODE_CUEBIN)
2821
+ {
2822
+ if (tracknum == 0 )
2823
+ output_toc_file->printf (" REM SINGLE-DENSITY AREA\n " );
2824
+ else if (toc.tracks [tracknum].physframeofs == 45000 )
2825
+ output_toc_file->printf (" REM HIGH-DENSITY AREA\n " );
2826
+ }
2827
+
2769
2828
// output the metadata about the track to the TOC file
2770
2829
const cdrom_file::track_info &trackinfo = toc.tracks [tracknum];
2771
2830
output_track_metadata (mode, *output_toc_file, tracknum, trackinfo, std::string (core_filename_extract_base (trackbin_name)), discoffs, outputoffs);
@@ -2785,31 +2844,44 @@ static void do_extract_cd(parameters_map ¶ms)
2785
2844
2786
2845
// now read and output the actual data
2787
2846
uint32_t bufferoffs = 0 ;
2788
- uint32_t actualframes = trackinfo.frames - trackinfo.padframes ;
2847
+ uint32_t actualframes = trackinfo.frames - trackinfo.padframes + trackinfo. splitframes ;
2789
2848
for (uint32_t frame = 0 ; frame < actualframes; frame++)
2790
2849
{
2791
2850
progress (false , " Extracting, %.1f%% complete... \r " , 100.0 * double (totaloutputoffs + outputoffs) / double (total_bytes));
2792
2851
2852
+ int trk, frameofs;
2853
+ if (tracknum > 0 && frame < trackinfo.splitframes )
2854
+ {
2855
+ // pull data from previous track, the reverse of how splitframes is used when making the GD-ROM CHDs
2856
+ trk = tracknum - 1 ;
2857
+ frameofs = toc.tracks [trk].frames - trackinfo.splitframes + frame;
2858
+ }
2859
+ else
2860
+ {
2861
+ trk = tracknum;
2862
+ frameofs = frame - trackinfo.splitframes ;
2863
+ }
2864
+
2793
2865
// read the data
2794
- cdrom->read_data (cdrom->get_track_start_phys (tracknum ) + frame , &buffer[bufferoffs], trackinfo .trktype , true );
2866
+ cdrom->read_data (cdrom->get_track_start_phys (trk ) + frameofs , &buffer[bufferoffs], toc. tracks [trk] .trktype , true );
2795
2867
2796
2868
// for CDRWin and GDI audio tracks must be reversed
2797
2869
// in the case of GDI and CHD version < 5 we assuming source CHD image is GDROM so audio tracks is already reversed
2798
- if (((mode == MODE_GDI && input_chd.version () > 4 ) || (mode == MODE_CUEBIN)) && (trackinfo .trktype == cdrom_file::CD_TRACK_AUDIO))
2799
- for (int swapindex = 0 ; swapindex < trackinfo .datasize ; swapindex += 2 )
2870
+ if (((mode == MODE_GDI && input_chd.version () > 4 ) || (mode == MODE_CUEBIN)) && (toc. tracks [trk] .trktype == cdrom_file::CD_TRACK_AUDIO))
2871
+ for (int swapindex = 0 ; swapindex < toc. tracks [trk] .datasize ; swapindex += 2 )
2800
2872
{
2801
2873
uint8_t swaptemp = buffer[bufferoffs + swapindex];
2802
2874
buffer[bufferoffs + swapindex] = buffer[bufferoffs + swapindex + 1 ];
2803
2875
buffer[bufferoffs + swapindex + 1 ] = swaptemp;
2804
2876
}
2805
- bufferoffs += trackinfo .datasize ;
2877
+ bufferoffs += toc. tracks [trk] .datasize ;
2806
2878
discoffs++;
2807
2879
2808
2880
// read the subcode data
2809
- if (trackinfo .subtype != cdrom_file::CD_SUB_NONE && (mode == MODE_NORMAL))
2881
+ if (toc. tracks [trk] .subtype != cdrom_file::CD_SUB_NONE && (mode == MODE_NORMAL))
2810
2882
{
2811
- cdrom->read_subcode (cdrom->get_track_start_phys (tracknum ) + frame , &buffer[bufferoffs], true );
2812
- bufferoffs += trackinfo .subsize ;
2883
+ cdrom->read_subcode (cdrom->get_track_start_phys (trk ) + frameofs , &buffer[bufferoffs], true );
2884
+ bufferoffs += toc. tracks [trk] .subsize ;
2813
2885
}
2814
2886
2815
2887
// write it out if we need to
@@ -2824,28 +2896,6 @@ static void do_extract_cd(parameters_map ¶ms)
2824
2896
}
2825
2897
}
2826
2898
2827
- if (cdrom->is_gdrom () && mode == MODE_CUEBIN && trackinfo.padframes > 0 )
2828
- {
2829
- uint32_t padframes = trackinfo.padframes ;
2830
-
2831
- // don't write the pad frames between the end of the single density area and start of the high density area
2832
- if (tracknum+1 < toc.numtrks && toc.tracks [tracknum+1 ].physframeofs == 45000 )
2833
- padframes = 0 ;
2834
-
2835
- bufferoffs = 0 ;
2836
- std::fill (buffer.begin (), buffer.end (), 0 );
2837
-
2838
- while (bufferoffs < padframes)
2839
- {
2840
- auto const [writerr, byteswritten] = write (*output_bin_file, &buffer[0 ], output_frame_size);
2841
- if (writerr)
2842
- report_error (1 , " Error writing pad data to file (%s): %s\n " , *output_file_str->second , " Write error" );
2843
- bufferoffs++;
2844
- }
2845
-
2846
- outputoffs += output_frame_size * padframes;
2847
- }
2848
-
2849
2899
discoffs += trackinfo.padframes ;
2850
2900
}
2851
2901
0 commit comments