gosu 1.4.1 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL_sound/SDL_sound.c +21 -63
  3. data/dependencies/SDL_sound/SDL_sound.h +2 -2
  4. data/dependencies/SDL_sound/SDL_sound_aiff.c +26 -23
  5. data/dependencies/SDL_sound/SDL_sound_au.c +8 -8
  6. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +4 -5
  7. data/dependencies/SDL_sound/SDL_sound_flac.c +28 -30
  8. data/dependencies/SDL_sound/SDL_sound_internal.h +4 -4
  9. data/dependencies/SDL_sound/SDL_sound_modplug.c +1 -1
  10. data/dependencies/SDL_sound/SDL_sound_mp3.c +19 -23
  11. data/dependencies/SDL_sound/SDL_sound_raw.c +5 -6
  12. data/dependencies/SDL_sound/SDL_sound_shn.c +4 -4
  13. data/dependencies/SDL_sound/SDL_sound_voc.c +15 -15
  14. data/dependencies/SDL_sound/SDL_sound_vorbis.c +14 -7
  15. data/dependencies/SDL_sound/SDL_sound_wav.c +17 -17
  16. data/dependencies/SDL_sound/dr_flac.h +10840 -4779
  17. data/dependencies/SDL_sound/dr_mp3.h +2793 -1004
  18. data/dependencies/SDL_sound/libmodplug/fastmix.c +5 -0
  19. data/dependencies/SDL_sound/libmodplug/load_669.c +1 -1
  20. data/dependencies/SDL_sound/libmodplug/load_amf.c +1 -0
  21. data/dependencies/SDL_sound/libmodplug/load_ams.c +38 -22
  22. data/dependencies/SDL_sound/libmodplug/load_it.c +18 -14
  23. data/dependencies/SDL_sound/libmodplug/load_mdl.c +18 -9
  24. data/dependencies/SDL_sound/libmodplug/load_med.c +7 -6
  25. data/dependencies/SDL_sound/libmodplug/load_mt2.c +36 -17
  26. data/dependencies/SDL_sound/libmodplug/load_okt.c +51 -24
  27. data/dependencies/SDL_sound/libmodplug/load_psm.c +4 -2
  28. data/dependencies/SDL_sound/libmodplug/load_s3m.c +4 -4
  29. data/dependencies/SDL_sound/libmodplug/load_ult.c +4 -3
  30. data/dependencies/SDL_sound/libmodplug/load_xm.c +5 -5
  31. data/dependencies/SDL_sound/libmodplug/snd_fx.c +8 -1
  32. data/dependencies/SDL_sound/libmodplug/sndfile.c +21 -4
  33. data/dependencies/SDL_sound/stb_vorbis.h +10 -18
  34. data/dependencies/mojoAL/mojoal.c +260 -6
  35. data/dependencies/stb/stb_image.h +208 -73
  36. data/dependencies/stb/stb_image_write.h +57 -23
  37. data/dependencies/stb/stb_truetype.h +345 -279
  38. data/dependencies/utf8proc/utf8proc.c +37 -18
  39. data/dependencies/utf8proc/utf8proc.h +17 -5
  40. data/dependencies/utf8proc/utf8proc_data.h +12012 -10089
  41. data/ext/gosu/extconf.rb +6 -3
  42. data/include/Gosu/Buttons.hpp +103 -103
  43. data/include/Gosu/Directories.hpp +31 -24
  44. data/include/Gosu/Font.hpp +4 -2
  45. data/include/Gosu/Gosu.hpp +5 -8
  46. data/include/Gosu/IO.hpp +0 -3
  47. data/include/Gosu/Input.hpp +7 -1
  48. data/include/Gosu/Math.hpp +0 -3
  49. data/include/Gosu/TextInput.hpp +3 -3
  50. data/include/Gosu/Timing.hpp +3 -6
  51. data/include/Gosu/Version.hpp +1 -1
  52. data/include/Gosu/Window.hpp +3 -2
  53. data/rdoc/gosu.rb +16 -2
  54. data/src/Audio.cpp +2 -2
  55. data/src/AudioFileAudioToolbox.cpp +1 -1
  56. data/src/AudioFileSDLSound.cpp +1 -1
  57. data/src/AudioImpl.cpp +0 -7
  58. data/src/AudioImpl.hpp +1 -3
  59. data/src/BitmapIO.cpp +23 -2
  60. data/src/BlockAllocator.cpp +1 -1
  61. data/src/DirectoriesApple.cpp +25 -24
  62. data/src/DirectoriesUnix.cpp +14 -12
  63. data/src/DirectoriesWin.cpp +26 -30
  64. data/src/FileUnix.cpp +1 -1
  65. data/src/FileWin.cpp +1 -1
  66. data/src/Font.cpp +13 -3
  67. data/src/Graphics.cpp +1 -1
  68. data/src/Image.cpp +10 -15
  69. data/src/Input.cpp +16 -1
  70. data/src/InputUIKit.cpp +1 -1
  71. data/src/Macro.cpp +1 -1
  72. data/src/RubyGosu.cxx +76 -34
  73. data/src/TextInput.cpp +1 -1
  74. data/src/TimingApple.cpp +2 -2
  75. data/src/TimingUnix.cpp +3 -7
  76. data/src/TimingWin.cpp +1 -2
  77. data/src/TrueTypeFont.cpp +1 -1
  78. data/src/Window.cpp +5 -4
  79. data/src/WindowUIKit.cpp +1 -1
  80. metadata +3 -3
