Mercurial > repos > blastem
comparison vgmsplit.c @ 850:215b5dabbc20
Make vgmsplit smarter about how it handles delays. Force GD3 offset to zero since it is not being copied currently
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 01 Nov 2015 20:40:30 -0800 |
parents | 7068a9db6dd0 |
children |
comparison
equal
deleted
inserted
replaced
849:1416c4261d5b | 850:215b5dabbc20 |
---|---|
13 #define OUT_CHANNELS 10 | 13 #define OUT_CHANNELS 10 |
14 #define DAC_CHANNEL 5 | 14 #define DAC_CHANNEL 5 |
15 #define PSG_BASE 6 | 15 #define PSG_BASE 6 |
16 #define SAMPLE_THRESHOLD 100 | 16 #define SAMPLE_THRESHOLD 100 |
17 | 17 |
18 uint32_t total_delay; | |
19 void accum_wait(uint32_t *delays, uint32_t samples) | |
20 { | |
21 total_delay += samples; | |
22 for (int i = 0; i < OUT_CHANNELS; i++) | |
23 { | |
24 delays[i] += samples; | |
25 } | |
26 } | |
27 | |
28 void write_wait(uint8_t **out_buffer, uint32_t *delay) | |
29 { | |
30 while (*delay >= 65535) | |
31 { | |
32 *((*out_buffer)++) = CMD_WAIT; | |
33 *((*out_buffer)++) = 0xFF; | |
34 *((*out_buffer)++) = 0xFF; | |
35 *delay -= 65535; | |
36 } | |
37 if (*delay) { | |
38 if (*delay == 735) { | |
39 *((*out_buffer)++) = CMD_WAIT_60; | |
40 } else if (*delay > 735 && *delay <= 751) { | |
41 *((*out_buffer)++) = CMD_WAIT_60; | |
42 *((*out_buffer)++) = CMD_WAIT_SHORT + *delay - 736; | |
43 } else if (*delay == 882) { | |
44 *((*out_buffer)++) = CMD_WAIT_50; | |
45 } else if (*delay > 882 && *delay <= 898) { | |
46 *((*out_buffer)++) = CMD_WAIT_50; | |
47 *((*out_buffer)++) = CMD_WAIT_SHORT + *delay - 882; | |
48 } else if (*delay <= 16) { | |
49 *((*out_buffer)++) = CMD_WAIT_SHORT + *delay - 1; | |
50 } else { | |
51 *((*out_buffer)++) = CMD_WAIT; | |
52 *((*out_buffer)++) = *delay; | |
53 *((*out_buffer)++) = *delay >> 8; | |
54 } | |
55 *delay = 0; | |
56 } | |
57 } | |
58 | |
18 int main(int argc, char ** argv) | 59 int main(int argc, char ** argv) |
19 { | 60 { |
20 data_block *blocks = NULL; | 61 data_block *blocks = NULL; |
21 data_block *seek_block = NULL; | 62 data_block *seek_block = NULL; |
22 uint32_t seek_offset; | 63 uint32_t seek_offset; |
39 data_size = fread(data, 1, data_size, f); | 80 data_size = fread(data, 1, data_size, f); |
40 fclose(f); | 81 fclose(f); |
41 uint8_t *buffers[OUT_CHANNELS]; | 82 uint8_t *buffers[OUT_CHANNELS]; |
42 uint8_t *out_pos[OUT_CHANNELS]; | 83 uint8_t *out_pos[OUT_CHANNELS]; |
43 uint8_t has_real_data[OUT_CHANNELS]; | 84 uint8_t has_real_data[OUT_CHANNELS]; |
85 uint32_t delay[OUT_CHANNELS]; | |
44 | 86 |
45 buffers[0] = malloc(data_size * OUT_CHANNELS); | 87 buffers[0] = malloc(data_size * OUT_CHANNELS); |
46 out_pos[0] = buffers[0]; | 88 out_pos[0] = buffers[0]; |
47 has_real_data[0] = 0; | 89 has_real_data[0] = 0; |
90 delay[0] = 0; | |
48 for (int i = 1; i < OUT_CHANNELS; i++) | 91 for (int i = 1; i < OUT_CHANNELS; i++) |
49 { | 92 { |
50 buffers[i] = buffers[i-1] + data_size; | 93 buffers[i] = buffers[i-1] + data_size; |
51 out_pos[i] = buffers[i]; | 94 out_pos[i] = buffers[i]; |
52 has_real_data[i] = 0; | 95 has_real_data[i] = 0; |
96 delay[i] = 0; | |
53 } | 97 } |
54 | 98 |
55 uint8_t * end = data + data_size; | 99 uint8_t * end = data + data_size; |
56 uint8_t * cur = data; | 100 uint8_t * cur = data; |
57 uint32_t current_cycle = 0; | 101 uint32_t current_cycle = 0; |
74 psg_latch = param; | 118 psg_latch = param; |
75 channel = param >> 5 & 3; | 119 channel = param >> 5 & 3; |
76 } else { | 120 } else { |
77 channel = psg_latch >> 5 & 3; | 121 channel = psg_latch >> 5 & 3; |
78 } | 122 } |
123 write_wait(out_pos + PSG_BASE+channel, delay + PSG_BASE+channel); | |
79 *(out_pos[PSG_BASE+channel]++) = cmd; | 124 *(out_pos[PSG_BASE+channel]++) = cmd; |
80 *(out_pos[PSG_BASE+channel]++) = param; | 125 *(out_pos[PSG_BASE+channel]++) = param; |
81 has_real_data[PSG_BASE+channel] = 1; | 126 has_real_data[PSG_BASE+channel] = 1; |
82 break; | 127 break; |
83 case CMD_YM2612_0: | 128 case CMD_YM2612_0: |
84 reg = *(cur++); | 129 reg = *(cur++); |
85 param = *(cur++); | 130 param = *(cur++); |
86 if (reg < REG_KEY_ONOFF) { | 131 if (reg < REG_KEY_ONOFF) { |
87 for (int i = 0; i < 6; i++) | 132 for (int i = 0; i < 6; i++) |
88 { | 133 { |
134 write_wait(out_pos + i, delay + i); | |
89 *(out_pos[i]++) = cmd; | 135 *(out_pos[i]++) = cmd; |
90 *(out_pos[i]++) = reg; | 136 *(out_pos[i]++) = reg; |
91 *(out_pos[i]++) = param; | 137 *(out_pos[i]++) = param; |
92 } | 138 } |
93 break; | 139 break; |
123 } else { | 169 } else { |
124 fprintf(stderr, "WARNING: Skipping nrecognized write to register %X on part %d\n", reg, (cmd == CMD_YM2612_0 ? 1 : 2)); | 170 fprintf(stderr, "WARNING: Skipping nrecognized write to register %X on part %d\n", reg, (cmd == CMD_YM2612_0 ? 1 : 2)); |
125 } | 171 } |
126 } | 172 } |
127 if (channel < PSG_BASE) { | 173 if (channel < PSG_BASE) { |
174 write_wait(out_pos + channel, delay + channel); | |
128 *(out_pos[channel]++) = cmd; | 175 *(out_pos[channel]++) = cmd; |
129 *(out_pos[channel]++) = reg; | 176 *(out_pos[channel]++) = reg; |
130 *(out_pos[channel]++) = param; | 177 *(out_pos[channel]++) = param; |
131 } | 178 } |
132 break; | 179 break; |
133 case CMD_WAIT: { | 180 case CMD_WAIT: { |
134 reg = *(cur++); | 181 uint32_t wait_time = *(cur++); |
135 param = *(cur++); | 182 wait_time |= *(cur++) << 8; |
136 for (int i = 0; i < OUT_CHANNELS; i++) | 183 accum_wait(delay, wait_time); |
137 { | |
138 *(out_pos[i]++) = cmd; | |
139 *(out_pos[i]++) = reg; | |
140 *(out_pos[i]++) = param; | |
141 } | |
142 break; | 184 break; |
143 } | 185 } |
144 case CMD_WAIT_60: | 186 case CMD_WAIT_60: |
187 accum_wait(delay, 735); | |
188 break; | |
145 case CMD_WAIT_50: | 189 case CMD_WAIT_50: |
190 accum_wait(delay, 882); | |
191 break; | |
146 case CMD_END: | 192 case CMD_END: |
147 for (int i = 0; i < OUT_CHANNELS; i++) | 193 for (int i = 0; i < OUT_CHANNELS; i++) |
148 { | 194 { |
195 write_wait(out_pos + i, delay + i); | |
149 *(out_pos[i]++) = cmd; | 196 *(out_pos[i]++) = cmd; |
150 } | 197 } |
151 cur = end; | 198 cur = end; |
152 break; | 199 break; |
153 case CMD_DATA: { | 200 case CMD_DATA: { |
161 if (cur + data_size > end) { | 208 if (cur + data_size > end) { |
162 data_size = end - cur; | 209 data_size = end - cur; |
163 } | 210 } |
164 cur += data_size; | 211 cur += data_size; |
165 if (data_type == DATA_YM2612_PCM) { | 212 if (data_type == DATA_YM2612_PCM) { |
213 write_wait(out_pos + DAC_CHANNEL, delay + DAC_CHANNEL); | |
166 memcpy(out_pos[DAC_CHANNEL], start, cur-start); | 214 memcpy(out_pos[DAC_CHANNEL], start, cur-start); |
167 out_pos[DAC_CHANNEL] += cur-start; | 215 out_pos[DAC_CHANNEL] += cur-start; |
168 } else { | 216 } else { |
169 fprintf(stderr, "WARNING: Skipping data block with unrecognized type %X\n", data_type); | 217 fprintf(stderr, "WARNING: Skipping data block with unrecognized type %X\n", data_type); |
170 } | 218 } |
171 break; | 219 break; |
172 } | 220 } |
173 case CMD_DATA_SEEK: { | 221 case CMD_DATA_SEEK: { |
222 write_wait(out_pos + DAC_CHANNEL, delay + DAC_CHANNEL); | |
174 memcpy(out_pos[DAC_CHANNEL], cur-1, 5); | 223 memcpy(out_pos[DAC_CHANNEL], cur-1, 5); |
175 out_pos[DAC_CHANNEL] += 5; | 224 out_pos[DAC_CHANNEL] += 5; |
176 cur += 4; | 225 cur += 4; |
177 break; | 226 break; |
178 } | 227 } |
179 | 228 |
180 default: | 229 default: |
181 if (cmd >= CMD_WAIT_SHORT && cmd < (CMD_WAIT_SHORT + 0x10)) { | 230 if (cmd >= CMD_WAIT_SHORT && cmd < (CMD_WAIT_SHORT + 0x10)) { |
231 accum_wait(delay, (cmd & 0xF) + 1); | |
232 } else if (cmd >= CMD_YM2612_DAC && cmd < CMD_DAC_STREAM_SETUP) { | |
233 write_wait(out_pos + DAC_CHANNEL, delay + DAC_CHANNEL); | |
234 *(out_pos[DAC_CHANNEL]++) = cmd; | |
182 for (int i = 0; i < OUT_CHANNELS; i++) | 235 for (int i = 0; i < OUT_CHANNELS; i++) |
183 { | 236 { |
184 *(out_pos[i]++) = cmd; | 237 if (i != DAC_CHANNEL) |
185 } | 238 { |
186 } else if (cmd >= CMD_YM2612_DAC && cmd < CMD_DAC_STREAM_SETUP) { | 239 delay[i] += cmd & 0xF; |
187 *(out_pos[DAC_CHANNEL]++) = cmd; | 240 } |
241 } | |
188 sample_count++; | 242 sample_count++; |
189 } else { | 243 } else { |
190 fprintf(stderr, "unimplemented command: %X at offset %X, last valid command was %X\n", cmd, (unsigned int)(cur - data - 1), last_cmd); | 244 fprintf(stderr, "unimplemented command: %X at offset %X, last valid command was %X\n", cmd, (unsigned int)(cur - data - 1), last_cmd); |
191 exit(1); | 245 exit(1); |
192 } | 246 } |
206 fprintf(stderr, "Failed to open %s for writing\n", fname); | 260 fprintf(stderr, "Failed to open %s for writing\n", fname); |
207 exit(1); | 261 exit(1); |
208 } | 262 } |
209 data_size = out_pos[i] - buffers[i]; | 263 data_size = out_pos[i] - buffers[i]; |
210 header.eof_offset = (header.data_offset + 0x34) + data_size - 4; | 264 header.eof_offset = (header.data_offset + 0x34) + data_size - 4; |
265 header.gd3_offset = 0; | |
211 fwrite(&header, 1, sizeof(header), f); | 266 fwrite(&header, 1, sizeof(header), f); |
212 fseek(f, header.data_offset + 0x34, SEEK_SET); | 267 fseek(f, header.data_offset + 0x34, SEEK_SET); |
213 fwrite(buffers[i], 1, data_size, f); | 268 fwrite(buffers[i], 1, data_size, f); |
214 fclose(f); | 269 fclose(f); |
215 } | 270 } |
216 } | 271 } |
272 printf("total_delay: %d\n", total_delay); | |
217 return 0; | 273 return 0; |
218 } | 274 } |