 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
theHobbit
Joined: 30 Sep 2006 Posts: 65
|
Posted: Fri Apr 11, 2008 12:52 pm Post subject: Problem with MODPLUG Code! |
|
|
Hi there, i'm porting modplug for my GameMusicGear app, but i'm having some problems with the amf format. I'm using psplink and a psp slim for testing.
Ok the code looks like this:
| Code: |
#define bswapLE16(X) (X)
#define READU16(X) ((((unsigned short)((X)[0]))<<0) | \
(((unsigned short)((X)[1]))<<8) )
BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, DWORD dwMemLength)
//-----------------------------------------------------------
{
AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream;
DWORD dwMemPos;
if ((!lpStream) || (dwMemLength < 2048)) return FALSE;
if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096))
{
UINT numorders, numpats, numsamples;
dwMemPos = 32;
numpats = lpStream[dwMemPos+3];
numorders = lpStream[dwMemPos+4];
numsamples = 64;
dwMemPos += 6;
if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders)
|| (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE;
m_nType = MOD_TYPE_AMF0;
m_nChannels = 8;
m_nInstruments = 0;
m_nSamples = 31;
m_nDefaultTempo = 125;
m_nDefaultSpeed = 6;
for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
{
Order[iOrd] = (iOrd < numorders) ? lpStream[dwMemPos+iOrd] : 0xFF;
}
dwMemPos = 294; // ???
for (UINT iSmp=0; iSmp<numsamples; iSmp++)
{
MODINSTRUMENT *psmp = &Ins[iSmp+1];
memcpy(m_szNames[iSmp+1], lpStream+dwMemPos, 22);
psmp->nFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]);
psmp->nVolume = lpStream[dwMemPos+23];
psmp->nGlobalVol = 64;
if (psmp->nVolume > 0x40) psmp->nVolume = 0x40;
psmp->nVolume <<= 2;
psmp->nLength = READU32(lpStream+dwMemPos+25);
psmp->nLoopStart = READU32(lpStream+dwMemPos+29);
psmp->nLoopEnd = psmp->nLoopStart + READU32(lpStream+dwMemPos+33);
if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength))
{
psmp->uFlags = CHN_LOOP;
} else
{
psmp->nLoopStart = psmp->nLoopEnd = 0;
}
if ((psmp->nLength) && (iSmp>31)) m_nSamples = iSmp+1;
dwMemPos += 37;
}
for (UINT iPat=0; iPat<numpats; iPat++)
{
MODCOMMAND *p = AllocatePattern(64, m_nChannels);
if (!p) break;
Patterns[iPat] = p;
PatternSize[iPat] = 64;
const UCHAR *pin = lpStream + dwMemPos;
for (UINT i=0; i<8*64; i++)
{
p->note = 0;
if (pin[0])
{
p->note = pin[0] + 13;
}
p->instr = pin[1];
p->command = pin[2];
p->param = pin[3];
if (p->command > 0x0F)
{
#ifdef AMFLOG
Log("0x%02X.0x%02X ?", p->command, p->param);
#endif
p->command = 0;
}
ConvertModCommand(p);
pin += 4;
p++;
}
dwMemPos += 64*32;
}
// Read samples
for (UINT iData=0; iData<m_nSamples; iData++)
{
MODINSTRUMENT *psmp = &Ins[iData+1];
if (psmp->nLength)
{
dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength);
}
}
return TRUE;
}
////////////////////////////
// DSM/AMF
USHORT *ptracks[MAX_PATTERNS];
DWORD sampleseekpos[MAX_SAMPLES];
if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F')
|| (pfh->version < 10) || (pfh->version > 14) || (!bswapLE16(pfh->numtracks))
|| (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS)
|| (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES)
|| (pfh->numchannels < 4) || (pfh->numchannels > 32))
return FALSE;
memcpy(m_szNames[0], pfh->title, 32);
dwMemPos = sizeof(AMFFILEHEADER);
m_nType = MOD_TYPE_AMF;
m_nChannels = pfh->numchannels;
m_nSamples = pfh->numsamples;
m_nInstruments = 0;
// Setup Channel Pan Positions
if (pfh->version >= 11)
{
signed char *panpos = (signed char *)(lpStream + dwMemPos);
UINT nchannels = (pfh->version >= 13) ? 32 : 16;
for (UINT i=0; i<nchannels; i++)
{
int pan = (panpos[i] + 64) * 2;
if (pan < 0) pan = 0;
if (pan > 256) { pan = 128; ChnSettings[i].dwFlags |= CHN_SURROUND; }
ChnSettings[i].nPan = pan;
}
dwMemPos += nchannels;
} else
{
for (UINT i=0; i<16; i++)
{
ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0;
}
dwMemPos += 16;
}
// Get Tempo/Speed
m_nDefaultTempo = 125;
m_nDefaultSpeed = 6;
if (pfh->version >= 13)
{
if (lpStream[dwMemPos] >= 32) m_nDefaultTempo = lpStream[dwMemPos];
if (lpStream[dwMemPos+1] <= 32) m_nDefaultSpeed = lpStream[dwMemPos+1];
dwMemPos += 2;
}
// Setup sequence list
for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
{
Order[iOrd] = 0xFF;
if (iOrd < pfh->numorders)
{
Order[iOrd] = iOrd;
PatternSize[iOrd] = 64;
if (pfh->version >= 14)
{
PatternSize[iOrd] = READU16(lpStream+dwMemPos);
dwMemPos += 2;
}
ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos);
dwMemPos += m_nChannels * sizeof(USHORT);
}
}
if (dwMemPos + m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE;
// Read Samples
UINT maxsampleseekpos = 0;
for (UINT iIns=0; iIns<m_nSamples; iIns++)
{
MODINSTRUMENT *pins = &Ins[iIns+1];
AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos);
dwMemPos += sizeof(AMFSAMPLE);
memcpy(m_szNames[iIns+1], psh->samplename, 32);
memcpy(pins->name, psh->filename, 13);
pins->nLength = bswapLE32(psh->length);
pins->nC4Speed = bswapLE16(psh->c2spd);
pins->nGlobalVol = 64;
pins->nVolume = psh->volume * 4;
if (pfh->version >= 11)
{
pins->nLoopStart = READU32(lpStream+dwMemPos);
pins->nLoopEnd = READU32(lpStream+dwMemPos+4);
dwMemPos += 8;
} else
{
pins->nLoopStart = READU16(lpStream+dwMemPos);
pins->nLoopEnd = pins->nLength;
dwMemPos += 2;
}
sampleseekpos[iIns] = 0;
if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1))
{
sampleseekpos[iIns] = bswapLE32(psh->offset);
if (bswapLE32(psh->offset) > maxsampleseekpos)
maxsampleseekpos = bswapLE32(psh->offset);
if ((pins->nLoopEnd > pins->nLoopStart + 2)
&& (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP;
}
}
// Read Track Mapping Table
USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos);
UINT realtrackcnt = 0;
dwMemPos += pfh->numtracks * sizeof(USHORT);
for (UINT iTrkMap=0; iTrkMap<pfh->numtracks; iTrkMap++)
{
if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap];
}
// Store tracks positions
BYTE **pTrackData = new BYTE *[realtrackcnt];
memset(pTrackData, 0, sizeof(pTrackData));
for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos + 3 <= dwMemLength)
{
UINT nTrkSize = READU16(lpStream+dwMemPos);
nTrkSize += (UINT)lpStream[dwMemPos+2] << 16;
if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength)
{
pTrackData[iTrack] = (BYTE *)(lpStream + dwMemPos);
}
dwMemPos += nTrkSize * 3 + 3;
}
// Create the patterns from the list of tracks
for (UINT iPat=0; iPat<pfh->numorders; iPat++)
{
MODCOMMAND *p;
p = AllocatePattern(PatternSize[iPat], m_nChannels);
if (!p) break;
Patterns[iPat] = p;
for (UINT iChn=0; iChn<m_nChannels; iChn++)
{
fprintf(stderr, "foo error\n");
UINT nTrack = bswapLE16(ptracks[iPat][iChn]);
if ((nTrack) && (nTrack <= pfh->numtracks))
{
UINT realtrk = bswapLE16(pTrackMap[nTrack-1]);
if (realtrk)
{
realtrk--;
if ((realtrk < realtrackcnt) && (pTrackData[realtrk]))
{
AMF_Unpack(p+iChn, pTrackData[realtrk], PatternSize[iPat], m_nChannels);
}
}
}
}
}
delete pTrackData;
// Read Sample Data
for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++)
{
if (dwMemPos >= dwMemLength) break;
for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (iSeek == sampleseekpos[iSmp])
{
MODINSTRUMENT *pins = &Ins[iSmp+1];
dwMemPos += ReadSample(pins, RS_PCM8U, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
break;
}
}
return TRUE;
} |
The code gives an addres load/inst fetch exception in the line after the "foo error" message:
UINT nTrack = bswapLE16(ptracks[iPat][iChn]);
Well i have tried to understand whats hapenning but i have only found that the problem is with the ptracks pointer array and that the exception occurs exactly in that line :|.
And also does anyone knows how to use the psp-addr2line in a prx? Well hope anyone can help |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Fri Apr 11, 2008 1:39 pm Post subject: |
|
|
| Code: | | ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos); |
is probably odd, so
| Code: | | UINT nTrack = bswapLE16(ptracks[iPat][iChn]); |
is generating an unaligned access exception. You can't fetch unaligned data on the MIPS. Data has to be on its natural alignment. |
|
| Back to top |
|
 |