@@ -8,6 +8,11 @@
8
8
  #include "libmodplug.h"
9
9
  #include <math.h>
10
10
 
11
+ #include "SDL_stdinc.h"
12
+ #if !(defined(HAVE_LIBC) && defined(__WATCOMC__)) /* Watcom has issues... */
13
+ #define floor SDL_floor
14
+ #endif
15
+
11
16
  /*
12
17
  *-----------------------------------------------------------------------------
13
18
  cubic spline interpolation doc,
@@ -16,7 +16,7 @@
16
16
  typedef struct tagFILEHEADER669
17
17
  {
18
18
  WORD sig; // 'if' or 'JN'
19
- signed char songmessage[108]; // Song Message
19
+ char songmessage[108]; // Song Message
20
20
  BYTE samples; // number of samples (1-64)
21
21
  BYTE patterns; // number of patterns (1-128)
22
22
  BYTE restartpos;
@@ -292,6 +292,7 @@ BOOL CSoundFile_ReadAMF(CSoundFile *_this, LPCBYTE lpStream, const DWORD dwMemLe
292
292
  // Setup sequence list
293
293
  for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
294
294
  {
295
+ if (dwMemPos + 4 > dwMemLength) return TRUE;
295
296
  _this->Order[iOrd] = 0xFF;
296
297
  if (iOrd < pfh->numorders)
297
298
  {
@@ -138,6 +138,13 @@ BOOL CSoundFile_ReadAMS(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
138
138
  while ((row < _this->PatternSize[iPat]) && (i+2 < len))
139
139
  {
140
140
  BYTE b0 = p[i++];
141
+
142
+ if (b0 == 0xff)
143
+ {
144
+ row++;
145
+ continue;
146
+ }
147
+
141
148
  BYTE b1 = p[i++];
142
149
  BYTE b2 = 0;
143
150
  UINT ch = b0 & 0x3F;
@@ -467,40 +474,49 @@ BOOL CSoundFile_ReadAMS2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
467
474
  {
468
475
  MODCOMMAND *m = _this->Patterns[ipat] + row * _this->m_nChannels;
469
476
  UINT byte1 = psrc[pos++];
477
+ UINT byte2;
470
478
  UINT ch = byte1 & 0x1F;
479
+ if (byte1 == 0xff)
480
+ {
481
+ row++;
482
+ continue;
483
+ }
484
+
471
485
  // Read Note + Instr
472
486
  if (!(byte1 & 0x40))
473
487
  {
474
- UINT byte2 = psrc[pos++];
488
+ byte2 = psrc[pos++];
475
489
  UINT note = byte2 & 0x7F;
476
490
  if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF;
477
491
  m[ch].instr = psrc[pos++];
478
- // Read Effect
479
- while (byte2 & 0x80)
492
+ } else {
493
+ byte2 = 0x80; /* row contains atleast one effect, so trigged the first parse */
494
+ }
495
+ // Read Effect
496
+ while (byte2 & 0x80)
497
+ {
498
+ byte2 = psrc[pos++];
499
+ if (byte2 & 0x40)
480
500
  {
481
- byte2 = psrc[pos++];
482
- if (byte2 & 0x40)
501
+ m[ch].volcmd = VOLCMD_VOLUME;
502
+ m[ch].vol = byte2 & 0x3F;
503
+ } else
504
+ {
505
+ UINT command = byte2 & 0x3F;
506
+ UINT param = psrc[pos++];
507
+ if (command == 0x0C)
483
508
  {
484
509
  m[ch].volcmd = VOLCMD_VOLUME;
485
- m[ch].vol = byte2 & 0x3F;
510
+ m[ch].vol = param / 2;
486
511
  } else
512
+ if (command < 0x10)
487
513
  {
488
- UINT command = byte2 & 0x3F;
489
- UINT param = psrc[pos++];
490
- if (command == 0x0C)
491
- {
492
- m[ch].volcmd = VOLCMD_VOLUME;
493
- m[ch].vol = param / 2;
494
- } else
495
- if (command < 0x10)
496
- {
497
- m[ch].command = command;
498
- m[ch].param = param;
499
- CSoundFile_ConvertModCommand(_this, &m[ch]);
500
- } else
501
- {
502
- // TODO: AMS effects
503
- }
514
+ m[ch].command = command;
515
+ m[ch].param = param;
516
+ CSoundFile_ConvertModCommand(_this, &m[ch]);
517
+ } else
518
+ {
519
+ // TODO: AMS effects
504
520
  }
505
521
  }
506
522
  }
