gosu 1.4.1 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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))