2 * This code handles HMP files. It can:
3 * - Open/read/close HMP files
4 * - Play HMP via Windows MIDI
5 * - Convert HMP to MIDI for further use
6 * Based on work of Arne de Bruijn and the JFFEE project
16 #ifdef WORDS_BIGENDIAN
17 #define MIDIINT(x) (x)
18 #define MIDISHORT(x) (x)
20 #define MIDIINT(x) SWAPINT(x)
21 #define MIDISHORT(x) SWAPSHORT(x)
25 // READ/OPEN/CLOSE HMP
27 void hmp_close(hmp_file *hmp)
31 for (i = 0; i < hmp->num_trks; i++)
32 if (hmp->trks[i].data)
33 d_free(hmp->trks[i].data);
37 hmp_file *hmp_open(const char *filename) {
46 if (!(fp = cfopen((char *)filename, "rb")))
49 hmp = d_malloc(sizeof(hmp_file));
55 memset(hmp, 0, sizeof(*hmp));
57 if ((cfread(buf, 1, 8, fp) != 8) || (memcmp(buf, "HMIMIDIP", 8)))
64 if (cfseek(fp, 0x30, SEEK_SET))
71 if (cfread(&num_tracks, 4, 1, fp) != 1)
78 if ((num_tracks < 1) || (num_tracks > HMP_TRACKS))
85 hmp->num_trks = num_tracks;
88 if (cfseek(fp, 0x308, SEEK_SET))
95 for (i = 0; i < num_tracks; i++) {
96 if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(&data, 4, 1, fp) != 1))
104 hmp->trks[i].len = data;
106 if (!(p = hmp->trks[i].data = d_malloc(data)))
113 /* finally, read track data */
114 if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(p, data, 1, fp) != 1))
126 // CONVERSION FROM HMP TO MIDI
128 static int hmptrk2mid(ubyte* data, int size, PHYSFS_file *mid)
131 ubyte lc1 = 0,last_com = 0;
134 int offset = cftell(mid);
136 while (data < dptr + size)
138 if (data[0] & 0x80) {
139 ubyte b = (data[0] & 0x7F);
140 PHYSFS_write(mid, &b, sizeof (b), 1);
144 d = (data[0] & 0x7F);
146 while ((data[n1] & 0x80) == 0) {
148 d += (data[n1] & 0x7F) << (n1 * 7);
152 while ((data[n1] & 0x80) == 0) {
157 for(n2 = 0; n2 <= n1; n2++) {
158 ubyte b = (data[n1 - n2] & 0x7F);
162 PHYSFS_write(mid, &b, sizeof(b), 1);
167 if (*data == 0xFF) { //meta?
168 PHYSFS_write(mid, data, 3 + data [2], 1);
176 switch (lc1 & 0xF0) {
183 PHYSFS_write(mid, &lc1, sizeof (lc1), 1);
184 PHYSFS_write(mid, data + 1, 2, 1);
190 PHYSFS_write(mid, &lc1, sizeof (lc1), 1);
191 PHYSFS_write(mid, data + 1, 1, 1);
200 return (cftell(mid) - offset);
203 ubyte tempo [19] = {'M','T','r','k',0,0,0,11,0,0xFF,0x51,0x03,0x18,0x80,0x00,0,0xFF,0x2F,0};
205 void hmp2mid(char *hmp_name, char *mid_name)
207 PHYSFS_file *mid=NULL;
212 hmp = hmp_open(hmp_name);
215 mid = PHYSFSX_openWriteBuffered(mid_name);
222 PHYSFS_write(mid, "MThd", 4, 1);
224 PHYSFS_write(mid, &mi, sizeof(mi), 1);
226 PHYSFS_write(mid, &ms, sizeof(mi), 1);
227 ms = MIDISHORT(hmp->num_trks);
228 PHYSFS_write(mid, &ms, sizeof(ms), 1);
229 ms = MIDISHORT((short) 0xC0);
230 PHYSFS_write(mid, &ms, sizeof(ms), 1);
231 PHYSFS_write(mid, tempo, sizeof(tempo), 1);
234 for (i = 1; i < hmp->num_trks; i++)
236 PHYSFS_write(mid, "MTrk", 4, 1);
239 PHYSFS_write(mid, &mi, sizeof(mi), 1);
240 mi = hmptrk2mid(hmp->trks[i].data, hmp->trks[i].len, mid);
242 cfseek(mid, loc, SEEK_SET);
243 PHYSFS_write(mid, &mi, sizeof(mi), 1);
244 cfseek(mid, 0, SEEK_END);