@@ -393,16 +393,16 @@ BOOL CSoundFile_ReadIT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLengt
393
393
  if (pis.flags & 2)
394
394
  {
395
395
  flags += 5;
396
- if (pis.flags & 4) flags |= RSF_STEREO;
397
396
  pins->uFlags |= CHN_16BIT;
398
397
  // IT 2.14 16-bit packed sample ?
399
398
  if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416;
399
+ if (pis.flags & 4) flags |= RSF_STEREO;
400
400
  } else
401
401
  {
402
- if (pis.flags & 4) flags |= RSF_STEREO;
403
402
  if (pis.cvt == 0xFF) flags = RS_ADPCM4; else
404
403
  // IT 2.14 8-bit packed sample ?
405
404
  if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148;
405
+ if (pis.flags & 4) flags |= RSF_STEREO;
406
406
  }
407
407
  CSoundFile_ReadSample(_this, &_this->Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer);
408
408
  }
@@ -592,12 +592,13 @@ static DWORD ITReadBits(DWORD *bitbuf, UINT *bitnum, LPBYTE *_ibuf, LPBYTE ibufe
592
592
  }
593
593
 
594
594
  #define IT215_SUPPORT
595
- void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
596
- //-------------------------------------------------------------------------------------------
595
+ DWORD ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, DWORD channels, BOOL b215)
596
+ //-------------------------------------------------------------------------------------------------------------------
597
597
  {
598
598
  signed char *pDst = pSample;
599
599
  LPBYTE pSrc = lpMemFile;
600
600
  LPBYTE pStop = lpMemFile + dwMemLength;
601
+ DWORD writePos = 0;
601
602
  // DWORD wHdr = 0;
602
603
  DWORD wCount = 0;
603
604
  DWORD bitbuf = 0;
@@ -658,29 +659,31 @@ void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwM
658
659
  bTemp = (BYTE)wBits;
659
660
  bTemp2 += bTemp;
660
661
  #ifdef IT215_SUPPORT
661
- pDst[dwPos] = (b215) ? bTemp2 : bTemp;
662
+ pDst[writePos] = (b215) ? bTemp2 : bTemp;
662
663
  #else
663
- pDst[dwPos] = bTemp;
664
+ pDst[writePos] = bTemp;
664
665
  #endif
665
666
  SkipByte:
666
667
  dwPos++;
668
+ writePos += channels;
667
669
  Next:
668
- if (pSrc >= pStop + 1) return;
670
+ if (pSrc >= pStop + 1) return (DWORD)(pSrc - lpMemFile);
669
671
  } while (dwPos < d);
670
672
  // Move On
671
673
  wCount -= d;
672
674
  dwLen -= d;
673
- pDst += d;
674
675
  }
676
+ return (DWORD)(pSrc - lpMemFile);
675
677
  }
676
678
 
677
679
 
678
- void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
679
- //--------------------------------------------------------------------------------------------
680
+ DWORD ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, DWORD channels, BOOL b215)
681
+ //--------------------------------------------------------------------------------------------------------------------
680
682
  {
681
683
  signed short *pDst = (signed short *)pSample;
682
684
  LPBYTE pSrc = lpMemFile;
683
685
  LPBYTE pStop = lpMemFile + dwMemLength;
686
+ DWORD writePos = 0;
684
687
  // DWORD wHdr = 0;
685
688
  DWORD wCount = 0;
686
689
  DWORD bitbuf = 0;
@@ -742,21 +745,22 @@ void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dw
742
745
  wTemp = (signed short)dwBits;
743
746
  wTemp2 += wTemp;
744
747
  #ifdef IT215_SUPPORT
745
- pDst[dwPos] = (b215) ? wTemp2 : wTemp;
748
+ pDst[writePos] = (b215) ? wTemp2 : wTemp;
746
749
  #else
747
- pDst[dwPos] = wTemp;
750
+ pDst[writePos] = wTemp;
748
751
  #endif
749
752
  SkipByte:
750
753
  dwPos++;
754
+ writePos += channels;
751
755
  Next:
752
- if (pSrc >= pStop + 1) return;
756
+ if (pSrc >= pStop + 1) return (DWORD)(pSrc - lpMemFile);
753
757
  } while (dwPos < d);
