00001 #include <stdio.h>
00002 #include <unistd.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005
00006 void
00007 dump (void *buf, int n)
00008 {
00009 int i;
00010 int j;
00011 int c;
00012
00013 for (i = 0; i < n; i += 16) {
00014 printf ("%04x: ", i);
00015 for (j = 0; j < 16; j++) {
00016 if (i+j < n)
00017 printf ("%02x ", ((unsigned char *)buf)[i+j]);
00018 else
00019 printf (" ");
00020 }
00021 printf (" ");
00022 for (j = 0; j < 16; j++) {
00023 c = ((unsigned char *)buf)[i+j] & 0x7f;
00024 if (i+j >= n)
00025 putchar (' ');
00026 else if (c < ' ' || c == 0x7f)
00027 putchar ('.');
00028 else
00029 putchar (c);
00030 }
00031 printf ("\n");
00032
00033 }
00034 }
00035
00036
00037 #pragma pack(1)
00038 struct TM {
00039 char ID[6];
00040 long offset;
00041 long size;
00042 };
00043
00044
00045 struct music_dir {
00046 struct TM dir;
00047 int nfiles;
00048 struct TM *files;
00049 };
00050
00051 FILE *musicf;
00052 #define MDIRS 4
00053 struct music_dir dirs[MDIRS];
00054
00055 int
00056 open_music_cat (char *filename)
00057 {
00058 int i;
00059 struct music_dir *dp;
00060
00061 if ((musicf = fopen (filename, "rb")) == NULL)
00062 return (-1);
00063
00064 for (i = 0, dp = dirs; i < MDIRS; i++, dp++)
00065 fread (&dp->dir, 1, sizeof dp->dir, musicf);
00066
00067 for (i = 0, dp = dirs; i < MDIRS; i++, dp++) {
00068 printf ("%6.6s 0x%08lx %8ld\n", dp->dir.ID,
00069 dp->dir.offset, dp->dir.size);
00070
00071 dp->nfiles = 32;
00072 dp->files = calloc (dp->nfiles, sizeof *dp->files);
00073 fseek (musicf, dp->dir.offset, SEEK_SET);
00074 fread (dp->files, dp->nfiles, sizeof *dp->files, musicf);
00075 }
00076
00077 return (0);
00078 }
00079
00080 int
00081 get_music (char *filetype, int idx, void *buf, int bufsize)
00082 {
00083 int len;
00084 int i;
00085 struct music_dir *dp;
00086 int n;
00087
00088 len = strlen (filetype);
00089
00090 for (i = 0, dp = dirs; i < MDIRS; i++, dp++) {
00091 if (xstrncasecmp (dp->dir.ID, filetype, len) == 0)
00092 break;
00093 }
00094
00095 if (i == MDIRS)
00096 return (-1);
00097
00098 if (idx < 0 || idx >= dp->nfiles)
00099 return (-1);
00100
00101 n = dp->files[idx].size;
00102 if (n > bufsize)
00103 n = bufsize;
00104
00105 fseek (musicf, dp->dir.offset + dp->files[idx].offset, SEEK_SET);
00106 n = fread (buf, 1, n, musicf);
00107 return (n);
00108 }
00109
00110 void
00111 do_display_cat (void)
00112 {
00113 int i, j;
00114 struct music_dir *dp;
00115 struct TM *fp;
00116 long base, offset;
00117
00118 base = 0;
00119 for (i = 0, dp = dirs; i < MDIRS; i++, dp++) {
00120 for (j = 0, fp = dp->files; j < dp->nfiles; j++, fp++) {
00121 offset = dp->dir.offset + fp->offset;
00122
00123 printf ("0x%08lx %8ld %.6s/%.6s\n",
00124 offset, fp->size,
00125 dp->dir.ID, fp->ID);
00126 }
00127 }
00128 }
00129
00130 int display_cat;
00131
00132 void
00133 usage (void)
00134 {
00135 fprintf (stderr, "usage: mtest\n");
00136 exit (1);
00137 }
00138
00139 int
00140 main (int argc, char **argv)
00141 {
00142 int c;
00143 char *type = NULL;
00144 int idx = 0;
00145 int n;
00146 char buf[1000 * 1000];
00147
00148 while ((c = getopt (argc, argv, "c")) != EOF) {
00149 switch (c) {
00150 case 'c':
00151 display_cat = 1;
00152 break;
00153 default:
00154 usage ();
00155 }
00156 }
00157
00158 if (optind < argc)
00159 type = argv[optind++];
00160
00161 if (optind < argc)
00162 idx = atoi (argv[optind++]);
00163
00164 if (optind != argc)
00165 usage ();
00166
00167 open_music_cat ("/l/baris/gamedat/music.cat");
00168
00169 if (display_cat) {
00170 do_display_cat ();
00171 exit (0);
00172 }
00173
00174 if (type) {
00175 n = get_music (type, idx, buf, sizeof buf);
00176 dump (buf, n);
00177 }
00178
00179 return (0);
00180 }
00181
00182