added bin_to_cso_mp3 tool
authornotaz <notasas@gmail.com>
Sat, 3 May 2008 16:26:03 +0000 (16:26 +0000)
committernotaz <notasas@gmail.com>
Sat, 3 May 2008 16:26:03 +0000 (16:26 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@435 be3aeb3a-fb24-0410-a615-afba39da0efa

platform/gp2x/Makefile
platform/psp/Makefile
tools/bin_to_cso_mp3/bin_to_cso_mp3.c [new file with mode: 0644]
tools/bin_to_cso_mp3/bin_to_cso_mp3.exe [new file with mode: 0755]
tools/bin_to_cso_mp3/readme.txt [new file with mode: 0644]

index 4c55445..59a7c15 100644 (file)
@@ -237,6 +237,10 @@ endif
 rel: PicoDrive.gpe code940/pico940_v2.bin readme.txt PicoDrive.man.txt PicoDrive.png ../game_def.cfg\r
        zip -9 -j ../../PicoDrive_$(VER).zip $^ mmuhack.o\r
        zip -9 -r ../../PicoDrive_$(VER).zip skin -i \*.png -i \*.txt\r
+       mkdir bin_to_cso_mp3\r
+       cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/\r
+       zip -9 -r ../../PicoDrive_$(VER).zip bin_to_cso_mp3\r
+       rm -rf bin_to_cso_mp3\r
 \r
 code940/code940.bin:\r
        make -C code940/\r
index a2f37f0..c89f1d6 100644 (file)
@@ -179,6 +179,10 @@ rel: EBOOT.PBP readme.txt ../game_def.cfg
        cp skin/* PicoDrive/skin/\r
        zip -9 -r ../../PicoDrive_psp_$(VER).zip PicoDrive\r
        rm -rf PicoDrive\r
+       mkdir bin_to_cso_mp3\r
+       cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/\r
+       zip -9 -r ../../PicoDrive_psp_$(VER).zip bin_to_cso_mp3\r
+       rm -rf bin_to_cso_mp3\r
 \r
 rel_kxploit: readme.txt ../game_def.cfg\r
        mkdir -p PicoDrive/skin/\r
@@ -186,4 +190,8 @@ rel_kxploit: readme.txt ../game_def.cfg
        cp skin/* PicoDrive/skin/\r
        zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip PicoDrive\r
        zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip PicoDrive%\r
+       mkdir bin_to_cso_mp3\r
+       cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/\r
+       zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip bin_to_cso_mp3\r
+       rm -rf bin_to_cso_mp3\r
 \r
diff --git a/tools/bin_to_cso_mp3/bin_to_cso_mp3.c b/tools/bin_to_cso_mp3/bin_to_cso_mp3.c
new file mode 100644 (file)
index 0000000..87a5599
--- /dev/null
@@ -0,0 +1,723 @@
+/*\r
+ * bin_to_cso_mp3\r
+ * originally written by Exophase as "bin_to_iso_ogg"\r
+ * updated for cso/mp3 by notaz\r
+ */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <sys/stat.h>\r
+#include <string.h>\r
+\r
+#ifndef MAX_PATH\r
+#define MAX_PATH 1024\r
+#endif\r
+\r
+#ifdef _WIN32\r
+#include <windows.h>\r
+\r
+#define DIR_SEPARATOR_CHAR '\\'\r
+#define PATH_SEPARATOR_CHAR ';'\r
+#define LAME_BINARY "lame.exe"\r
+#define CISO_BINARY "ciso.exe"\r
+#define NULL_REDIR  "> NUL 2>&1"\r
+#else\r
+#define DIR_SEPARATOR_CHAR '/'\r
+#define PATH_SEPARATOR_CHAR ':'\r
+#define LAME_BINARY "lame"\r
+#define CISO_BINARY "ciso"\r
+#define NULL_REDIR  "> /dev/null 2>&1"\r
+#define mkdir(x) mkdir(x, S_IRWXU)\r
+#endif\r
+\r
+#define LAME_OPTIONS "-h --cbr"\r
+\r
+typedef unsigned char u8;\r
+typedef unsigned short int u16;\r
+typedef unsigned int u32;\r
+typedef unsigned long long int u64;\r
+typedef signed char s8;\r
+typedef signed short int s16;\r
+typedef signed int s32;\r
+typedef signed long long int s64;\r
+\r
+typedef enum\r
+{\r
+  TRACK_FILE_TYPE_BINARY,\r
+  TRACK_FILE_TYPE_WAVE,\r
+} track_file_type_enum;\r
+\r
+typedef struct\r
+{\r
+  u32 file_number;\r
+  u32 physical_offset;\r
+\r
+  u32 sector_offset;\r
+  u32 sector_count;\r
+  u32 pregap_offset;\r
+\r
+  u32 sector_size;\r
+  u32 format_type;\r
+} cd_track_struct;\r
+\r
+typedef struct\r
+{\r
+  track_file_type_enum type;\r
+  FILE *file_handle;\r
+\r
+  u32 current_offset;\r
+} cd_track_file_struct;\r
+\r
+typedef struct\r
+{\r
+  FILE *bin_file;\r
+  cd_track_file_struct track_files[100];\r
+  u32 num_files;\r
+\r
+  s32 first_track;\r
+  s32 last_track;\r
+  u32 num_physical_tracks;\r
+  u32 num_sectors;\r
+  s32 last_seek_track;\r
+\r
+  cd_track_struct physical_tracks[100];\r
+  cd_track_struct *logical_tracks[100];\r
+} cd_bin_struct;\r
+\r
+\r
+cd_bin_struct cd_bin;\r
+int opt_use_mp3 = 1;\r
+int opt_mp3_bitrate = 128;\r
+int opt_use_cso = 1;\r
+\r
+static void myexit(int code)\r
+{\r
+#ifdef _WIN32\r
+  system("pause");\r
+#endif\r
+  exit(code);\r
+}\r
+\r
+char *skip_whitespace(char *str)\r
+{\r
+  while(*str == ' ')\r
+    str++;\r
+\r
+  return str;\r
+}\r
+\r
+s32 load_bin_cue(char *cue_file_name)\r
+{\r
+  FILE *cue_file = fopen(cue_file_name, "rb");\r
+\r
+  printf("loading cue file %s\n", cue_file_name);\r
+\r
+  if(cue_file)\r
+  {\r
+    char line_buffer[256];\r
+    char *line_buffer_ptr;\r
+\r
+    char bin_file_name[MAX_PATH];\r
+    char *separator_pos;\r
+    s32 current_physical_track_number = -1;\r
+    u32 current_physical_offset;\r
+    u32 current_pregap = 0;\r
+    u32 bin_file_size;\r
+\r
+    cd_track_struct *current_physical_track = NULL;\r
+\r
+    u32 i;\r
+\r
+    // First, get filename. Only support binary right now.\r
+    fgets(line_buffer, 255, cue_file);\r
+\r
+    strcpy(bin_file_name, strchr(line_buffer, '"') + 1);\r
+\r
+    *(strrchr(bin_file_name, '"')) = 0;\r
+\r
+    // Might have to change directory first.\r
+    separator_pos = strrchr(cue_file_name, DIR_SEPARATOR_CHAR);\r
+\r
+    if(separator_pos)\r
+    {\r
+      char current_dir[MAX_PATH];\r
+      getcwd(current_dir, MAX_PATH);\r
+\r
+      *separator_pos = 0;\r
+\r
+      chdir(cue_file_name);\r
+\r
+#ifdef GP2X_BUILD\r
+      cd_bin.bin_file = open(bin_file_name, O_RDONLY);\r
+#else\r
+      cd_bin.bin_file = fopen(bin_file_name, "rb");\r
+#endif\r
+\r
+      printf("loaded bin file %s (%p)\n", bin_file_name, cd_bin.bin_file);\r
+\r
+      *separator_pos = DIR_SEPARATOR_CHAR;\r
+      chdir(current_dir);\r
+    }\r
+    else\r
+    {\r
+#ifdef GP2X_BUILD\r
+      cd_bin.bin_file = open(bin_file_name, O_RDONLY);\r
+#else\r
+      cd_bin.bin_file = fopen(bin_file_name, "rb");\r
+#endif\r
+    }\r
+\r
+    for(i = 0; i < 100; i++)\r
+    {\r
+      cd_bin.logical_tracks[i] = NULL;\r
+    }\r
+\r
+    cd_bin.first_track = -1;\r
+    cd_bin.last_track = -1;\r
+    cd_bin.num_physical_tracks = 0;\r
+    cd_bin.num_sectors = 0;\r
+\r
+    // Get line\r
+    while(fgets(line_buffer, 256, cue_file))\r
+    {\r
+      // Skip trailing whitespace\r
+      line_buffer_ptr = skip_whitespace(line_buffer);\r
+\r
+      // Dirty, but should work - switch on first character.\r
+      switch(line_buffer_ptr[0])\r
+      {\r
+        // New track number\r
+        case 'T':\r
+        {\r
+          u32 new_track_number;\r
+          char track_type[64];\r
+\r
+          sscanf(line_buffer_ptr, "TRACK %d %s", &new_track_number,\r
+           track_type);\r
+\r
+          current_physical_track_number++;\r
+          current_physical_track =\r
+           cd_bin.physical_tracks + current_physical_track_number;\r
+\r
+          current_physical_track->sector_size = 2352;\r
+\r
+          if(!strcmp(track_type, "AUDIO"))\r
+          {\r
+            current_physical_track->format_type = 0;\r
+            current_physical_track->sector_size = 2352;\r
+          }\r
+\r
+          if(!strcmp(track_type, "MODE1/2352"))\r
+          {\r
+            current_physical_track->format_type = 4;\r
+            current_physical_track->sector_size = 2352;\r
+          }\r
+\r
+          if(!strcmp(track_type, "MODE1/2048"))\r
+          {\r
+            current_physical_track->format_type = 4;\r
+            current_physical_track->sector_size = 2048;\r
+          }\r
+\r
+          cd_bin.logical_tracks[new_track_number] = current_physical_track;\r
+          cd_bin.num_physical_tracks++;\r
+\r
+          if((cd_bin.first_track == -1) ||\r
+           (new_track_number < cd_bin.first_track))\r
+          {\r
+            cd_bin.first_track = new_track_number;\r
+          }\r
+\r
+          if((cd_bin.last_track == -1) ||\r
+           (new_track_number > cd_bin.last_track))\r
+          {\r
+            cd_bin.last_track = new_track_number;\r
+          }\r
+\r
+          break;\r
+        }\r
+\r
+        // Pregap\r
+        case 'P':\r
+        {\r
+          u32 minutes, seconds, frames;\r
+\r
+          sscanf(line_buffer_ptr, "PREGAP %d:%d:%d", &minutes,\r
+           &seconds, &frames);\r
+\r
+          current_pregap += frames + (seconds * 75) + (minutes * 75 * 60);\r
+          break;\r
+        }\r
+\r
+        // Index\r
+        case 'I':\r
+        {\r
+          u32 index_number;\r
+          u32 minutes, seconds, frames;\r
+          u32 sector_offset;\r
+\r
+          sscanf(line_buffer_ptr, "INDEX %d %d:%d:%d", &index_number,\r
+           &minutes, &seconds, &frames);\r
+\r
+          sector_offset = frames + (seconds * 75) + (minutes * 75 * 60);\r
+\r
+          if(index_number == 1)\r
+          {\r
+            current_physical_track->pregap_offset = current_pregap;\r
+            current_physical_track->sector_offset = sector_offset;\r
+          }\r
+\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    current_physical_offset = 0;\r
+\r
+    for(i = 0; i < cd_bin.num_physical_tracks - 1; i++)\r
+    {\r
+      cd_bin.physical_tracks[i].sector_count =\r
+       cd_bin.physical_tracks[i + 1].sector_offset -\r
+       cd_bin.physical_tracks[i].sector_offset;\r
+\r
+      cd_bin.physical_tracks[i].physical_offset = current_physical_offset;\r
+      current_physical_offset += (cd_bin.physical_tracks[i].sector_count *\r
+       cd_bin.physical_tracks[i].sector_size);\r
+\r
+      cd_bin.physical_tracks[i].sector_offset +=\r
+       cd_bin.physical_tracks[i].pregap_offset;\r
+\r
+      cd_bin.num_sectors += cd_bin.physical_tracks[i].sector_count;\r
+    }\r
+\r
+#ifdef GP2X_BUILD\r
+    bin_file_size = lseek(cd_bin.bin_file, 0, SEEK_END);\r
+    lseek(cd_bin.bin_file, 0, SEEK_SET);\r
+#else\r
+    fseek(cd_bin.bin_file, 0, SEEK_END);\r
+    bin_file_size = ftell(cd_bin.bin_file);\r
+    fseek(cd_bin.bin_file, 0, SEEK_SET);\r
+#endif\r
+\r
+    // Set the last track data\r
+    cd_bin.physical_tracks[i].physical_offset = current_physical_offset;\r
+    cd_bin.physical_tracks[i].sector_offset +=\r
+     cd_bin.physical_tracks[i].pregap_offset;\r
+    cd_bin.physical_tracks[i].sector_count =\r
+     (bin_file_size - current_physical_offset) /\r
+     cd_bin.physical_tracks[i].sector_size;\r
+\r
+    cd_bin.num_sectors += cd_bin.physical_tracks[i].sector_count;\r
+\r
+    printf("finished loading cue %s\n", cue_file_name);\r
+    printf("bin file: %s (%p)\n", bin_file_name, cd_bin.bin_file);\r
+    printf("first track: %d, last track: %d\n", cd_bin.first_track,\r
+     cd_bin.last_track);\r
+\r
+    for(i = cd_bin.first_track; i <= cd_bin.last_track; i++)\r
+    {\r
+      printf("track %d (%p):\n", i, cd_bin.logical_tracks[i]);\r
+      if(cd_bin.logical_tracks[i] == NULL)\r
+      {\r
+        printf("  (invalid)\n");\r
+      }\r
+      else\r
+      {\r
+        printf("  physical offset 0x%x\n",\r
+         cd_bin.logical_tracks[i]->physical_offset);\r
+        printf("  sector offset 0x%x\n",\r
+         cd_bin.logical_tracks[i]->sector_offset);\r
+        printf("  sector size %d\n",\r
+         cd_bin.logical_tracks[i]->sector_size);\r
+      }\r
+    }\r
+\r
+    cd_bin.last_seek_track = 0;\r
+\r
+    fclose(cue_file);\r
+    return 0;\r
+  }\r
+\r
+  return -1;\r
+}\r
+\r
+#define address8(base, offset)                                                \\r
+  *((u8 *)((u8 *)base + (offset)))                                            \\r
+\r
+#define address16(base, offset)                                               \\r
+  *((u16 *)((u8 *)base + (offset)))                                           \\r
+\r
+#define address32(base, offset)                                               \\r
+  *((u32 *)((u8 *)base + (offset)))                                           \\r
+\r
+// This will only work on little endian platforms for now.\r
+\r
+s32 convert_bin_to_wav(FILE *bin_file, char *output_dir, char *wav_file_name,\r
+ u32 sector_count)\r
+{\r
+  FILE *wav_file;\r
+  u8 wav_header[36];\r
+  u8 *riff_header = wav_header + 0;\r
+  u8 *fmt_header = wav_header + 0x0C;\r
+  u8 sector_buffer[2352];\r
+  u32 byte_length = sector_count * 2352;\r
+  u32 i;\r
+\r
+  chdir(output_dir);\r
+  wav_file = fopen(wav_file_name, "wb");\r
+\r
+  printf("writing wav %s, %x sectors\n", wav_file_name, sector_count);\r
+\r
+  // RIFF type chunk\r
+  memcpy(riff_header   + 0x00, "RIFF", 4);\r
+  address32(riff_header, 0x04) = byte_length + 44 - 8;\r
+  memcpy(riff_header   + 0x08, "WAVE", 4);\r
+\r
+  // WAVE file chunk: format\r
+  memcpy(fmt_header   + 0x00, "fmt ", 4);\r
+  // Chunk data size\r
+  address32(fmt_header, 0x04) = 16;\r
+  // Compression code: PCM\r
+  address16(fmt_header, 0x08) = 1;\r
+  // Number of channels: Stereo\r
+  address16(fmt_header, 0x0a) = 2;\r
+  // Sample rate: 44100Hz\r
+  address32(fmt_header, 0x0c) = 44100;\r
+  // Average bytes per second: sample rate * 4\r
+  address32(fmt_header, 0x10) = 44100 * 4;\r
+  // Block align (bytes per sample)\r
+  address16(fmt_header, 0x14) = 4;\r
+  // Bit depth\r
+  address16(fmt_header, 0x16) = 16;\r
+\r
+  // Write out header\r
+  fwrite(wav_header, 36, 1, wav_file);\r
+\r
+  // DATA chunk\r
+  fprintf(wav_file, "data");\r
+  // length\r
+  fwrite(&byte_length, 4, 1, wav_file);\r
+\r
+  // Write out sectors\r
+  for(i = 0; i < sector_count; i++)\r
+  {\r
+    printf("\b\b\b%3i", i*100 / sector_count);\r
+    fflush(stdout);\r
+    fread(sector_buffer, 2352, 1, bin_file);\r
+    fwrite(sector_buffer, 2352, 1, wav_file);\r
+  }\r
+  printf("\b\b\b100\n");\r
+\r
+  fclose(wav_file);\r
+  chdir("..");\r
+  return 0;\r
+}\r
+\r
+void convert_wav_to_ogg(char *wav_file_name, char *output_dir,\r
+ char *ogg_file_name)\r
+{\r
+  char cmd_string[(MAX_PATH * 2) + 16];\r
+\r
+  chdir(output_dir);\r
+  sprintf(cmd_string, "oggenc %s", wav_file_name);\r
+  system(cmd_string);\r
+\r
+  unlink(wav_file_name);\r
+  chdir("..");\r
+}\r
+\r
+void convert_wav_to_mp3(char *wav_file_name, char *output_dir,\r
+ char *mp3_file_name)\r
+{\r
+  char cmd_string[(MAX_PATH * 2) + 16];\r
+\r
+  chdir(output_dir);\r
+  sprintf(cmd_string, LAME_BINARY " " LAME_OPTIONS " -b %i \"%s\" \"%s\"",\r
+   opt_mp3_bitrate, wav_file_name, mp3_file_name);\r
+  if (system(cmd_string) != 0)\r
+  {\r
+    printf("failed to encode mp3\n");\r
+    myexit(1);\r
+  }\r
+\r
+  unlink(wav_file_name);\r
+  chdir("..");\r
+}\r
+\r
+s32 convert_bin_to_iso(FILE *bin_file, char *output_dir, char *iso_file_name,\r
+ u32 sector_count)\r
+{\r
+  FILE *iso_file;\r
+  u8 sector_buffer[2352];\r
+  u32 i;\r
+\r
+  chdir(output_dir);\r
+  iso_file = fopen(iso_file_name, "wb");\r
+  if (iso_file == NULL)\r
+  {\r
+    printf("failed to open: %s\n", iso_file_name);\r
+    myexit(1);\r
+  }\r
+  printf("writing iso %s, %x sectors\n", iso_file_name, sector_count);\r
+\r
+  for(i = 0; i < sector_count; i++)\r
+  {\r
+    printf("\b\b\b%3i", i*100 / sector_count);\r
+    fflush(stdout);\r
+    fread(sector_buffer, 2352, 1, bin_file);\r
+    fwrite(sector_buffer + 16, 2048, 1, iso_file);\r
+  }\r
+  printf("\b\b\b100\n");\r
+\r
+  fclose(iso_file);\r
+  chdir("..");\r
+  return 0;\r
+}\r
+\r
+void convert_iso_to_cso(char *output_dir, char *iso_file_name, char *cso_file_name)\r
+{\r
+  char cmd_string[(MAX_PATH * 2) + 16];\r
+\r
+  chdir(output_dir);\r
+  sprintf(cmd_string, CISO_BINARY " 9 \"%s\" \"%s\"", iso_file_name, cso_file_name);\r
+  if (system(cmd_string) != 0)\r
+  {\r
+    printf("failed to convert iso to cso\n");\r
+    myexit(1);\r
+  }\r
+\r
+  unlink(iso_file_name);\r
+  chdir("..");\r
+}\r
+\r
+\r
+#define sector_offset_to_msf(offset, minutes, seconds, frames)                \\r
+{                                                                             \\r
+  u32 _offset = offset;                                                       \\r
+  minutes = (_offset / 75) / 60;                                              \\r
+  seconds = (_offset / 75) % 60;                                              \\r
+  frames = _offset % 75;                                                      \\r
+}                                                                             \\r
+\r
+\r
+s32 convert_bin_cue(char *output_name_base)\r
+{\r
+  char output_file_name[MAX_PATH];\r
+  FILE *output_cue_file;\r
+  FILE *bin_file = cd_bin.bin_file;\r
+  cd_track_struct *current_track;\r
+  u32 m, s, f;\r
+  u32 current_pregap = 0;\r
+  u32 last_pregap = 0;\r
+  u32 i;\r
+  struct stat sb;\r
+\r
+  if(stat(output_name_base, &sb))\r
+    mkdir(output_name_base);\r
+\r
+  sprintf(output_file_name, "%s.cue", output_name_base);\r
+  chdir(output_name_base);\r
+  output_cue_file = fopen(output_file_name, "wb");\r
+  chdir("..");\r
+\r
+  // Every track gets its own file. It's either going to be of type ISO\r
+  // or of type WAV.\r
+\r
+  for(i = 0; i < 100; i++)\r
+  {\r
+    current_track = cd_bin.logical_tracks[i];\r
+    if(current_track != NULL)\r
+    {\r
+      switch(current_track->format_type)\r
+      {\r
+        char output_name_tmp[MAX_PATH];\r
+\r
+        // Audio\r
+        case 0:\r
+        {\r
+          sprintf(output_file_name, "%s_%02d.mp3", output_name_base, i);\r
+          sprintf(output_name_tmp, "%s_%02d.wav", output_name_base, i);\r
+\r
+          fprintf(output_cue_file, "FILE \"%s\" %s\n",\r
+           opt_use_mp3 ? output_file_name : output_name_tmp,\r
+           opt_use_mp3 ? "MP3" : "WAVE");\r
+          fprintf(output_cue_file, "  TRACK %02d AUDIO\n", i);\r
+          current_pregap = current_track->pregap_offset - last_pregap;\r
+          last_pregap = current_track->pregap_offset;\r
+          if(current_pregap > 0)\r
+          {\r
+            sector_offset_to_msf(current_pregap, m, s, f);\r
+            fprintf(output_cue_file, "    PREGAP %02d:%02d:%02d\n", m, s, f);\r
+          }\r
+          fprintf(output_cue_file, "    INDEX 01 00:00:00\n");\r
+          sector_offset_to_msf(current_track->sector_count, m, s, f);\r
+          fprintf(output_cue_file, "    REM LENGTH %02d:%02d:%02d\n", m, s, f);\r
+\r
+          fseek(bin_file, current_track->physical_offset, SEEK_SET);\r
+          convert_bin_to_wav(bin_file, output_name_base, output_name_tmp,\r
+           current_track->sector_count);\r
+          if(opt_use_mp3)\r
+          {\r
+            convert_wav_to_mp3(output_name_tmp, output_name_base,\r
+             output_file_name);\r
+          }\r
+          break;\r
+        }\r
+\r
+        // Data\r
+        default:\r
+          sprintf(output_file_name, "%s_%02d.cso", output_name_base, i);\r
+          sprintf(output_name_tmp, "%s_%02d.iso", output_name_base, i);\r
+          fprintf(output_cue_file, "FILE \"%s\" BINARY\n",\r
+           opt_use_cso ? output_file_name : output_name_tmp);\r
+          fprintf(output_cue_file, "  TRACK %02d MODE1/2048\n", i);\r
+          current_pregap = current_track->pregap_offset - last_pregap;\r
+          last_pregap = current_track->pregap_offset;\r
+          if(current_pregap > 0)\r
+          {\r
+            sector_offset_to_msf(current_pregap, m, s, f);\r
+            fprintf(output_cue_file, "    PREGAP %02d:%02d:%02d\n", m, s, f);\r
+          }\r
+          fprintf(output_cue_file, "    INDEX 01 00:00:00\n");\r
+\r
+          fseek(bin_file, current_track->physical_offset, SEEK_SET);\r
+          convert_bin_to_iso(bin_file, output_name_base, output_name_tmp,\r
+           current_track->sector_count);\r
+          if(opt_use_cso)\r
+          {\r
+            convert_iso_to_cso(output_name_base, output_name_tmp, output_file_name);\r
+          }\r
+          break;\r
+      }\r
+    }\r
+  }\r
+\r
+  fclose(output_cue_file);\r
+\r
+  return 0;\r
+}\r
+\r
+#ifdef _WIN32\r
+static void update_path(void)\r
+{\r
+  char buff1[MAX_PATH], buff2[MAX_PATH];\r
+  char *path;\r
+  int i;\r
+\r
+  path = getenv("PATH");\r
+  GetModuleFileNameA(NULL, buff1, sizeof(buff1));\r
+  for (i = strlen(buff1)-1; i > 0; i--)\r
+    if (buff1[i] == '\\') break;\r
+  buff1[i] = 0;\r
+\r
+  snprintf(buff2, sizeof(buff2), "%s;%s", path, buff1);\r
+  SetEnvironmentVariableA("PATH", buff2);\r
+}\r
+#endif\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+  char out_buff[MAX_PATH], *cue_file, *out_base;\r
+  int a;\r
+\r
+  if(argc < 2)\r
+  {\r
+    printf("bin/cue to cso/mp3 converter\n");\r
+    printf("usage: %s [options] <input cue> [output base]\n", argv[0]);\r
+    printf("options:\n"\r
+           "   -m        output mp3 files for audio (default) (lame required)\n"\r
+           "   -b <rate> mp3 bitrate to use (default is 128)\n"\r
+           "   -w        output wav files for audio\n"\r
+           "   -c        output cso as data track (default) (ciso required)\n"\r
+           "   -i        output iso as data track\n");\r
+    return 0;\r
+  }\r
+\r
+  for (a = 1; a < argc - 1; a++)\r
+  {\r
+    if      (strcmp(argv[a], "-m") == 0)\r
+      opt_use_mp3 = 1;\r
+    else if (strcmp(argv[a], "-w") == 0)\r
+      opt_use_mp3 = 0;\r
+    else if (strcmp(argv[a], "-c") == 0)\r
+      opt_use_cso = 1;\r
+    else if (strcmp(argv[a], "-i") == 0)\r
+      opt_use_cso = 0;\r
+    else if (strcmp(argv[a], "-b") == 0)\r
+    {\r
+      opt_mp3_bitrate = atoi(argv[++a]);\r
+    }\r
+    else\r
+      break;\r
+  }\r
+  cue_file = argv[a];\r
+  out_base = argv[a+1];\r
+\r
+  /* some sanity checks */\r
+  if(strlen(cue_file) < 4 || strcasecmp(cue_file + strlen(cue_file) - 4, ".cue") != 0)\r
+  {\r
+    printf("error: not a cue file specified?\n");\r
+    myexit(1);\r
+  }\r
+\r
+#ifdef _WIN32\r
+  update_path();\r
+#endif\r
+\r
+  if(opt_use_mp3 && system(LAME_BINARY " --help " NULL_REDIR) != 0)\r
+  {\r
+    printf("LAME seems to be missing.\n"\r
+#ifdef _WIN32\r
+      "Download from http://lame.sourceforge.net/links.php#Binaries and extract\n"\r
+      "lame.exe to the same directory as %s\n", argv[0]\r
+#else\r
+      "Install lame using your packet manager, obtain binaries or build from\n"\r
+      "sources at http://lame.sourceforge.net/\n"\r
+#endif\r
+      );\r
+    myexit(1);\r
+  }\r
+\r
+  if(opt_use_cso && system(CISO_BINARY " " NULL_REDIR) != 0)\r
+  {\r
+    printf("CISO seems to be missing.\n"\r
+#ifdef _WIN32\r
+      "Download ciso.exe and extract to the same directory as %s\n"\r
+      "You can take ciso.exe from yacc at http://yacc.pspgen.com/\n", argv[0]\r
+#else\r
+      "Install ciso using your packet manager, obtain binaries or build from\n"\r
+      "sources at http://ciso.tenshu.fr/\n"\r
+#endif\r
+      );\r
+    myexit(1);\r
+  }\r
+\r
+  if(load_bin_cue(cue_file) == 0)\r
+  {\r
+    if(out_base == NULL)\r
+    {\r
+      char *p;\r
+      strncpy(out_buff, cue_file, sizeof(out_buff));\r
+      out_buff[sizeof(out_buff)-1] = 0;\r
+      p = strrchr(out_buff, DIR_SEPARATOR_CHAR);\r
+      if (p != NULL)\r
+      {\r
+        *p++ = 0;\r
+        chdir(out_buff);\r
+        memmove(out_buff, p, strlen(p)+1);\r
+      }\r
+      out_buff[strlen(out_buff)-4] = 0;\r
+      out_base = out_buff;\r
+    }\r
+    if(convert_bin_cue(out_base) != 0)\r
+      myexit(1);\r
+  }\r
+  else\r
+  {\r
+    printf("error: could not load cue file %s\n", cue_file);\r
+    myexit(1);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
diff --git a/tools/bin_to_cso_mp3/bin_to_cso_mp3.exe b/tools/bin_to_cso_mp3/bin_to_cso_mp3.exe
new file mode 100755 (executable)
index 0000000..733795c
Binary files /dev/null and b/tools/bin_to_cso_mp3/bin_to_cso_mp3.exe differ
diff --git a/tools/bin_to_cso_mp3/readme.txt b/tools/bin_to_cso_mp3/readme.txt
new file mode 100644 (file)
index 0000000..5d416e9
--- /dev/null
@@ -0,0 +1,47 @@
+
+bin_to_cso_mp3
+Originally written by Exophase as "bin_to_iso_ogg"
+updated for cso/mp3 by notaz
+
+
+About
+-----
+
+This is a tool to convert cue/bin CD image to cue/cso/mp3 form, useful to use
+with emulators. It can also create ISO instead of CSO and WAV instead of MP3.
+Note that input must be .cue file, along with single .bin file.
+
+
+Easy/Windows usage
+------------------
+
+1. Download LAME from http://lame.sourceforge.net/links.php#Binaries
+   You need an archive or "LAME Bundle" with lame.exe inside. Extract lame.exe
+   to the same directory as bin_to_cso_mp3.exe
+2. Find ciso.exe . It usually comes with ISO->CSO converters, for example yacc
+   (http://yacc.pspgen.com/). Extract ciso.exe to the directory from previous
+   step.
+3. Drag the .cue file you want to convert onto bin_to_cso_mp3.exe . It should
+   pop up console window with some scrolling text, which should close by itself
+   when done. After that you should see new directory with converted files.
+
+
+Advanced usage
+--------------
+
+Just run bin_to_cso_mp3.exe from console terminal (or "command prompt") without
+any parameters to see usage.
+
+
+Linux
+-----
+
+You will need to compile bin_to_cso_mp3.c yourself using gcc:
+$ gcc bin_to_cso_mp3.c -o bin_to_cso_mp3
+
+You will also need to have lame and ciso binaries in PATH. Those can sometimes
+be installed using packet manager from the distribution, or you can compile
+them from sources:
+lame: http://lame.sourceforge.net/
+ciso: http://ciso.tenshu.fr/
+