754
758
  // Move On
755
759
  wCount -= d;
756
760
  dwLen -= d;
757
- pDst += d;
758
761
  if (pSrc >= pStop) break;
759
762
  }
763
+ return (DWORD)(pSrc - lpMemFile);
760
764
  }
761
765
 
762
766
  UINT CSoundFile_LoadMixPlugins(CSoundFile *_this, const void *pData, UINT nLen)
@@ -122,17 +122,17 @@ static void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTr
122
122
 
123
123
  case 0x03:
124
124
  {
125
- cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0;
126
- cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0;
125
+ cmd.note = (xx & 0x01) ? (pos < len ? lpTracks[pos++] : 0) : 0;
126
+ cmd.instr = (xx & 0x02) ? (pos < len ? lpTracks[pos++] : 0) : 0;
127
127
  cmd.volcmd = cmd.vol = 0;
128
128
  cmd.command = cmd.param = 0;
129
129
  if ((cmd.note < NOTE_MAX-12) && (cmd.note)) cmd.note += 12;
130
- UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0;
131
- UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0;
130
+ UINT volume = (xx & 0x04) ? (pos < len ? lpTracks[pos++] : 0) : 0;
131
+ UINT commands = (xx & 0x08) ? (pos < len ? lpTracks[pos++] : 0) : 0;
132
132
  UINT command1 = commands & 0x0F;
133
133
  UINT command2 = commands & 0xF0;
134
- UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0;
135
- UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0;
134
+ UINT param1 = (xx & 0x10) ? (pos < len ? lpTracks[pos++] : 0) : 0;
135
+ UINT param2 = (xx & 0x20) ? (pos < len ? lpTracks[pos++] : 0) : 0;
136
136
  if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2))
137
137
  {
138
138
  param1 = ((param1 & 0x0F) << 8) | param2;
@@ -208,6 +208,7 @@ BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
208
208
  {
209
209
  // IN: infoblock
210
210
  case 0x4E49:
211
+ if (blocklen < sizeof(MDLINFOBLOCK)) break;
211
212
  pmib = (const MDLINFOBLOCK *)(lpStream+dwMemPos);
212
213
  norders = pmib->norders;
213
214
  if (norders > MAX_ORDERS) norders = MAX_ORDERS;
@@ -263,6 +264,7 @@ BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
263
264
  break;
264
265
  // TR: Track Data
265
266
  case 0x5254:
267
+ if (blocklen < 2) break;
266
268
  if (dwTrackPos) break;
267
269
  pp = lpStream + dwMemPos;
268
270
  ntracks = pp[0] | (pp[1] << 8);
@@ -272,7 +274,9 @@ BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
272
274
  case 0x4949:
273
275
  ninstruments = lpStream[dwMemPos];
274
276
  dwPos = dwMemPos+1;
275
- for (i=0; dwPos+34<dwMemLength && i<ninstruments; i++)
277
+ if (blocklen < sizeof(INSTRUMENTHEADER)*ninstruments + 1) break;
278
+
279
+ for (i=0; i<ninstruments; i++)
276
280
  {
277
281
  UINT nins = lpStream[dwPos];
278
282
  if ((nins >= MAX_INSTRUMENTS) || (!nins)) break;
@@ -282,6 +286,7 @@ BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
282
286
  UINT note = 12;
283
287
  if ((_this->Headers[nins] = (INSTRUMENTHEADER *) SDL_calloc(1, sizeof (INSTRUMENTHEADER))) == NULL) break;
284
288
  INSTRUMENTHEADER *penv = _this->Headers[nins];
289
+ if (dwPos > dwMemLength - 34) break;
285
290
  penv->nGlobalVol = 64;
286
291
  penv->nPPC = 5*12;
287
292
  if (34 + 14u*lpStream[dwPos+1] > dwMemLength - dwPos) break;
@@ -321,6 +326,7 @@ BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
321
326
  }
322
327
  }
323
328
  dwPos += 34 + 14*lpStream[dwPos+1];
329
+ if (dwPos > dwMemLength - 2) break;
324
330
  }
325
331
  for (j=1; j<=_this->m_nInstruments; j++) if (!_this->Headers[j])
