diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2020-09-26 17:19:07 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-10-09 11:39:25 -0400 |
commit | 4231c2c83f2b5331e3e38b10a308ee3752315f9c (patch) | |
tree | 1e14867e9c9f0d7b778e7c4c18103a7cbd491794 /lib/rbcodec/metadata | |
parent | 278522f8118bd2cfce065ec95f0a93ca53e3ca44 (diff) | |
download | rockbox-4231c2c83f2b5331e3e38b10a308ee3752315f9c.tar.gz rockbox-4231c2c83f2b5331e3e38b10a308ee3752315f9c.zip |
codecs: Add support for the 'VTX' ZX Spectrum chiptunes format.
This codec requires floating point.
Original author: Peter Sovietov
Ported to Rockbox: Roman Skylarov
Further integration and bugfixes: Solomon Peachy
Change-Id: I781ecd3592dfcdbbc694063334350342534f1d6c
Diffstat (limited to 'lib/rbcodec/metadata')
-rw-r--r-- | lib/rbcodec/metadata/metadata.c | 40 | ||||
-rw-r--r-- | lib/rbcodec/metadata/metadata.h | 13 | ||||
-rw-r--r-- | lib/rbcodec/metadata/metadata_parsers.h | 3 | ||||
-rw-r--r-- | lib/rbcodec/metadata/vtx.c | 150 |
4 files changed, 184 insertions, 22 deletions
diff --git a/lib/rbcodec/metadata/metadata.c b/lib/rbcodec/metadata/metadata.c index 9c41347975..aec72db97f 100644 --- a/lib/rbcodec/metadata/metadata.c +++ b/lib/rbcodec/metadata/metadata.c | |||
@@ -43,7 +43,7 @@ static bool get_shn_metadata(int fd, struct mp3entry *id3) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | static bool get_other_asap_metadata(int fd, struct mp3entry *id3) | 45 | static bool get_other_asap_metadata(int fd, struct mp3entry *id3) |
46 | { | 46 | { |
47 | id3->bitrate = 706; | 47 | id3->bitrate = 706; |
48 | id3->frequency = 44100; | 48 | id3->frequency = 44100; |
49 | id3->vbr = false; | 49 | id3->vbr = false; |
@@ -85,7 +85,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
85 | /* Musepack SV7 */ | 85 | /* Musepack SV7 */ |
86 | [AFMT_MPC_SV7] = | 86 | [AFMT_MPC_SV7] = |
87 | AFMT_ENTRY("MPCv7", "mpc", NULL, get_musepack_metadata,"mpc\0"), | 87 | AFMT_ENTRY("MPCv7", "mpc", NULL, get_musepack_metadata,"mpc\0"), |
88 | /* A/52 (aka AC3) audio */ | 88 | /* A/52 (aka AC3) audio */ |
89 | [AFMT_A52] = | 89 | [AFMT_A52] = |
90 | AFMT_ENTRY("AC3", "a52", NULL, get_a52_metadata, "a52\0ac3\0"), | 90 | AFMT_ENTRY("AC3", "a52", NULL, get_a52_metadata, "a52\0ac3\0"), |
91 | /* WavPack */ | 91 | /* WavPack */ |
@@ -109,7 +109,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
109 | /* NESM (NES Sound Format) */ | 109 | /* NESM (NES Sound Format) */ |
110 | [AFMT_NSF] = | 110 | [AFMT_NSF] = |
111 | AFMT_ENTRY("NSF", "nsf", NULL, get_nsf_metadata, "nsf\0nsfe\0"), | 111 | AFMT_ENTRY("NSF", "nsf", NULL, get_nsf_metadata, "nsf\0nsfe\0"), |
112 | /* Speex File Format */ | 112 | /* Speex File Format */ |
113 | [AFMT_SPEEX] = | 113 | [AFMT_SPEEX] = |
114 | AFMT_ENTRY("Speex", "speex",NULL, get_ogg_metadata, "spx\0"), | 114 | AFMT_ENTRY("Speex", "speex",NULL, get_ogg_metadata, "spx\0"), |
115 | /* SPC700 Save State */ | 115 | /* SPC700 Save State */ |
@@ -162,12 +162,12 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
162 | AFMT_ENTRY("DLT", "asap", NULL, get_other_asap_metadata,"dlt\0"), | 162 | AFMT_ENTRY("DLT", "asap", NULL, get_other_asap_metadata,"dlt\0"), |
163 | /* Atari MPT File */ | 163 | /* Atari MPT File */ |
164 | [AFMT_MPT] = | 164 | [AFMT_MPT] = |
165 | AFMT_ENTRY("MPT", "asap", NULL, get_other_asap_metadata,"mpt\0"), | 165 | AFMT_ENTRY("MPT", "asap", NULL, get_other_asap_metadata,"mpt\0"), |
166 | /* Atari MPD File */ | 166 | /* Atari MPD File */ |
167 | [AFMT_MPD] = | 167 | [AFMT_MPD] = |
168 | AFMT_ENTRY("MPD", "asap", NULL, get_other_asap_metadata,"mpd\0"), | 168 | AFMT_ENTRY("MPD", "asap", NULL, get_other_asap_metadata,"mpd\0"), |
169 | /* Atari RMT File */ | 169 | /* Atari RMT File */ |
170 | [AFMT_RMT] = | 170 | [AFMT_RMT] = |
171 | AFMT_ENTRY("RMT", "asap", NULL, get_other_asap_metadata,"rmt\0"), | 171 | AFMT_ENTRY("RMT", "asap", NULL, get_other_asap_metadata,"rmt\0"), |
172 | /* Atari TMC File */ | 172 | /* Atari TMC File */ |
173 | [AFMT_TMC] = | 173 | [AFMT_TMC] = |
@@ -177,10 +177,10 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
177 | AFMT_ENTRY("TM8", "asap", NULL, get_other_asap_metadata,"tm8\0"), | 177 | AFMT_ENTRY("TM8", "asap", NULL, get_other_asap_metadata,"tm8\0"), |
178 | /* Atari TM2 File */ | 178 | /* Atari TM2 File */ |
179 | [AFMT_TM2] = | 179 | [AFMT_TM2] = |
180 | AFMT_ENTRY("TM2", "asap", NULL, get_other_asap_metadata,"tm2\0"), | 180 | AFMT_ENTRY("TM2", "asap", NULL, get_other_asap_metadata,"tm2\0"), |
181 | /* Atrac3 in Sony OMA Container */ | 181 | /* Atrac3 in Sony OMA Container */ |
182 | [AFMT_OMA_ATRAC3] = | 182 | [AFMT_OMA_ATRAC3] = |
183 | AFMT_ENTRY("ATRAC3","atrac3_oma",NULL, get_oma_metadata, "oma\0aa3\0"), | 183 | AFMT_ENTRY("ATRAC3","atrac3_oma",NULL, get_oma_metadata, "oma\0aa3\0"), |
184 | /* SMAF (Synthetic music Mobile Application Format) */ | 184 | /* SMAF (Synthetic music Mobile Application Format) */ |
185 | [AFMT_SMAF] = | 185 | [AFMT_SMAF] = |
186 | AFMT_ENTRY("SMAF", "smaf", NULL, get_smaf_metadata, "mmf\0"), | 186 | AFMT_ENTRY("SMAF", "smaf", NULL, get_smaf_metadata, "mmf\0"), |
@@ -194,7 +194,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
194 | [AFMT_WAVE64] = | 194 | [AFMT_WAVE64] = |
195 | AFMT_ENTRY("WAVE64","wav64",NULL, get_wave64_metadata,"w64\0"), | 195 | AFMT_ENTRY("WAVE64","wav64",NULL, get_wave64_metadata,"w64\0"), |
196 | /* True Audio */ | 196 | /* True Audio */ |
197 | [AFMT_TTA] = | 197 | [AFMT_TTA] = |
198 | AFMT_ENTRY("TTA", "tta", NULL, get_tta_metadata, "tta\0"), | 198 | AFMT_ENTRY("TTA", "tta", NULL, get_tta_metadata, "tta\0"), |
199 | /* WMA Voice in ASF */ | 199 | /* WMA Voice in ASF */ |
200 | [AFMT_WMAVOICE] = | 200 | [AFMT_WMAVOICE] = |
@@ -206,8 +206,13 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
206 | [AFMT_MP4_AAC_HE] = | 206 | [AFMT_MP4_AAC_HE] = |
207 | AFMT_ENTRY("AAC-HE","aac", NULL, get_mp4_metadata, "mp4\0"), | 207 | AFMT_ENTRY("AAC-HE","aac", NULL, get_mp4_metadata, "mp4\0"), |
208 | /* AY (ZX Spectrum, Amstrad CPC Sound Format) */ | 208 | /* AY (ZX Spectrum, Amstrad CPC Sound Format) */ |
209 | [AFMT_AY] = | 209 | [AFMT_AY] = |
210 | AFMT_ENTRY("AY", "ay", NULL, get_ay_metadata, "ay\0"), | 210 | AFMT_ENTRY("AY", "ay", NULL, get_ay_metadata, "ay\0"), |
211 | /* AY (ZX Spectrum Sound Format) */ | ||
212 | #ifdef HAVE_FPU | ||
213 | [AFMT_VTX] = | ||
214 | AFMT_ENTRY("VTX", "vtx", NULL, get_vtx_metadata, "vtx\0"), | ||
215 | #endif | ||
211 | /* GBS (Game Boy Sound Format) */ | 216 | /* GBS (Game Boy Sound Format) */ |
212 | [AFMT_GBS] = | 217 | [AFMT_GBS] = |
213 | AFMT_ENTRY("GBS", "gbs", NULL, get_gbs_metadata, "gbs\0"), | 218 | AFMT_ENTRY("GBS", "gbs", NULL, get_gbs_metadata, "gbs\0"), |
@@ -313,6 +318,9 @@ bool rbcodec_format_is_atomic(int afmt) | |||
313 | case AFMT_MOD: | 318 | case AFMT_MOD: |
314 | case AFMT_SAP: | 319 | case AFMT_SAP: |
315 | case AFMT_AY: | 320 | case AFMT_AY: |
321 | #ifdef HAVE_FPU | ||
322 | case AFMT_VTX: | ||
323 | #endif | ||
316 | case AFMT_GBS: | 324 | case AFMT_GBS: |
317 | case AFMT_HES: | 325 | case AFMT_HES: |
318 | case AFMT_SGC: | 326 | case AFMT_SGC: |
@@ -352,17 +360,17 @@ unsigned int probe_file_format(const char *filename) | |||
352 | { | 360 | { |
353 | char *suffix; | 361 | char *suffix; |
354 | unsigned int i; | 362 | unsigned int i; |
355 | 363 | ||
356 | suffix = strrchr(filename, '.'); | 364 | suffix = strrchr(filename, '.'); |
357 | 365 | ||
358 | if (suffix == NULL) | 366 | if (suffix == NULL) |
359 | { | 367 | { |
360 | return AFMT_UNKNOWN; | 368 | return AFMT_UNKNOWN; |
361 | } | 369 | } |
362 | 370 | ||
363 | /* skip '.' */ | 371 | /* skip '.' */ |
364 | suffix++; | 372 | suffix++; |
365 | 373 | ||
366 | for (i = 1; i < AFMT_NUM_CODECS; i++) | 374 | for (i = 1; i < AFMT_NUM_CODECS; i++) |
367 | { | 375 | { |
368 | /* search extension list for type */ | 376 | /* search extension list for type */ |
@@ -379,7 +387,7 @@ unsigned int probe_file_format(const char *filename) | |||
379 | } | 387 | } |
380 | while (*ext != '\0'); | 388 | while (*ext != '\0'); |
381 | } | 389 | } |
382 | 390 | ||
383 | return AFMT_UNKNOWN; | 391 | return AFMT_UNKNOWN; |
384 | } | 392 | } |
385 | 393 | ||
@@ -418,7 +426,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) | |||
418 | close(logfd); | 426 | close(logfd); |
419 | } | 427 | } |
420 | } | 428 | } |
421 | 429 | ||
422 | /* Clear the mp3entry to avoid having bogus pointers appear */ | 430 | /* Clear the mp3entry to avoid having bogus pointers appear */ |
423 | wipe_mp3entry(id3); | 431 | wipe_mp3entry(id3); |
424 | 432 | ||
@@ -454,7 +462,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) | |||
454 | void strip_tags(int handle_id) | 462 | void strip_tags(int handle_id) |
455 | { | 463 | { |
456 | static const unsigned char tag[] = "TAG"; | 464 | static const unsigned char tag[] = "TAG"; |
457 | static const unsigned char apetag[] = "APETAGEX"; | 465 | static const unsigned char apetag[] = "APETAGEX"; |
458 | size_t len, version; | 466 | size_t len, version; |
459 | void *tail; | 467 | void *tail; |
460 | 468 | ||
@@ -502,7 +510,7 @@ void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig) | |||
502 | MOVE_ENTRY(entry->artist) | 510 | MOVE_ENTRY(entry->artist) |
503 | MOVE_ENTRY(entry->album) | 511 | MOVE_ENTRY(entry->album) |
504 | 512 | ||
505 | if (entry->genre_string > (char*)orig && | 513 | if (entry->genre_string > (char*)orig && |
506 | entry->genre_string < (char*)orig + sizeof(struct mp3entry)) | 514 | entry->genre_string < (char*)orig + sizeof(struct mp3entry)) |
507 | /* Don't adjust that if it points to an entry of the "genres" array */ | 515 | /* Don't adjust that if it points to an entry of the "genres" array */ |
508 | entry->genre_string += offset; | 516 | entry->genre_string += offset; |
diff --git a/lib/rbcodec/metadata/metadata.h b/lib/rbcodec/metadata/metadata.h index 5c78eae9d4..fc9c1d062c 100644 --- a/lib/rbcodec/metadata/metadata.h +++ b/lib/rbcodec/metadata/metadata.h | |||
@@ -83,6 +83,9 @@ enum | |||
83 | AFMT_MPC_SV8, /* Musepack SV8 */ | 83 | AFMT_MPC_SV8, /* Musepack SV8 */ |
84 | AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */ | 84 | AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */ |
85 | AFMT_AY, /* AY (ZX Spectrum, Amstrad CPC Sound Format) */ | 85 | AFMT_AY, /* AY (ZX Spectrum, Amstrad CPC Sound Format) */ |
86 | #ifdef HAVE_FPU | ||
87 | AFMT_VTX, /* VTX (ZX Spectrum Sound Format) */ | ||
88 | #endif | ||
86 | AFMT_GBS, /* GBS (Game Boy Sound Format) */ | 89 | AFMT_GBS, /* GBS (Game Boy Sound Format) */ |
87 | AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */ | 90 | AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */ |
88 | AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */ | 91 | AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */ |
@@ -140,7 +143,7 @@ enum rec_format_indexes | |||
140 | REC_FORMAT_CFG_NUM_BITS = 2 | 143 | REC_FORMAT_CFG_NUM_BITS = 2 |
141 | }; | 144 | }; |
142 | 145 | ||
143 | #define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3" | 146 | #define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3" |
144 | 147 | ||
145 | /* get REC_FORMAT_* corresponding AFMT_* */ | 148 | /* get REC_FORMAT_* corresponding AFMT_* */ |
146 | extern const int rec_format_afmt[REC_NUM_FORMATS]; | 149 | extern const int rec_format_afmt[REC_NUM_FORMATS]; |
@@ -232,7 +235,7 @@ struct mp3entry { | |||
232 | char* comment; | 235 | char* comment; |
233 | char* albumartist; | 236 | char* albumartist; |
234 | char* grouping; | 237 | char* grouping; |
235 | int discnum; | 238 | int discnum; |
236 | int tracknum; | 239 | int tracknum; |
237 | int layer; | 240 | int layer; |
238 | int year; | 241 | int year; |
@@ -283,7 +286,7 @@ struct mp3entry { | |||
283 | 286 | ||
284 | #ifdef HAVE_TAGCACHE | 287 | #ifdef HAVE_TAGCACHE |
285 | unsigned char autoresumable; /* caches result of autoresumable() */ | 288 | unsigned char autoresumable; /* caches result of autoresumable() */ |
286 | 289 | ||
287 | /* runtime database fields */ | 290 | /* runtime database fields */ |
288 | long tagcache_idx; /* 0=invalid, otherwise idx+1 */ | 291 | long tagcache_idx; /* 0=invalid, otherwise idx+1 */ |
289 | int rating; | 292 | int rating; |
@@ -292,7 +295,7 @@ struct mp3entry { | |||
292 | long lastplayed; | 295 | long lastplayed; |
293 | long playtime; | 296 | long playtime; |
294 | #endif | 297 | #endif |
295 | 298 | ||
296 | /* replaygain support */ | 299 | /* replaygain support */ |
297 | long track_level; /* holds the level in dB * (1<<FP_BITS) */ | 300 | long track_level; /* holds the level in dB * (1<<FP_BITS) */ |
298 | long album_level; | 301 | long album_level; |
@@ -329,5 +332,3 @@ bool rbcodec_format_is_atomic(int afmt); | |||
329 | bool format_buffers_with_offset(int afmt); | 332 | bool format_buffers_with_offset(int afmt); |
330 | 333 | ||
331 | #endif | 334 | #endif |
332 | |||
333 | |||
diff --git a/lib/rbcodec/metadata/metadata_parsers.h b/lib/rbcodec/metadata/metadata_parsers.h index cc7d8a102e..6a4da51b63 100644 --- a/lib/rbcodec/metadata/metadata_parsers.h +++ b/lib/rbcodec/metadata/metadata_parsers.h | |||
@@ -49,6 +49,9 @@ bool get_vox_metadata(int fd, struct mp3entry* id3); | |||
49 | bool get_wave64_metadata(int fd, struct mp3entry* id3); | 49 | bool get_wave64_metadata(int fd, struct mp3entry* id3); |
50 | bool get_tta_metadata(int fd, struct mp3entry* id3); | 50 | bool get_tta_metadata(int fd, struct mp3entry* id3); |
51 | bool get_ay_metadata(int fd, struct mp3entry* id3); | 51 | bool get_ay_metadata(int fd, struct mp3entry* id3); |
52 | #ifdef HAVE_FPU | ||
53 | bool get_vtx_metadata(int fd, struct mp3entry* id3); | ||
54 | #endif | ||
52 | bool get_gbs_metadata(int fd, struct mp3entry* id3); | 55 | bool get_gbs_metadata(int fd, struct mp3entry* id3); |
53 | bool get_hes_metadata(int fd, struct mp3entry* id3); | 56 | bool get_hes_metadata(int fd, struct mp3entry* id3); |
54 | bool get_sgc_metadata(int fd, struct mp3entry* id3); | 57 | bool get_sgc_metadata(int fd, struct mp3entry* id3); |
diff --git a/lib/rbcodec/metadata/vtx.c b/lib/rbcodec/metadata/vtx.c new file mode 100644 index 0000000000..eb06528b29 --- /dev/null +++ b/lib/rbcodec/metadata/vtx.c | |||
@@ -0,0 +1,150 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <ctype.h> | ||
5 | #include <inttypes.h> | ||
6 | #include "platform.h" | ||
7 | |||
8 | #include "metadata.h" | ||
9 | #include "metadata_common.h" | ||
10 | #include "metadata_parsers.h" | ||
11 | #include "rbunicode.h" | ||
12 | #include "string-extra.h" | ||
13 | |||
14 | typedef unsigned char uchar; | ||
15 | typedef unsigned short ushort; | ||
16 | typedef unsigned int uint; | ||
17 | typedef unsigned long ulong; | ||
18 | |||
19 | typedef enum { | ||
20 | VTX_CHIP_AY = 0, /* emulate AY */ | ||
21 | VTX_CHIP_YM /* emulate YM */ | ||
22 | } vtx_chiptype_t; | ||
23 | |||
24 | typedef enum { | ||
25 | VTX_LAYOUT_MONO = 0, | ||
26 | VTX_LAYOUT_ABC, | ||
27 | VTX_LAYOUT_ACB, | ||
28 | VTX_LAYOUT_BAC, | ||
29 | VTX_LAYOUT_BCA, | ||
30 | VTX_LAYOUT_CAB, | ||
31 | VTX_LAYOUT_CBA, | ||
32 | VTX_LAYOUT_CUSTOM | ||
33 | } vtx_layout_t; | ||
34 | |||
35 | typedef struct { | ||
36 | vtx_chiptype_t chiptype; /* Type of sound chip */ | ||
37 | vtx_layout_t layout; /* stereo layout */ | ||
38 | uint loop; /* song loop */ | ||
39 | uint chipfreq; /* AY chip freq (1773400 for ZX) */ | ||
40 | uint playerfreq; /* 50 Hz for ZX, 60 Hz for yamaha */ | ||
41 | uint year; /* year song composed */ | ||
42 | char *title; /* song title */ | ||
43 | char *author; /* song author */ | ||
44 | char *from; /* song from */ | ||
45 | char *tracker; /* tracker */ | ||
46 | char *comment; /* comment */ | ||
47 | uint regdata_size; /* size of unpacked data */ | ||
48 | uint frames; /* number of AY data frames */ | ||
49 | } vtx_info_t; | ||
50 | |||
51 | #define VTX_STRING_MAX 254 | ||
52 | |||
53 | static uint Reader_ReadByte(int fd) { | ||
54 | unsigned char c; | ||
55 | read(fd, &c, sizeof(c)); | ||
56 | return c; | ||
57 | } | ||
58 | |||
59 | static uint Reader_ReadWord(int fd) { | ||
60 | unsigned short s; | ||
61 | read(fd, &s, sizeof(s)); | ||
62 | return letoh16(s); | ||
63 | } | ||
64 | |||
65 | static uint Reader_ReadDWord(int fd) { | ||
66 | unsigned int i; | ||
67 | read(fd, &i, sizeof(i)); | ||
68 | return letoh32(i); | ||
69 | } | ||
70 | |||
71 | static char* Reader_ReadString(int fd, char *str) { | ||
72 | int i = 0; | ||
73 | char c = 1; | ||
74 | char *p = str; | ||
75 | |||
76 | if (str) | ||
77 | *str = 0; | ||
78 | |||
79 | while (i < VTX_STRING_MAX && c) { | ||
80 | read(fd, &c, sizeof(c)); | ||
81 | if (str) | ||
82 | *str++ = c; | ||
83 | i++; | ||
84 | } | ||
85 | |||
86 | if (str) | ||
87 | *str = 0; | ||
88 | |||
89 | return p; | ||
90 | } | ||
91 | |||
92 | /* vtx info */ | ||
93 | |||
94 | bool get_vtx_metadata(int fd, struct mp3entry* id3) | ||
95 | { | ||
96 | vtx_info_t info; | ||
97 | char *p = id3->id3v2buf; | ||
98 | char buf[VTX_STRING_MAX+1]; | ||
99 | |||
100 | if (lseek(fd, 0, SEEK_SET) < 0) | ||
101 | goto exit_bad; | ||
102 | |||
103 | if (filesize(fd) < 20) | ||
104 | goto exit_bad; | ||
105 | |||
106 | uint hdr = Reader_ReadWord(fd); | ||
107 | |||
108 | if ((hdr != 0x7961) && (hdr != 0x6d79)) | ||
109 | goto exit_bad; | ||
110 | |||
111 | info.layout = (vtx_layout_t)Reader_ReadByte(fd); | ||
112 | info.loop = Reader_ReadWord(fd); | ||
113 | info.chipfreq = Reader_ReadDWord(fd); | ||
114 | info.playerfreq = Reader_ReadByte(fd); | ||
115 | info.year = Reader_ReadWord(fd); | ||
116 | info.regdata_size = Reader_ReadDWord(fd); | ||
117 | info.frames = info.regdata_size / 14; | ||
118 | info.title = Reader_ReadString(fd, buf); | ||
119 | if (buf[0]) { | ||
120 | /* Title */ | ||
121 | id3->title = p; | ||
122 | p += strlcpy(p, info.title, VTX_STRING_MAX) + 1; | ||
123 | } | ||
124 | info.author = Reader_ReadString(fd, buf); | ||
125 | if (buf[0]) { | ||
126 | /* Artist */ | ||
127 | id3->artist = p; | ||
128 | p += strlcpy(p, info.author, VTX_STRING_MAX) + 1; | ||
129 | } | ||
130 | info.from = Reader_ReadString(fd, NULL); | ||
131 | info.tracker = Reader_ReadString(fd, NULL); | ||
132 | info.comment = Reader_ReadString(fd, buf); | ||
133 | if (buf[0]) { | ||
134 | /* Comment */ | ||
135 | id3->comment = p; | ||
136 | p += strlcpy(p, info.comment, VTX_STRING_MAX) + 1; | ||
137 | } | ||
138 | |||
139 | id3->vbr = false; | ||
140 | id3->bitrate = 706; | ||
141 | id3->frequency = 44100; // XXX allow this to be configured? | ||
142 | |||
143 | id3->filesize = filesize(fd); | ||
144 | id3->length = info.frames * 1000 / info.playerfreq; | ||
145 | |||
146 | return true; | ||
147 | |||
148 | exit_bad: | ||
149 | return false; | ||
150 | } | ||