theHobbit
Joined: 30 Sep 2006 Posts: 65
|
Posted: Sat Apr 12, 2008 12:09 pm Post subject: |
|
|
| Thanks for your answer, i have tried changing USHORT by BYTE and it works but the song is playing weird. Am i missing something? Do you know how can I fix the unaligned issue? Thanks in advance! |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Sat Apr 12, 2008 4:45 pm Post subject: |
|
|
ptracks[][] is a word, so simply changing it to a byte doesn't fetch all the data. Look at the macro from the code again:
| Code: | #define READU16(X) ((((unsigned short)((X)[0]))<<0) | \
(((unsigned short)((X)[1]))<<8) )
|
See what it does? It fetches a word by getting the two bytes and putting them together. That's what you need to do to get unaligned words. Any place in the code that gets a word needs to fetch it as two bytes unless you KNOW the pointer is word aligned. |
|
| Back to top |
|
 |
theHobbit
Joined: 30 Sep 2006 Posts: 65
|
Posted: Mon Apr 14, 2008 12:08 pm Post subject: |
|
|
Thanks, i have solved it doing this:
| Code: | | UINT nTrack = bswapLE16(ptracks[iPat][iChn*sizeof(USHORT)]); |
But well i don't know if it's the best solution :) |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Mon Apr 14, 2008 1:26 pm Post subject: |
|
|
| theHobbit wrote: | Thanks, i have solved it doing this:
| Code: | | UINT nTrack = bswapLE16(ptracks[iPat][iChn*sizeof(USHORT)]); |
But well i don't know if it's the best solution :) |
That only makes it skip entries in the array. You need to go back through the code and find every place the STREAM is accessed and make sure that access is via byte accesses, not words or longs. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|