326
332
  {
@@ -412,13 +418,16 @@ BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
412
418
  for (UINT chn=0; chn<_this->m_nChannels; chn++) if ((patterntracks[ipat*32+chn]) && (patterntracks[ipat*32+chn] <= ntracks))
413
419
  {
414
420
  const BYTE *lpTracks = lpStream + dwTrackPos;
415
- UINT len = lpTracks[0] | (lpTracks[1] << 8);
421
+ UINT len = 0;
422
+ if (dwTrackPos + 2 < dwMemLength)
423
+ len = lpTracks[0] | (lpTracks[1] << 8);
424
+
416
425
  if (len < dwMemLength-dwTrackPos) {
417
426
  MODCOMMAND *m = _this->Patterns[ipat] + chn;
418
427
  UINT nTrack = patterntracks[ipat*32+chn];
419
428
 
420
429
  lpTracks += 2;
421
- for (UINT ntrk=1; ntrk<nTrack && lpTracks + 1 < (dwMemLength + lpStream - len); ntrk++)
430
+ for (UINT ntrk=1; ntrk<nTrack && lpTracks < (dwMemLength + lpStream - len - 2); ntrk++)
422
431
  {
423
432
  lpTracks += len;
424
433
  len = lpTracks[0] | (lpTracks[1] << 8);
@@ -575,8 +575,8 @@ BOOL CSoundFile_ReadMed(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
575
575
  nSections = 0;
576
576
  }
577
577
  UINT pseq = 0;
578
-
579
- if ((playseqtable) && (playseqtable < dwMemLength) && (nplayseq*4 + 4 < dwMemLength - playseqtable))
578
+
579
+ if ((playseqtable) && (playseqtable < dwMemLength - 4) && ((nplayseq+1)*4 < dwMemLength - playseqtable))
580
580
  {
581
581
  pseq = bswapBE32(((LPDWORD)(lpStream+playseqtable))[nplayseq]);
582
582
  }
@@ -624,11 +624,12 @@ BOOL CSoundFile_ReadMed(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
624
624
  UINT len = bswapBE32(psdh->length);
625
625
  if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0;
626
626
  UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type);
627
- dwPos += 6;
627
+ LPSTR psdata = (LPSTR)(lpStream + dwPos + 6);
628
+ UINT bLimit = dwMemLength - dwPos - 6;
628
629
  if (stype & 0x80)
629
630
  {
630
- dwPos += (stype & 0x20) ? 14 : 6;
631
- if (dwPos >= dwMemLength) continue;
631
+ psdata += (stype & 0x20) ? 14 : 6;
632
+ bLimit -= (stype & 0x20) ? 14 : 6;
632
633
  } else
633
634
  {
634
635
  if (stype & 0x10)
@@ -643,7 +644,7 @@ BOOL CSoundFile_ReadMed(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
643
644
  if (stype & 0x20) len /= 2;
644
645
  }
645
646
  _this->Ins[iSmp+1].nLength = len;
646
- CSoundFile_ReadSample(_this, &_this->Ins[iSmp+1], flags, (const char *)(lpStream + dwPos), dwMemLength - dwPos);
647
+ CSoundFile_ReadSample(_this, &_this->Ins[iSmp+1], flags, psdata, bLimit);
647
648
  }
648
649
  // Reading patterns (blocks)
649
650
  if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS;
@@ -122,6 +122,19 @@ typedef struct _MT2GROUP
122
122
  #pragma pack()
123
123
 
124
124
 
125
+ static int calcNumOnes(int number) {
126
+ int cnt = 0;
127
+
128
+ while(number)
129
+ {
130
+ number &= (number -1);
131
+ cnt ++;
132
+ }
133
+
134
+ return(cnt);
135
+ }
136
+
137
+
125
138
  static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, const MT2COMMAND *p)
126
139
  //---------------------------------------------------------------------------
127
140
  {
@@ -188,7 +201,7 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
188
201
  const MT2INSTRUMENT *InstrMap[255];
189
202
  const MT2SAMPLE *SampleMap[256];
190
203
 
191
- if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER))
204
+ if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER) + 4)
192
205
  || (pfh->dwMT20 != 0x3032544D)
193
206
  || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300)
194
207
  || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE;
@@ -246,6 +259,7 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
246
259
  UINT wDataLen = (pmp->wDataLen + 1) & ~1;
247
260
  dwMemPos += 6;
248
261
  if (dwMemPos > dwMemLength - wDataLen || wDataLen > dwMemLength) break;
262
+
249
263
  UINT nLines = pmp->wLines;
250
264
  if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256))
