forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problem with MODPLUG Code!

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
theHobbit



Joined: 30 Sep 2006
Posts: 65

PostPosted: Fri Apr 11, 2008 12:52 pm    Post subject: Problem with MODPLUG Code! Reply with quote

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
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Fri Apr 11, 2008 1:39 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
theHobbit



Joined: 30 Sep 2006
Posts: 65

PostPosted: Sat Apr 12, 2008 12:09 pm    Post subject: Reply with quote

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
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Apr 12, 2008 4:45 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
theHobbit



Joined: 30 Sep 2006
Posts: 65

PostPosted: Mon Apr 14, 2008 12:08 pm    Post subject: Reply with quote

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
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Mon Apr 14, 2008 1:26 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
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