ft2play is now safe for use on big endian machines
parent
1737f4021d
commit
496f7870f8
|
@ -38,6 +38,9 @@
|
||||||
typedef signed long ssize_t;
|
typedef signed long ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
#define USE_VOL_RAMP
|
#define USE_VOL_RAMP
|
||||||
|
|
||||||
enum { _soundBufferSize = 512 };
|
enum { _soundBufferSize = 512 };
|
||||||
|
@ -409,6 +412,7 @@ typedef struct
|
||||||
static MEM *mopen(const uint8_t *src, size_t length);
|
static MEM *mopen(const uint8_t *src, size_t length);
|
||||||
static void mclose(MEM *buf);
|
static void mclose(MEM *buf);
|
||||||
static size_t mread(void *buffer, size_t size, size_t count, MEM *buf);
|
static size_t mread(void *buffer, size_t size, size_t count, MEM *buf);
|
||||||
|
static size_t mread_swap(void *buffer, size_t size, size_t count, MEM *buf, uint8_t le_xor, uint8_t be_xor);
|
||||||
static int32_t meof(MEM *buf);
|
static int32_t meof(MEM *buf);
|
||||||
static void mseek(MEM *buf, ssize_t offset, int32_t whence);
|
static void mseek(MEM *buf, ssize_t offset, int32_t whence);
|
||||||
static void setSamplesPerFrame(PLAYER *, uint32_t val);
|
static void setSamplesPerFrame(PLAYER *, uint32_t val);
|
||||||
|
@ -2319,17 +2323,31 @@ static int8_t AllocateInstr(PLAYER *pl, uint16_t i)
|
||||||
static int8_t LoadInstrHeader(PLAYER *p, MEM *f, uint16_t i)
|
static int8_t LoadInstrHeader(PLAYER *p, MEM *f, uint16_t i)
|
||||||
{
|
{
|
||||||
uint8_t j;
|
uint8_t j;
|
||||||
|
uint16_t k;
|
||||||
|
|
||||||
InstrHeaderTyp ih;
|
InstrHeaderTyp ih;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
memset(&ih, 0, InstrHeaderSize);
|
memset(&ih, 0, InstrHeaderSize);
|
||||||
|
|
||||||
mread(&ih.InstrSize, 4, 1, f);
|
mread_swap(&ih.InstrSize, 4, 1, f, 0, 3);
|
||||||
|
|
||||||
if ((ih.InstrSize <= 0) || (ih.InstrSize > InstrHeaderSize))
|
if ((ih.InstrSize <= 0) || (ih.InstrSize > InstrHeaderSize))
|
||||||
ih.InstrSize = InstrHeaderSize;
|
ih.InstrSize = InstrHeaderSize;
|
||||||
|
|
||||||
mread(ih.Name, ih.InstrSize - 4, 1, f);
|
size = ih.InstrSize - 4;
|
||||||
|
|
||||||
|
mread(ih.Name, min(size, 22), 1, f);
|
||||||
|
if (size > 22) mread(&ih.Typ, min(size - 22, 1), 1, f);
|
||||||
|
if (size > 23) mread_swap(&ih.AntSamp, min(size - 23, 2), 1, f, 0, 1);
|
||||||
|
if (size > 25) mread_swap(&ih.SampleSize, min(size - 25, 4), 1, f, 0, 3);
|
||||||
|
if (size > 29) mread(&ih.TA, min(size - 29, 96), 1, f);
|
||||||
|
if (size > 125) mread_swap(&ih.EnvVP, min(size - 125, 96), 1, f, 0, 1);
|
||||||
|
if (size > 221) mread(&ih.EnvVPAnt, min(size - 221, 14), 1, f);
|
||||||
|
if (size > 235) mread_swap(&ih.FadeOut, min(size - 235, 2), 1, f, 0, 1);
|
||||||
|
if (size > 237) mread(&ih.MIDIOn, min(size - 237, 2), 1, f);
|
||||||
|
if (size > 239) mread_swap(&ih.MIDIProgram, min(size - 239, 4), 1, f, 0, 1);
|
||||||
|
if (size > 243) mread(&ih.Mute, min(size - 243, 16), 1, f);
|
||||||
|
|
||||||
if (meof(f) || (ih.AntSamp > 32)) return (0);
|
if (meof(f) || (ih.AntSamp > 32)) return (0);
|
||||||
|
|
||||||
|
@ -2340,7 +2358,11 @@ static int8_t LoadInstrHeader(PLAYER *p, MEM *f, uint16_t i)
|
||||||
memcpy(p->Instr[i]->TA, ih.TA, ih.InstrSize);
|
memcpy(p->Instr[i]->TA, ih.TA, ih.InstrSize);
|
||||||
p->Instr[i]->AntSamp = ih.AntSamp;
|
p->Instr[i]->AntSamp = ih.AntSamp;
|
||||||
|
|
||||||
mread(ih.Samp, ih.AntSamp * sizeof (SampleHeaderTyp), 1, f);
|
for (k = 0; k < ih.AntSamp; k++)
|
||||||
|
{
|
||||||
|
mread_swap(&ih.Samp[k].Len, 4, 3, f, 0, 3);
|
||||||
|
mread(&ih.Samp[k].vol, 28, 1, f);
|
||||||
|
}
|
||||||
if (meof(f)) return (0);
|
if (meof(f)) return (0);
|
||||||
|
|
||||||
for (j = 0; j < ih.AntSamp; ++j)
|
for (j = 0; j < ih.AntSamp; ++j)
|
||||||
|
@ -2488,7 +2510,7 @@ static int8_t LoadPatterns(PLAYER *p, MEM *f)
|
||||||
|
|
||||||
for (i = 0; i < p->Song.AntPtn; ++i)
|
for (i = 0; i < p->Song.AntPtn; ++i)
|
||||||
{
|
{
|
||||||
mread(&ph.PatternHeaderSize, 4, 1, f);
|
mread_swap(&ph.PatternHeaderSize, 4, 1, f, 0, 3);
|
||||||
mread(&ph.Typ, 1, 1, f);
|
mread(&ph.Typ, 1, 1, f);
|
||||||
|
|
||||||
ph.PattLen = 0;
|
ph.PattLen = 0;
|
||||||
|
@ -2499,10 +2521,10 @@ static int8_t LoadPatterns(PLAYER *p, MEM *f)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mread(&ph.PattLen, 2, 1, f);
|
mread_swap(&ph.PattLen, 2, 1, f, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mread(&ph.DataLen, 2, 1, f);
|
mread_swap(&ph.DataLen, 2, 1, f, 0, 1);
|
||||||
|
|
||||||
if (p->Song.Ver == 0x0102)
|
if (p->Song.Ver == 0x0102)
|
||||||
mseek(f, ph.PatternHeaderSize - 8, SEEK_CUR);
|
mseek(f, ph.PatternHeaderSize - 8, SEEK_CUR);
|
||||||
|
@ -2589,7 +2611,11 @@ int8_t ft2play_LoadModule(void *_p, const uint8_t *buffer, size_t size)
|
||||||
if (f == NULL) return (0);
|
if (f == NULL) return (0);
|
||||||
|
|
||||||
// start loading
|
// start loading
|
||||||
mread(&h, sizeof (h), 1, f);
|
mread(&h.Sig, 58, 1, f);
|
||||||
|
mread_swap(&h.Ver, 2, 1, f, 0, 1);
|
||||||
|
mread_swap(&h.HeaderSize, 4, 1, f, 0, 3);
|
||||||
|
mread_swap(&h.Len, 2, 8, f, 0, 1);
|
||||||
|
mread(&h.SongTab, 256, 1, f);
|
||||||
|
|
||||||
if ((memcmp(h.Sig, "Extended Module: ", 17) != 0) || (h.Ver < 0x0102) || (h.Ver > 0x104))
|
if ((memcmp(h.Sig, "Extended Module: ", 17) != 0) || (h.Ver < 0x0102) || (h.Ver > 0x104))
|
||||||
{
|
{
|
||||||
|
@ -3789,15 +3815,26 @@ void ft2play_PlaySong(void *_p, int32_t startOrder)
|
||||||
p->playedOrder[startOrder / 8] = 1 << (startOrder % 8);
|
p->playedOrder[startOrder / 8] = 1 << (startOrder % 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mopen_is_big_endian;
|
||||||
|
|
||||||
static MEM *mopen(const uint8_t *src, size_t length)
|
static MEM *mopen(const uint8_t *src, size_t length)
|
||||||
{
|
{
|
||||||
MEM *b;
|
MEM *b;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t a;
|
||||||
|
uint8_t b[4];
|
||||||
|
} endian_test;
|
||||||
|
|
||||||
if ((src == NULL) || (length <= 0)) return (NULL);
|
if ((src == NULL) || (length <= 0)) return (NULL);
|
||||||
|
|
||||||
b = (MEM *)(malloc(sizeof (MEM)));
|
b = (MEM *)(malloc(sizeof (MEM)));
|
||||||
if (b == NULL) return (NULL);
|
if (b == NULL) return (NULL);
|
||||||
|
|
||||||
|
endian_test.a = 1;
|
||||||
|
mopen_is_big_endian = endian_test.b[3];
|
||||||
|
|
||||||
b->_base = (uint8_t *)(src);
|
b->_base = (uint8_t *)(src);
|
||||||
b->_ptr = (uint8_t *)(src);
|
b->_ptr = (uint8_t *)(src);
|
||||||
b->_cnt = length;
|
b->_cnt = length;
|
||||||
|
@ -3840,6 +3877,45 @@ static size_t mread(void *buffer, size_t size, size_t count, MEM *buf)
|
||||||
return (pcnt / size);
|
return (pcnt / size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t mread_swap(void *buffer, size_t size, size_t count, MEM *buf, uint8_t le_xor, uint8_t be_xor)
|
||||||
|
{
|
||||||
|
size_t wrcnt;
|
||||||
|
ssize_t pcnt;
|
||||||
|
uint8_t xor;
|
||||||
|
|
||||||
|
if (buf == NULL) return (0);
|
||||||
|
if (buf->_ptr == NULL) return (0);
|
||||||
|
|
||||||
|
wrcnt = size * count;
|
||||||
|
if ((size == 0) || buf->_eof) return (0);
|
||||||
|
|
||||||
|
xor = mopen_is_big_endian ? be_xor : le_xor;
|
||||||
|
|
||||||
|
pcnt = (buf->_cnt > wrcnt) ? wrcnt : buf->_cnt;
|
||||||
|
|
||||||
|
if ( !xor )
|
||||||
|
memcpy(buffer, buf->_ptr, pcnt);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
uint8_t * bbuffer = (uint8_t *) buffer;
|
||||||
|
for (i = 0; i < pcnt; i++)
|
||||||
|
bbuffer[i ^ xor] = buf->_ptr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->_cnt -= pcnt;
|
||||||
|
buf->_ptr += pcnt;
|
||||||
|
|
||||||
|
if (buf->_cnt <= 0)
|
||||||
|
{
|
||||||
|
buf->_ptr = buf->_base + buf->_bufsiz;
|
||||||
|
buf->_cnt = 0;
|
||||||
|
buf->_eof = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pcnt / size);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t meof(MEM *buf)
|
static int32_t meof(MEM *buf)
|
||||||
{
|
{
|
||||||
if (buf == NULL) return (1); // XXX: Should return a different value?
|
if (buf == NULL) return (1); // XXX: Should return a different value?
|
||||||
|
|
Loading…
Reference in New Issue