251
265
  {
@@ -254,11 +268,13 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
254
268
  if (!_this->Patterns[iPat]) return TRUE;
255
269
  MODCOMMAND *m = _this->Patterns[iPat];
256
270
  UINT len = wDataLen;
271
+ if (len <= 4) return TRUE;
272
+
257
273
  if (pfh->fulFlags & 1) // Packed Patterns
258
274
  {
259
275
  const BYTE *p = lpStream+dwMemPos;
260
276
  UINT pos = 0, row=0, ch=0;
261
- while (pos < len)
277
+ while (pos < len - 4)
262
278
  {
263
279
  MT2COMMAND cmd;
264
280
  UINT infobyte = p[pos++];
@@ -273,13 +289,14 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
273
289
  {
274
290
  UINT patpos = row*_this->m_nChannels+ch;
275
291
  cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0;
276
- if ((infobyte & 1) && (pos < len)) cmd.note = p[pos++];
277
- if ((infobyte & 2) && (pos < len)) cmd.instr = p[pos++];
278
- if ((infobyte & 4) && (pos < len)) cmd.vol = p[pos++];
279
- if ((infobyte & 8) && (pos < len)) cmd.pan = p[pos++];
280
- if ((infobyte & 16) && (pos < len)) cmd.fxcmd = p[pos++];
281
- if ((infobyte & 32) && (pos < len)) cmd.fxparam1 = p[pos++];
282
- if ((infobyte & 64) && (pos < len)) cmd.fxparam2 = p[pos++];
292
+ if (pos >= len - calcNumOnes(infobyte & 0x7F)) break;
293
+ if (infobyte & 1) cmd.note = p[pos++];
294
+ if (infobyte & 2) cmd.instr = p[pos++];
295
+ if (infobyte & 4) cmd.vol = p[pos++];
296
+ if (infobyte & 8) cmd.pan = p[pos++];
297
+ if (infobyte & 16) cmd.fxcmd = p[pos++];
298
+ if (infobyte & 32) cmd.fxparam1 = p[pos++];
299
+ if (infobyte & 64) cmd.fxparam2 = p[pos++];
283
300
  ConvertMT2Command(_this, &m[patpos], &cmd);
284
301
  }
285
302
  row += rptcount+1;
@@ -361,7 +378,7 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
361
378
  {
362
379
  if (dwMemPos + sizeof(MT2INSTRUMENT) - 4 > dwMemLength) return TRUE;
363
380
  InstrMap[iIns-1] = pmi;
364
- if (penv)
381
+ if (penv && pmi->dwDataLen >= sizeof(MT2INSTRUMENT) - 40)
365
382
  {
366
383
  penv->nFadeOut = pmi->wFadeOut;
367
384
  penv->nNNA = pmi->wNNA & 3;
@@ -397,6 +414,10 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
397
414
  pedata[i] = NULL;
398
415
  }
399
416
  }
417
+
418
+ // envelopes exceed file length?
419
+ if (dwEnvPos > dwMemLength) return TRUE;
420
+
400
421
  }
401
422
  // Load envelopes
402
423
  for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv])
@@ -467,7 +488,7 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
467
488
  _this->m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1;
468
489
  for (UINT iSmp=1; iSmp<=256; iSmp++)
469
490
  {
470
- if (dwMemPos+36 > dwMemLength) return TRUE;
491
+ if (dwMemPos > dwMemLength - 36) return TRUE;
471
492
  const MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos);
472
493
  if (pms->dwDataLen > dwMemLength - (dwMemPos+36)) return TRUE;
473
494
  if (pms->dwDataLen > 0)
@@ -505,8 +526,7 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
505
526
  if (iMap<_this->m_nInstruments) penv = _this->Headers[iMap+1];
506
527
  for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++)
507
528
  {
508
- if (dwMemPos+8 > dwMemLength) return TRUE;
509
- if (penv)
529
+ if (penv && dwMemPos < dwMemLength && dwMemPos < dwMemLength - 8)
510
530
  {
511
531
  const MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos);
512
532
  for (UINT i=0; i<96; i++)
@@ -537,7 +557,7 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
537
557
  if (psmp->nLength > 0 && dwMemPos < dwMemLength)
538
558
  {
539
559
  UINT rsflags;
540
-
560
+
541
561
  if (pms->nChannels == 2)
542
562
  rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
543
563
  else
@@ -546,13 +566,12 @@ BOOL CSoundFile_ReadMT2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
546
566
  dwMemPos += CSoundFile_ReadSample(_this, psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
547
567
  }
548
568
  } else
549
- if (dwMemPos+4 < dwMemLength)
569
+ if (dwMemPos < dwMemLength-4)
550
570
  {
551
571
  UINT nNameLen = *(DWORD *)(lpStream+dwMemPos);
552
572
  dwMemPos += nNameLen + 16;
553
573
  }
554
- if (dwMemPos+4 >= dwMemLength) break;
574
+ if (dwMemPos >= dwMemLength-4) break;
555
575
  }
556
576
  return TRUE;
