9411ba24 |
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <zlib.h> |
5 | |
6 | #define CD_FRAMESIZE_RAW 2352 |
7 | |
8 | struct ztab_entry { |
9 | unsigned int offset; |
10 | unsigned short size; |
11 | } __attribute__((packed)); |
12 | |
13 | int main(int argc, char *argv[]) |
14 | { |
15 | unsigned char outbuf[CD_FRAMESIZE_RAW * 2]; |
16 | unsigned char inbuf[CD_FRAMESIZE_RAW]; |
17 | struct ztab_entry *ztable; |
18 | char *out_basename, *out_fname, *out_tfname; |
19 | FILE *fin, *fout; |
20 | long in_bytes, out_bytes; |
21 | long s, total_sectors; |
22 | int ret, len; |
23 | |
24 | if (argc < 2) { |
25 | fprintf(stderr, "usage:\n%s <cd_img> [out_basename]\n", argv[0]); |
26 | return 1; |
27 | } |
28 | |
29 | fin = fopen(argv[1], "rb"); |
30 | if (fin == NULL) { |
31 | fprintf(stderr, "fopen %s: ", argv[1]); |
32 | perror(NULL); |
33 | return 1; |
34 | } |
35 | |
36 | if (argv[2] != NULL) |
37 | out_basename = argv[2]; |
38 | else |
39 | out_basename = argv[1]; |
40 | |
41 | len = strlen(out_basename) + 3; |
42 | out_fname = malloc(len); |
43 | if (out_fname == NULL) { |
44 | fprintf(stderr, "OOM\n"); |
45 | return 1; |
46 | } |
47 | snprintf(out_fname, len, "%s.Z", out_basename); |
48 | |
49 | fout = fopen(out_fname, "wb"); |
50 | if (fout == NULL) { |
51 | fprintf(stderr, "fopen %s: ", out_fname); |
52 | perror(NULL); |
53 | return 1; |
54 | } |
55 | |
56 | if (fseek(fin, 0, SEEK_END) != 0) { |
57 | fprintf(stderr, "fseek failed: "); |
58 | perror(NULL); |
59 | return 1; |
60 | } |
61 | |
62 | in_bytes = ftell(fin); |
63 | if (in_bytes % CD_FRAMESIZE_RAW) { |
64 | fprintf(stderr, "warning: input size %ld is not " |
65 | "multiple of sector size\n", in_bytes); |
66 | } |
67 | total_sectors = in_bytes / CD_FRAMESIZE_RAW; |
68 | fseek(fin, 0, SEEK_SET); |
69 | |
70 | ztable = calloc(total_sectors, sizeof(ztable[0])); |
71 | if (ztable == NULL) { |
72 | fprintf(stderr, "OOM\n"); |
73 | return 1; |
74 | } |
75 | |
76 | out_bytes = 0; |
77 | for (s = 0; s < total_sectors; s++) { |
78 | uLongf dest_len = sizeof(outbuf); |
79 | |
80 | ret = fread(inbuf, 1, sizeof(inbuf), fin); |
81 | if (ret != sizeof(inbuf)) { |
82 | printf("\n"); |
83 | fprintf(stderr, "fread returned %d\n", ret); |
84 | return 1; |
85 | } |
86 | |
87 | ret = compress2(outbuf, &dest_len, inbuf, sizeof(inbuf), 9); |
88 | if (ret != Z_OK) { |
89 | printf("\n"); |
90 | fprintf(stderr, "compress2 failed: %d\n", ret); |
91 | return 1; |
92 | } |
93 | |
94 | ret = fwrite(outbuf, 1, dest_len, fout); |
95 | if (ret != dest_len) { |
96 | printf("\n"); |
97 | fprintf(stderr, "fwrite returned %d\n", ret); |
98 | return 1; |
99 | } |
100 | |
101 | ztable[s].offset = out_bytes; |
102 | ztable[s].size = dest_len; |
103 | out_bytes += dest_len; |
104 | |
105 | // print progress |
106 | if ((s & 0x1ff) == 0) { |
107 | printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); |
108 | printf("%3ld%% %ld/%ld", s * 100 / total_sectors, s, total_sectors); |
109 | fflush(stdout); |
110 | } |
111 | } |
112 | |
113 | fclose(fin); |
114 | fclose(fout); |
115 | |
116 | // write .table |
117 | len = strlen(out_fname) + 7; |
118 | out_tfname = malloc(len); |
119 | if (out_tfname == NULL) { |
120 | printf("\n"); |
121 | fprintf(stderr, "OOM\n"); |
122 | return 1; |
123 | } |
124 | snprintf(out_tfname, len, "%s.table", out_fname); |
125 | |
126 | fout = fopen(out_tfname, "wb"); |
127 | if (fout == NULL) { |
128 | fprintf(stderr, "fopen %s: ", out_tfname); |
129 | perror(NULL); |
130 | return 1; |
131 | } |
132 | |
133 | ret = fwrite(ztable, sizeof(ztable[0]), total_sectors, fout); |
134 | if (ret != total_sectors) { |
135 | printf("\n"); |
136 | fprintf(stderr, "fwrite returned %d\n", ret); |
137 | return 1; |
138 | } |
139 | fclose(fout); |
140 | |
141 | printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); |
142 | printf("%3ld%% %ld/%ld\n", s * 100 / total_sectors, s, total_sectors); |
143 | printf("%ld bytes from %ld (%.1f%%)\n", out_bytes, in_bytes, |
144 | (double)out_bytes * 100.0 / in_bytes); |
145 | |
146 | return 0; |
147 | } |