- added a method to FileReader to read the contents into an array and used it on the MIDI sources for testing.

This commit is contained in:
Christoph Oelckers 2018-11-02 10:20:12 +01:00 committed by drfrag666
parent a2760d7da2
commit 0357cd451e
5 changed files with 62 additions and 71 deletions

View file

@ -184,6 +184,14 @@ public:
return mReader->Read(buffer, (long)len); return mReader->Read(buffer, (long)len);
} }
TArray<uint8_t> Read()
{
TArray<uint8_t> buffer(mReader->Length, true);
Size length = mReader->Read(&buffer[0], mReader->Length);
if (length < mReader->Length) buffer.Clear();
return buffer;
}
char *Gets(char *strbuf, Size len) char *Gets(char *strbuf, Size len)
{ {
return mReader->Gets(strbuf, (int)len); return mReader->Gets(strbuf, (int)len);

View file

@ -121,8 +121,7 @@ private:
uint32_t *SendCommand (uint32_t *event, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom); uint32_t *SendCommand (uint32_t *event, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
TrackInfo *FindNextDue (); TrackInfo *FindNextDue ();
uint8_t *MusHeader; TArray<uint8_t> MusHeader;
int SongLen;
TrackInfo *Tracks; TrackInfo *Tracks;
TrackInfo *TrackDue; TrackInfo *TrackDue;
int NumTracks; int NumTracks;
@ -181,8 +180,7 @@ private:
static uint32_t ReadVarLenHMI(TrackInfo *); static uint32_t ReadVarLenHMI(TrackInfo *);
static uint32_t ReadVarLenHMP(TrackInfo *); static uint32_t ReadVarLenHMP(TrackInfo *);
uint8_t *MusHeader; TArray<uint8_t> MusHeader;
int SongLen;
int NumTracks; int NumTracks;
TrackInfo *Tracks; TrackInfo *Tracks;
TrackInfo *TrackDue; TrackInfo *TrackDue;
@ -218,8 +216,7 @@ private:
uint32_t *SendCommand (uint32_t *event, EventSource track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom); uint32_t *SendCommand (uint32_t *event, EventSource track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
EventSource FindNextDue(); EventSource FindNextDue();
uint8_t *MusHeader; TArray<uint8_t> MusHeader;
int SongLen; // length of the entire file
int NumSongs; int NumSongs;
TrackInfo *Songs; TrackInfo *Songs;
TrackInfo *CurrSong; TrackInfo *CurrSong;

View file

@ -133,19 +133,17 @@ HMISong::HMISong (FileReader &reader)
{ // Way too small to be HMI. { // Way too small to be HMI.
return; return;
} }
MusHeader = new uint8_t[len]; MusHeader = reader.Read();
SongLen = len;
NumTracks = 0; NumTracks = 0;
if (reader.Read(MusHeader, len) != len) if (MusHeader.Size() == 0)
return; return;
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0) if (memcmp(&MusHeader[0], HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)
{ {
SetupForHMI(len); SetupForHMI(len);
} }
else if (((uint32_t *)MusHeader)[0] == MAKE_ID('H','M','I','M') && else if (memcmp(&MusHeader[0], "HMIMIDIP", 8) == 0)
((uint32_t *)MusHeader)[1] == MAKE_ID('I','D','I','P'))
{ {
SetupForHMP(len); SetupForHMP(len);
} }
@ -159,14 +157,10 @@ HMISong::HMISong (FileReader &reader)
HMISong::~HMISong() HMISong::~HMISong()
{ {
if (Tracks != NULL) if (Tracks != nullptr)
{ {
delete[] Tracks; delete[] Tracks;
} }
if (MusHeader != NULL)
{
delete[] MusHeader;
}
} }
//========================================================================== //==========================================================================
@ -179,8 +173,10 @@ void HMISong::SetupForHMI(int len)
{ {
int i, p; int i, p;
auto MusPtr = &MusHeader[0];
ReadVarLen = ReadVarLenHMI; ReadVarLen = ReadVarLenHMI;
NumTracks = GetShort(MusHeader + HMI_TRACK_COUNT_OFFSET); NumTracks = GetShort(MusPtr + HMI_TRACK_COUNT_OFFSET);
if (NumTracks <= 0) if (NumTracks <= 0)
{ {
@ -191,16 +187,16 @@ void HMISong::SetupForHMI(int len)
// HMI files have two values here, a full value and a quarter value. Some games, // HMI files have two values here, a full value and a quarter value. Some games,
// notably Quarantines, have identical values for some reason, so it's safer to // notably Quarantines, have identical values for some reason, so it's safer to
// use the quarter value and multiply it by four than to trust the full value. // use the quarter value and multiply it by four than to trust the full value.
Division = GetShort(MusHeader + HMI_DIVISION_OFFSET) << 2; Division = GetShort(MusPtr + HMI_DIVISION_OFFSET) << 2;
Tempo = InitialTempo = 4000000; Tempo = InitialTempo = 4000000;
Tracks = new TrackInfo[NumTracks + 1]; Tracks = new TrackInfo[NumTracks + 1];
int track_dir = GetInt(MusHeader + HMI_TRACK_DIR_PTR_OFFSET); int track_dir = GetInt(MusPtr + HMI_TRACK_DIR_PTR_OFFSET);
// Gather information about each track // Gather information about each track
for (i = 0, p = 0; i < NumTracks; ++i) for (i = 0, p = 0; i < NumTracks; ++i)
{ {
int start = GetInt(MusHeader + track_dir + i*4); int start = GetInt(MusPtr + track_dir + i*4);
int tracklen, datastart; int tracklen, datastart;
if (start > len - HMITRACK_DESIGNATION_OFFSET - 4) if (start > len - HMITRACK_DESIGNATION_OFFSET - 4)
@ -209,7 +205,7 @@ void HMISong::SetupForHMI(int len)
} }
// BTW, HMI does not actually check the track header. // BTW, HMI does not actually check the track header.
if (memcmp(MusHeader + start, TRACK_MAGIC, 13) != 0) if (memcmp(MusPtr + start, TRACK_MAGIC, 13) != 0)
{ {
continue; continue;
} }
@ -222,7 +218,7 @@ void HMISong::SetupForHMI(int len)
} }
else else
{ {
tracklen = GetInt(MusHeader + track_dir + i*4 + 4) - start; tracklen = GetInt(MusPtr + track_dir + i*4 + 4) - start;
} }
// Clamp incomplete tracks to the end of the file. // Clamp incomplete tracks to the end of the file.
tracklen = MIN(tracklen, len - start); tracklen = MIN(tracklen, len - start);
@ -232,7 +228,7 @@ void HMISong::SetupForHMI(int len)
} }
// Offset to actual MIDI events. // Offset to actual MIDI events.
datastart = GetInt(MusHeader + start + HMITRACK_DATA_PTR_OFFSET); datastart = GetInt(MusPtr + start + HMITRACK_DATA_PTR_OFFSET);
tracklen -= datastart; tracklen -= datastart;
if (tracklen <= 0) if (tracklen <= 0)
{ {
@ -240,7 +236,7 @@ void HMISong::SetupForHMI(int len)
} }
// Store track information // Store track information
Tracks[p].TrackBegin = MusHeader + start + datastart; Tracks[p].TrackBegin = MusPtr + start + datastart;
Tracks[p].TrackP = 0; Tracks[p].TrackP = 0;
Tracks[p].MaxTrackP = tracklen; Tracks[p].MaxTrackP = tracklen;
@ -248,7 +244,7 @@ void HMISong::SetupForHMI(int len)
// connected to the MIDI device. // connected to the MIDI device.
for (int ii = 0; ii < NUM_HMI_DESIGNATIONS; ++ii) for (int ii = 0; ii < NUM_HMI_DESIGNATIONS; ++ii)
{ {
Tracks[p].Designation[ii] = GetShort(MusHeader + start + HMITRACK_DESIGNATION_OFFSET + ii*2); Tracks[p].Designation[ii] = GetShort(MusPtr + start + HMITRACK_DESIGNATION_OFFSET + ii*2);
} }
p++; p++;
@ -270,12 +266,14 @@ void HMISong::SetupForHMP(int len)
int track_data; int track_data;
int i, p; int i, p;
auto MusPtr = &MusHeader[0];
ReadVarLen = ReadVarLenHMP; ReadVarLen = ReadVarLenHMP;
if (MusHeader[8] == 0) if (MusPtr[8] == 0)
{ {
track_data = HMP_TRACK_OFFSET_0; track_data = HMP_TRACK_OFFSET_0;
} }
else if (memcmp(MusHeader + 8, HMP_NEW_DATE, sizeof(HMP_NEW_DATE)) == 0) else if (memcmp(MusPtr + 8, HMP_NEW_DATE, sizeof(HMP_NEW_DATE)) == 0)
{ {
track_data = HMP_TRACK_OFFSET_1; track_data = HMP_TRACK_OFFSET_1;
} }
@ -284,7 +282,7 @@ void HMISong::SetupForHMP(int len)
return; return;
} }
NumTracks = GetInt(MusHeader + HMP_TRACK_COUNT_OFFSET); NumTracks = GetInt(MusPtr + HMP_TRACK_COUNT_OFFSET);
if (NumTracks <= 0) if (NumTracks <= 0)
{ {
@ -292,7 +290,7 @@ void HMISong::SetupForHMP(int len)
} }
// The division is the number of pulses per quarter note (PPQN). // The division is the number of pulses per quarter note (PPQN).
Division = GetInt(MusHeader + HMP_DIVISION_OFFSET); Division = GetInt(MusPtr + HMP_DIVISION_OFFSET);
Tempo = InitialTempo = 1000000; Tempo = InitialTempo = 1000000;
Tracks = new TrackInfo[NumTracks + 1]; Tracks = new TrackInfo[NumTracks + 1];
@ -308,7 +306,7 @@ void HMISong::SetupForHMP(int len)
break; break;
} }
tracklen = GetInt(MusHeader + start + HMPTRACK_LEN_OFFSET); tracklen = GetInt(MusPtr + start + HMPTRACK_LEN_OFFSET);
track_data += tracklen; track_data += tracklen;
// Clamp incomplete tracks to the end of the file. // Clamp incomplete tracks to the end of the file.
@ -326,7 +324,7 @@ void HMISong::SetupForHMP(int len)
} }
// Store track information // Store track information
Tracks[p].TrackBegin = MusHeader + start + HMPTRACK_MIDI_DATA_OFFSET; Tracks[p].TrackBegin = MusPtr + start + HMPTRACK_MIDI_DATA_OFFSET;
Tracks[p].TrackP = 0; Tracks[p].TrackP = 0;
Tracks[p].MaxTrackP = tracklen; Tracks[p].MaxTrackP = tracklen;
@ -337,14 +335,14 @@ void HMISong::SetupForHMP(int len)
// HMI files. Some songs contain nothing but zeroes for this data, so I'd rather // HMI files. Some songs contain nothing but zeroes for this data, so I'd rather
// not go around using it without confirmation. // not go around using it without confirmation.
Printf("Track %d: %d %08x %d: \034I", i, GetInt(MusHeader + start), Printf("Track %d: %d %08x %d: \034I", i, GetInt(MusPtr + start),
GetInt(MusHeader + start + 4), GetInt(MusHeader + start + 8)); GetInt(MusPtr + start + 4), GetInt(MusPtr + start + 8));
int designations = HMP_DESIGNATIONS_OFFSET + int designations = HMP_DESIGNATIONS_OFFSET +
GetInt(MusHeader + start + HMPTRACK_DESIGNATION_OFFSET) * 4 * NUM_HMP_DESIGNATIONS; GetInt(MusPtr + start + HMPTRACK_DESIGNATION_OFFSET) * 4 * NUM_HMP_DESIGNATIONS;
for (int ii = 0; ii < NUM_HMP_DESIGNATIONS; ++ii) for (int ii = 0; ii < NUM_HMP_DESIGNATIONS; ++ii)
{ {
Printf(" %04x", GetInt(MusHeader + designations + ii*4)); Printf(" %04x", GetInt(MusPtr + designations + ii*4));
} }
Printf("\n"); Printf("\n");
#endif #endif
@ -478,7 +476,7 @@ void HMISong :: DoRestart()
bool HMISong::CheckDone() bool HMISong::CheckDone()
{ {
return TrackDue == NULL; return TrackDue == nullptr;
} }
//========================================================================== //==========================================================================
@ -968,7 +966,7 @@ void NoteOffQueue::Heapify()
// //
// HMISong :: FindNextDue // HMISong :: FindNextDue
// //
// Scans every track for the next event to play. Returns NULL if all events // Scans every track for the next event to play. Returns nullptr if all events
// have been consumed. // have been consumed.
// //
//========================================================================== //==========================================================================
@ -991,7 +989,7 @@ HMISong::TrackInfo *HMISong::FindNextDue ()
} }
// Check regular tracks. // Check regular tracks.
track = NULL; track = nullptr;
best = 0xFFFFFFFF; best = 0xFFFFFFFF;
for (i = 0; i < NumTracks; ++i) for (i = 0; i < NumTracks; ++i)
{ {

View file

@ -102,13 +102,11 @@ struct MIDISong2::TrackInfo
MIDISong2::MIDISong2 (FileReader &reader) MIDISong2::MIDISong2 (FileReader &reader)
: MusHeader(0), Tracks(0) : MusHeader(0), Tracks(0)
{ {
int p; unsigned p;
int i; int i;
SongLen = (int)reader.GetLength(); MusHeader = reader.Read();
MusHeader = new uint8_t[SongLen]; if (MusHeader.Size() == 0) return;
if (reader.Read(MusHeader, SongLen) != SongLen)
return;
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6) if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6)
@ -138,7 +136,7 @@ MIDISong2::MIDISong2 (FileReader &reader)
Tracks = new TrackInfo[NumTracks]; Tracks = new TrackInfo[NumTracks];
// Gather information about each track // Gather information about each track
for (i = 0, p = 14; i < NumTracks && p < SongLen + 8; ++i) for (i = 0, p = 14; i < NumTracks && p < MusHeader.Size() + 8; ++i)
{ {
uint32_t chunkLen = uint32_t chunkLen =
(MusHeader[p+4]<<24) | (MusHeader[p+4]<<24) |
@ -146,9 +144,9 @@ MIDISong2::MIDISong2 (FileReader &reader)
(MusHeader[p+6]<<8) | (MusHeader[p+6]<<8) |
(MusHeader[p+7]); (MusHeader[p+7]);
if (chunkLen + p + 8 > (uint32_t)SongLen) if (chunkLen + p + 8 > MusHeader.Size())
{ // Track too long, so truncate it { // Track too long, so truncate it
chunkLen = SongLen - p - 8; chunkLen = MusHeader.Size() - p - 8;
} }
if (MusHeader[p+0] == 'M' && if (MusHeader[p+0] == 'M' &&
@ -156,7 +154,7 @@ MIDISong2::MIDISong2 (FileReader &reader)
MusHeader[p+2] == 'r' && MusHeader[p+2] == 'r' &&
MusHeader[p+3] == 'k') MusHeader[p+3] == 'k')
{ {
Tracks[i].TrackBegin = MusHeader + p + 8; Tracks[i].TrackBegin = &MusHeader[p + 8];
Tracks[i].TrackP = 0; Tracks[i].TrackP = 0;
Tracks[i].MaxTrackP = chunkLen; Tracks[i].MaxTrackP = chunkLen;
} }
@ -182,14 +180,10 @@ MIDISong2::MIDISong2 (FileReader &reader)
MIDISong2::~MIDISong2 () MIDISong2::~MIDISong2 ()
{ {
if (Tracks != NULL) if (Tracks != nullptr)
{ {
delete[] Tracks; delete[] Tracks;
} }
if (MusHeader != NULL)
{
delete[] MusHeader;
}
} }
//========================================================================== //==========================================================================
@ -277,7 +271,7 @@ void MIDISong2 :: DoRestart()
bool MIDISong2::CheckDone() bool MIDISong2::CheckDone()
{ {
return TrackDue == NULL; return TrackDue == nullptr;
} }
//========================================================================== //==========================================================================
@ -754,7 +748,7 @@ uint32_t MIDISong2::TrackInfo::ReadVarLen ()
// //
// MIDISong2 :: FindNextDue // MIDISong2 :: FindNextDue
// //
// Scans every track for the next event to play. Returns NULL if all events // Scans every track for the next event to play. Returns nullptr if all events
// have been consumed. // have been consumed.
// //
//========================================================================== //==========================================================================
@ -774,10 +768,10 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue ()
switch (Format) switch (Format)
{ {
case 0: case 0:
return Tracks[0].Finished ? NULL : Tracks; return Tracks[0].Finished ? nullptr : Tracks;
case 1: case 1:
track = NULL; track = nullptr;
best = 0xFFFFFFFF; best = 0xFFFFFFFF;
for (i = 0; i < NumTracks; ++i) for (i = 0; i < NumTracks; ++i)
{ {
@ -798,9 +792,9 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue ()
{ {
track++; track++;
} }
return track < &Tracks[NumTracks] ? track : NULL; return track < &Tracks[NumTracks] ? track : nullptr;
} }
return NULL; return nullptr;
} }

View file

@ -108,13 +108,11 @@ struct XMISong::TrackInfo
XMISong::XMISong (FileReader &reader) XMISong::XMISong (FileReader &reader)
: MusHeader(0), Songs(0) : MusHeader(0), Songs(0)
{ {
SongLen = (int)reader.GetLength(); MusHeader = reader.Read();
MusHeader = new uint8_t[SongLen]; if (MusHeader.Size() == 0) return;
if (reader.Read(MusHeader, SongLen) != SongLen)
return;
// Find all the songs in this file. // Find all the songs in this file.
NumSongs = FindXMIDforms(MusHeader, SongLen, NULL); NumSongs = FindXMIDforms(&MusHeader[0], MusHeader.Size(), nullptr);
if (NumSongs == 0) if (NumSongs == 0)
{ {
return; return;
@ -132,7 +130,7 @@ XMISong::XMISong (FileReader &reader)
Songs = new TrackInfo[NumSongs]; Songs = new TrackInfo[NumSongs];
memset(Songs, 0, sizeof(*Songs) * NumSongs); memset(Songs, 0, sizeof(*Songs) * NumSongs);
FindXMIDforms(MusHeader, SongLen, Songs); FindXMIDforms(&MusHeader[0], MusHeader.Size(), Songs);
CurrSong = Songs; CurrSong = Songs;
DPrintf(DMSG_SPAMMY, "XMI song count: %d\n", NumSongs); DPrintf(DMSG_SPAMMY, "XMI song count: %d\n", NumSongs);
} }
@ -145,14 +143,10 @@ XMISong::XMISong (FileReader &reader)
XMISong::~XMISong () XMISong::~XMISong ()
{ {
if (Songs != NULL) if (Songs != nullptr)
{ {
delete[] Songs; delete[] Songs;
} }
if (MusHeader != NULL)
{
delete[] MusHeader;
}
} }
//========================================================================== //==========================================================================
@ -176,7 +170,7 @@ int XMISong::FindXMIDforms(const uint8_t *chunk, int len, TrackInfo *songs) cons
{ {
if (GetNativeInt(chunk + p + 8) == MAKE_ID('X','M','I','D')) if (GetNativeInt(chunk + p + 8) == MAKE_ID('X','M','I','D'))
{ {
if (songs != NULL) if (songs != nullptr)
{ {
FoundXMID(chunk + p + 12, chunklen - 4, songs + count); FoundXMID(chunk + p + 12, chunklen - 4, songs + count);
} }