557
577
  }
558
-
@@ -10,18 +10,20 @@
10
10
  //////////////////////////////////////////////
11
11
  #include "libmodplug.h"
12
12
 
13
+ #define MAGIC(a,b,c,d) (((a) << 24UL) | ((b) << 16UL) | ((c) << 8UL) | (d))
14
+
15
+ #pragma pack(1)
13
16
  typedef struct OKTFILEHEADER
14
17
  {
15
18
  DWORD okta; // "OKTA"
16
19
  DWORD song; // "SONG"
17
20
  DWORD cmod; // "CMOD"
18
- DWORD fixed8;
21
+ DWORD cmodlen;
19
22
  BYTE chnsetup[8];
20
23
  DWORD samp; // "SAMP"
21
24
  DWORD samplen;
22
25
  } OKTFILEHEADER;
23
26
 
24
-
25
27
  typedef struct OKTSAMPLE
26
28
  {
27
29
  CHAR name[20];
@@ -33,20 +35,29 @@ typedef struct OKTSAMPLE
33
35
  BYTE pad2;
34
36
  BYTE pad3;
35
37
  } OKTSAMPLE;
38
+ #pragma pack()
39
+
36
40
 
41
+ static DWORD readBE32(const BYTE *v)
42
+ {
43
+ return (v[0] << 24UL) | (v[1] << 16UL) | (v[2] << 8UL) | v[3];
44
+ }
37
45
 
38
46
  BOOL CSoundFile_ReadOKT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength)
39
47
  //---------------------------------------------------------------
40
48
  {
41
49
  const OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream;
42
- DWORD dwMemPos = sizeof(OKTFILEHEADER);
50
+ DWORD dwMemPos = sizeof(OKTFILEHEADER), dwSize;
43
51
  UINT nsamples = 0, norders = 0;//, npatterns = 0
44
52
 
45
53
  if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
46
- if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53)
47
- || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2])
48
- || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000)
49
- || (pfh->samp != 0x504D4153)) return FALSE;
54
+ if ((bswapBE32(pfh->okta) != MAGIC('O','K','T','A'))
55
+ || (bswapBE32(pfh->song) != MAGIC('S','O','N','G'))
56
+ || (bswapBE32(pfh->cmod) != MAGIC('C','M','O','D'))
57
+ || (bswapBE32(pfh->cmodlen) != 8)
58
+ || (pfh->chnsetup[0]) || (pfh->chnsetup[2])
59
+ || (pfh->chnsetup[4]) || (pfh->chnsetup[6])
60
+ || (bswapBE32(pfh->samp) != MAGIC('S','A','M','P'))) return FALSE;
50
61
  _this->m_nType = MOD_TYPE_OKT;
51
62
  _this->m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7];
52
63
  if (_this->m_nChannels > MAX_CHANNELS) _this->m_nChannels = MAX_CHANNELS;
@@ -56,10 +67,10 @@ BOOL CSoundFile_ReadOKT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
56
67
  // Reading samples
57
68
  for (UINT smp=1; smp <= nsamples; smp++)
58
69
  {
59
- if (dwMemPos + sizeof(OKTSAMPLE) >= dwMemLength) return TRUE;
70
+ if (dwMemPos >= dwMemLength - sizeof(OKTSAMPLE)) return TRUE;
60
71
  if (smp < MAX_SAMPLES)
61
72
  {
62
- OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos);
73
+ const OKTSAMPLE *psmp = (const OKTSAMPLE *)(lpStream + dwMemPos);
63
74
  MODINSTRUMENT *pins = &_this->Ins[smp];
64
75
 
65
76
  pins->uFlags = 0;
@@ -74,42 +85,52 @@ BOOL CSoundFile_ReadOKT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
74
85
  dwMemPos += sizeof(OKTSAMPLE);
75
86
  }
76
87
  // SPEE
77
- if (dwMemPos + 10 > dwMemLength) return TRUE;
78
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053)
88
+ if (dwMemPos >= dwMemLength - 12) return TRUE;
89
+ if (readBE32(lpStream + dwMemPos) == MAGIC('S','P','E','E'))
79
90
  {
80
91
  _this->m_nDefaultSpeed = lpStream[dwMemPos+9];
81
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
92
+
93
+ dwSize = readBE32(lpStream + dwMemPos + 4);
94
+ if (dwSize > dwMemLength - 8 || dwMemPos > dwMemLength - dwSize - 8) return TRUE;
95
+ dwMemPos += dwSize + 8;
82
96
  }
83
97
  // SLEN
84
98
  if (dwMemPos + 10 > dwMemLength) return TRUE;
