Skip to content

Commit d9e9d00

Browse files
committed
improve detection of headerless GYM files
1 parent 1aed079 commit d9e9d00

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

player/gymplayer.cpp

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,14 @@ const char* GYMPlayer::GetPlayerName(void) const
8787

8888
/*static*/ UINT8 GYMPlayer::PlayerCanLoadFile(DATA_LOADER *dataLoader)
8989
{
90-
DataLoader_ReadUntil(dataLoader,0x04);
90+
DataLoader_ReadUntil(dataLoader, 0x04);
9191
if (DataLoader_GetSize(dataLoader) < 0x04)
9292
return 0xF1; // file too small
9393
if (! memcmp(&DataLoader_GetData(dataLoader)[0x00], "GYMX", 4))
9494
return 0x00; // valid GYMX header
95-
if (DataLoader_GetData(dataLoader)[0x00] <= 0x03) // check for a valid command byte
96-
return 0x00; // TODO: Check the first 0x40 bytes for a better heuristic
95+
DataLoader_ReadUntil(dataLoader, 0x200);
96+
if (CheckRawGYMFile(DataLoader_GetSize(dataLoader), DataLoader_GetData(dataLoader)))
97+
return 0x00; // the heuristic for detection raw GYM files found no issues
9798
return 0xF0; // invalid file
9899
}
99100

@@ -102,6 +103,61 @@ UINT8 GYMPlayer::CanLoadFile(DATA_LOADER *dataLoader) const
102103
return this->PlayerCanLoadFile(dataLoader);
103104
}
104105

106+
/*static*/ bool GYMPlayer::CheckRawGYMFile(UINT32 dataLen, const UINT8* data)
107+
{
108+
UINT32 filePos;
109+
bool fileEnd;
110+
UINT8 curCmd;
111+
UINT8 curReg;
112+
113+
fileEnd = false;
114+
filePos = 0x00;
115+
116+
while(filePos < dataLen && data[filePos] == 0x00)
117+
filePos ++;
118+
if (filePos >= dataLen)
119+
return false; // only 00s - assume invalid file
120+
121+
while(! fileEnd && filePos < dataLen)
122+
{
123+
curCmd = data[filePos];
124+
filePos ++;
125+
switch(curCmd)
126+
{
127+
case 0x00: // wait 1 frame
128+
break;
129+
case 0x01: // YM2612 port 0
130+
case 0x02: // YM2612 port 1
131+
if (filePos + 0x02 > dataLen)
132+
break;
133+
curReg = data[filePos + 0x00];
134+
// valid YM2612 registers are:
135+
// port 0: 21..BF
136+
// port 1: 30..BF
137+
if (curReg >= 0xC0)
138+
return false;
139+
if (curCmd == 0x01 && curReg < 0x21)
140+
return false;
141+
if (curCmd == 0x02 && curReg < 0x30)
142+
return false;
143+
filePos += 0x02;
144+
break;
145+
case 0x03: // SEGA PSG
146+
if (filePos + 0x01 > dataLen)
147+
break;
148+
curReg = data[filePos];
149+
if (curReg >= 0x40 && curReg < 0x80)
150+
return false; // invalid PSG values
151+
filePos += 0x01;
152+
break;
153+
default:
154+
return false; // assume invalid file
155+
}
156+
}
157+
158+
return true;
159+
}
160+
105161
UINT8 GYMPlayer::LoadFile(DATA_LOADER *dataLoader)
106162
{
107163
_dLoad = NULL;

player/gymplayer.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class GYMPlayer : public PlayerBase
115115
void RefreshMuting(GYM_CHIPDEV& chipDev, const PLR_MUTE_OPTS& muteOpts);
116116
void RefreshPanning(GYM_CHIPDEV& chipDev, const PLR_PAN_OPTS& panOpts);
117117

118+
static bool CheckRawGYMFile(UINT32 dataLen, const UINT8* data);
118119
UINT8 DecompressZlibData(void);
119120
void CalcSongLength(void);
120121
UINT8 LoadTags(void);

utils/DataLoader.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void DataLoader_SetPreloadBytes(DATA_LOADER *loader, UINT32 byteCount)
7777
void DataLoader_ReadUntil(DATA_LOADER *loader, UINT32 fileOffset)
7878
{
7979
if (fileOffset > loader->_bytesLoaded)
80-
DataLoader_Read(loader,fileOffset);
80+
DataLoader_Read(loader, fileOffset - loader->_bytesLoaded);
8181
return;
8282
}
8383

0 commit comments

Comments
 (0)