85
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53)
99
+ if (readBE32(lpStream + dwMemPos) == MAGIC('S','L','E','N'))
86
100
  {
87
- if (dwMemPos + 10 > dwMemLength) return TRUE;
88
101
  // npatterns = lpStream[dwMemPos+9];
89
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
102
+
103
+ dwSize = readBE32(lpStream + dwMemPos + 4);
104
+ if (dwSize > dwMemLength - 8 || dwMemPos > dwMemLength - dwSize - 8) return TRUE;
105
+ dwMemPos += dwSize + 8;
90
106
  }
91
107
  // PLEN
92
108
  if (dwMemPos + 10 > dwMemLength) return TRUE;
93
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50)
109
+ if (readBE32(lpStream + dwMemPos) == MAGIC('P','L','E','N'))
94
110
  {
95
- if (dwMemPos + 10 > dwMemLength) return TRUE;
96
111
  norders = lpStream[dwMemPos+9];
97
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
112
+
113
+ dwSize = readBE32(lpStream + dwMemPos + 4);
114
+ if (dwSize > dwMemLength - 8 || dwMemPos > dwMemLength - dwSize - 8) return TRUE;
115
+ dwMemPos += dwSize + 8;
98
116
  }
99
117
  // PATT
100
118
  if (dwMemPos + 8 > dwMemLength) return TRUE;
101
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150)
119
+ if (readBE32(lpStream + dwMemPos) == MAGIC('P','A','T','T'))
102
120
  {
103
121
  UINT orderlen = norders;
104
122
  if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1;
105
123
  if (dwMemPos + 8 + orderlen > dwMemLength) return TRUE;
106
124
  for (UINT i=0; i<orderlen; i++) _this->Order[i] = lpStream[dwMemPos+8+i];
107
125
  for (UINT j=orderlen; j>1; j--) { if (_this->Order[j-1]) break; _this->Order[j-1] = 0xFF; }
108
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
126
+
127
+ dwSize = readBE32(lpStream + dwMemPos + 4);
128
+ if (dwSize > dwMemLength - 8 || dwMemPos > dwMemLength - dwSize - 8) return TRUE;
129
+ dwMemPos += dwSize + 8;
109
130
  }
110
131
  // PBOD
111
132
  UINT npat = 0;
112
- while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250))
133
+ while ((dwMemPos < dwMemLength - 10) && (readBE32(lpStream + dwMemPos) == MAGIC('P','B','O','D')))
113
134
  {
114
135
  DWORD dwPos = dwMemPos + 10;
115
136
  UINT rows = lpStream[dwMemPos+9];
@@ -181,15 +202,21 @@ BOOL CSoundFile_ReadOKT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
181
202
  }
182
203
  }
183
204
  npat++;
184
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
205
+
206
+ dwSize = readBE32(lpStream + dwMemPos + 4);
207
+ if (dwSize > dwMemLength - 8 || dwMemPos > dwMemLength - dwSize - 8) return TRUE;
208
+ dwMemPos += dwSize + 8;
185
209
  }
186
210
  // SBOD
187
211
  UINT nsmp = 1;
188
- while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253))
212
+ while ((dwMemPos < dwMemLength-10) && (readBE32(lpStream + dwMemPos) == MAGIC('S','B','O','D')))
189
213
  {
190
214
  if (nsmp < MAX_SAMPLES) CSoundFile_ReadSample(_this, &_this->Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8);
191
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
192
215
  nsmp++;
216
+
217
+ dwSize = readBE32(lpStream + dwMemPos + 4);
218
+ if (dwSize > dwMemLength - 8 || dwMemPos > dwMemLength - dwSize - 8) return TRUE;
219
+ dwMemPos += dwSize + 8;
193
220
  }
194
221
  return TRUE;
195
222
  }
@@ -100,7 +100,7 @@ BOOL CSoundFile_ReadPSM(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
100
100
  // DWORD smpnames[MAX_SAMPLES];
101
101
  DWORD patptrs[MAX_PATTERNS];
102
102
  BYTE samplemap[MAX_SAMPLES];
103
- UINT nPatterns;
103
+ UINT nPatterns = 0;
104
104
 
105
105
  if (dwMemLength < 256) return FALSE;
106
106
 
@@ -309,8 +309,10 @@ BOOL CSoundFile_ReadPSM(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
309
309
  if ((flags & 0x40) && (pos+1 < len))
310
310
  {
311
311
  UINT nins = p[pos++];
312
- if (nins < MAX_SAMPLES)
312
+ if (nins >= _this->m_nSamples) {
313
+ } else {
313
314
  sp->instr = samplemap[nins];
315
+ }
314
316
  }
315
317
  // Volume
316
318
  if ((flags & 0x20) && (pos < len))