gosu 0.15.2 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL/include/SDL.h +138 -0
  3. data/dependencies/SDL/include/SDL_assert.h +293 -0
  4. data/dependencies/SDL/include/SDL_atomic.h +295 -0
  5. data/dependencies/SDL/include/SDL_audio.h +859 -0
  6. data/dependencies/SDL/include/SDL_bits.h +121 -0
  7. data/dependencies/SDL/include/SDL_blendmode.h +123 -0
  8. data/dependencies/SDL/include/SDL_clipboard.h +71 -0
  9. data/dependencies/SDL/include/SDL_config.h +55 -0
  10. data/dependencies/SDL/include/SDL_config_android.h +182 -0
  11. data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
  12. data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
  13. data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
  14. data/dependencies/SDL/include/SDL_config_os2.h +188 -0
  15. data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
  16. data/dependencies/SDL/include/SDL_config_psp.h +165 -0
  17. data/dependencies/SDL/include/SDL_config_windows.h +288 -0
  18. data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
  19. data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
  20. data/dependencies/SDL/include/SDL_copying.h +20 -0
  21. data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
  22. data/dependencies/SDL/include/SDL_egl.h +1676 -0
  23. data/dependencies/SDL/include/SDL_endian.h +263 -0
  24. data/dependencies/SDL/include/SDL_error.h +112 -0
  25. data/dependencies/SDL/include/SDL_events.h +827 -0
  26. data/dependencies/SDL/include/SDL_filesystem.h +136 -0
  27. data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
  28. data/dependencies/SDL/include/SDL_gesture.h +87 -0
  29. data/dependencies/SDL/include/SDL_haptic.h +1247 -0
  30. data/dependencies/SDL/include/SDL_hints.h +1578 -0
  31. data/dependencies/SDL/include/SDL_joystick.h +499 -0
  32. data/dependencies/SDL/include/SDL_keyboard.h +217 -0
  33. data/dependencies/SDL/include/SDL_keycode.h +351 -0
  34. data/dependencies/SDL/include/SDL_loadso.h +81 -0
  35. data/dependencies/SDL/include/SDL_locale.h +101 -0
  36. data/dependencies/SDL/include/SDL_log.h +211 -0
  37. data/dependencies/SDL/include/SDL_main.h +180 -0
  38. data/dependencies/SDL/include/SDL_messagebox.h +146 -0
  39. data/dependencies/SDL/include/SDL_metal.h +117 -0
  40. data/dependencies/SDL/include/SDL_misc.h +75 -0
  41. data/dependencies/SDL/include/SDL_mouse.h +302 -0
  42. data/dependencies/SDL/include/SDL_mutex.h +251 -0
  43. data/dependencies/SDL/include/SDL_name.h +33 -0
  44. data/dependencies/SDL/include/SDL_opengl.h +2183 -0
  45. data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
  46. data/dependencies/SDL/include/SDL_opengles.h +39 -0
  47. data/dependencies/SDL/include/SDL_opengles2.h +52 -0
  48. data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
  49. data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
  50. data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
  51. data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
  52. data/dependencies/SDL/include/SDL_pixels.h +479 -0
  53. data/dependencies/SDL/include/SDL_platform.h +198 -0
  54. data/dependencies/SDL/include/SDL_power.h +75 -0
  55. data/dependencies/SDL/include/SDL_quit.h +58 -0
  56. data/dependencies/SDL/include/SDL_rect.h +174 -0
  57. data/dependencies/SDL/include/SDL_render.h +1158 -0
  58. data/dependencies/SDL/include/SDL_revision.h +2 -0
  59. data/dependencies/SDL/include/SDL_rwops.h +283 -0
  60. data/dependencies/SDL/include/SDL_scancode.h +413 -0
  61. data/dependencies/SDL/include/SDL_sensor.h +267 -0
  62. data/dependencies/SDL/include/SDL_shape.h +144 -0
  63. data/dependencies/SDL/include/SDL_stdinc.h +647 -0
  64. data/dependencies/SDL/include/SDL_surface.h +563 -0
  65. data/dependencies/SDL/include/SDL_system.h +325 -0
  66. data/dependencies/SDL/include/SDL_syswm.h +354 -0
  67. data/dependencies/SDL/include/SDL_test.h +69 -0
  68. data/dependencies/SDL/include/SDL_test_assert.h +105 -0
  69. data/dependencies/SDL/include/SDL_test_common.h +218 -0
  70. data/dependencies/SDL/include/SDL_test_compare.h +69 -0
  71. data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
  72. data/dependencies/SDL/include/SDL_test_font.h +81 -0
  73. data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
  74. data/dependencies/SDL/include/SDL_test_harness.h +134 -0
  75. data/dependencies/SDL/include/SDL_test_images.h +78 -0
  76. data/dependencies/SDL/include/SDL_test_log.h +67 -0
  77. data/dependencies/SDL/include/SDL_test_md5.h +129 -0
  78. data/dependencies/SDL/include/SDL_test_memory.h +63 -0
  79. data/dependencies/SDL/include/SDL_test_random.h +115 -0
  80. data/dependencies/SDL/include/SDL_thread.h +366 -0
  81. data/dependencies/SDL/include/SDL_timer.h +115 -0
  82. data/dependencies/SDL/include/SDL_touch.h +102 -0
  83. data/dependencies/SDL/include/SDL_types.h +29 -0
  84. data/dependencies/SDL/include/SDL_version.h +162 -0
  85. data/dependencies/SDL/include/SDL_video.h +1282 -0
  86. data/dependencies/SDL/include/SDL_vulkan.h +276 -0
  87. data/dependencies/SDL/include/begin_code.h +166 -0
  88. data/dependencies/SDL/include/close_code.h +40 -0
  89. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  90. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  91. data/dependencies/SDL_sound/SDL_sound.c +795 -0
  92. data/dependencies/SDL_sound/SDL_sound.h +725 -0
  93. data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
  94. data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
  95. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
  96. data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
  97. data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
  98. data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
  99. data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
  100. data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
  101. data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
  102. data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
  103. data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
  104. data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
  105. data/dependencies/SDL_sound/dr_flac.h +5906 -0
  106. data/dependencies/SDL_sound/dr_mp3.h +2832 -0
  107. data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
  108. data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
  109. data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
  110. data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
  111. data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
  112. data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
  113. data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
  114. data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
  115. data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
  116. data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
  117. data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
  118. data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
  119. data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
  120. data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
  121. data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
  122. data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
  123. data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
  124. data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
  125. data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
  126. data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
  127. data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
  128. data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
  129. data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
  130. data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
  131. data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
  132. data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
  133. data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
  134. data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
  135. data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
  136. data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
  137. data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
  138. data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
  139. data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
  140. data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
  141. data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
  142. data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
  143. data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
  144. data/dependencies/al_soft/AL/al.h +655 -0
  145. data/dependencies/al_soft/AL/alc.h +270 -0
  146. data/dependencies/al_soft/AL/alext.h +585 -0
  147. data/dependencies/al_soft/AL/efx-creative.h +3 -0
  148. data/dependencies/al_soft/AL/efx-presets.h +402 -0
  149. data/dependencies/al_soft/AL/efx.h +762 -0
  150. data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
  151. data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
  152. data/{src → dependencies/stb}/stb_image.h +330 -127
  153. data/{src → dependencies/stb}/stb_image_write.h +156 -85
  154. data/{src → dependencies/stb}/stb_truetype.h +192 -69
  155. data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
  156. data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
  157. data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
  158. data/ext/gosu/extconf.rb +56 -22
  159. data/{Gosu → include/Gosu}/Audio.hpp +6 -8
  160. data/{Gosu → include/Gosu}/AutoLink.hpp +0 -0
  161. data/include/Gosu/Bitmap.hpp +100 -0
  162. data/{Gosu → include/Gosu}/Buttons.hpp +94 -35
  163. data/{Gosu → include/Gosu}/Channel.h +0 -0
  164. data/{Gosu → include/Gosu}/Color.h +0 -0
  165. data/{Gosu → include/Gosu}/Color.hpp +0 -0
  166. data/{Gosu → include/Gosu}/Directories.hpp +0 -0
  167. data/{Gosu → include/Gosu}/Font.h +0 -0
  168. data/{Gosu → include/Gosu}/Font.hpp +0 -0
  169. data/{Gosu → include/Gosu}/Fwd.hpp +0 -0
  170. data/{Gosu → include/Gosu}/Gosu.h +3 -0
  171. data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
  172. data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
  173. data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
  174. data/{Gosu → include/Gosu}/IO.hpp +0 -0
  175. data/{Gosu → include/Gosu}/Image.h +0 -0
  176. data/{Gosu → include/Gosu}/Image.hpp +7 -6
  177. data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
  178. data/{Gosu → include/Gosu}/Input.hpp +30 -15
  179. data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
  180. data/{Gosu → include/Gosu}/Math.hpp +0 -0
  181. data/{Gosu → include/Gosu}/Platform.hpp +0 -0
  182. data/{Gosu → include/Gosu}/Sample.h +0 -0
  183. data/{Gosu → include/Gosu}/Song.h +0 -0
  184. data/{Gosu → include/Gosu}/Text.hpp +0 -0
  185. data/{Gosu → include/Gosu}/TextInput.h +0 -0
  186. data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
  187. data/{Gosu → include/Gosu}/Timing.hpp +0 -0
  188. data/{Gosu → include/Gosu}/Utility.hpp +1 -1
  189. data/{Gosu → include/Gosu}/Version.hpp +0 -0
  190. data/{Gosu → include/Gosu}/Window.h +2 -0
  191. data/{Gosu → include/Gosu}/Window.hpp +21 -13
  192. data/lib/OpenAL32.dll +0 -0
  193. data/lib/SDL2.dll +0 -0
  194. data/lib/gosu.rb +0 -3
  195. data/lib/gosu/patches.rb +0 -9
  196. data/lib/gosu/swig_patches.rb +3 -2
  197. data/lib/libmpg123.dll +0 -0
  198. data/lib/libsndfile.dll +0 -0
  199. data/lib64/OpenAL32.dll +0 -0
  200. data/lib64/SDL2.dll +0 -0
  201. data/lib64/libmpg123.dll +0 -0
  202. data/lib64/libsndfile.dll +0 -0
  203. data/rdoc/gosu.rb +95 -20
  204. data/src/Audio.cpp +50 -224
  205. data/src/AudioFile.hpp +17 -37
  206. data/src/AudioFileAudioToolbox.cpp +237 -0
  207. data/src/AudioFileSDLSound.cpp +147 -0
  208. data/src/AudioImpl.cpp +3 -12
  209. data/src/AudioImpl.hpp +3 -1
  210. data/src/Bitmap.cpp +85 -83
  211. data/src/BitmapIO.cpp +52 -58
  212. data/src/Constants.cpp +80 -33
  213. data/src/Font.cpp +3 -1
  214. data/src/GosuWrapper.cpp +19 -0
  215. data/src/Graphics.cpp +7 -4
  216. data/src/Image.cpp +13 -16
  217. data/src/Input.cpp +408 -159
  218. data/src/LargeImageData.cpp +1 -1
  219. data/src/MarkupParser.cpp +2 -1
  220. data/src/RubyGosu.cxx +349 -83
  221. data/src/RubyGosu.h +4 -2
  222. data/src/TexChunk.cpp +1 -1
  223. data/src/TextBuilder.cpp +3 -1
  224. data/src/Texture.cpp +1 -1
  225. data/src/TrueTypeFont.cpp +1 -1
  226. data/src/Utility.cpp +11 -7
  227. data/src/Window.cpp +30 -39
  228. data/src/WindowWrapper.cpp +28 -0
  229. metadata +207 -52
  230. data/Gosu/Bitmap.hpp +0 -113
  231. data/src/AudioToolboxFile.hpp +0 -210
  232. data/src/OggFile.hpp +0 -92
  233. data/src/SndFile.hpp +0 -174
  234. data/src/WinMain.cpp +0 -64
@@ -0,0 +1,142 @@
1
+ /*
2
+ * This source code is public domain.
3
+ *
4
+ * Authors: Olivier Lapicque <olivierl@jps.net>
5
+ */
6
+
7
+ #include "libmodplug.h"
8
+
9
+ //////////////////////////////////////////////////////////
10
+ // MTM file support (import only)
11
+
12
+ #pragma pack(1)
13
+
14
+ typedef struct tagMTMSAMPLE
15
+ {
16
+ char samplename[22]; // changed from CHAR
17
+ DWORD length;
18
+ DWORD reppos;
19
+ DWORD repend;
20
+ CHAR finetune;
21
+ BYTE volume;
22
+ BYTE attribute;
23
+ } MTMSAMPLE;
24
+
25
+
26
+ typedef struct tagMTMHEADER
27
+ {
28
+ char id[4]; // MTM file marker + version // changed from CHAR
29
+ char songname[20]; // ASCIIZ songname // changed from CHAR
30
+ WORD numtracks; // number of tracks saved
31
+ BYTE lastpattern; // last pattern number saved
32
+ BYTE lastorder; // last order number to play (songlength-1)
33
+ WORD commentsize; // length of comment field
34
+ BYTE numsamples; // number of samples saved
35
+ BYTE attribute; // attribute byte (unused)
36
+ BYTE beatspertrack;
37
+ BYTE numchannels; // number of channels used
38
+ BYTE panpos[32]; // voice pan positions
39
+ } MTMHEADER;
40
+
41
+ #pragma pack()
42
+
43
+
44
+ BOOL CSoundFile_ReadMTM(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
45
+ //-----------------------------------------------------------
46
+ {
47
+ MTMHEADER *pmh = (MTMHEADER *)lpStream;
48
+ DWORD dwMemPos = 66;
49
+
50
+ if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
51
+ if ((SDL_strncmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32)
52
+ || (pmh->numsamples >= MAX_SAMPLES) || (!pmh->numsamples)
53
+ || (!pmh->numtracks) || (!pmh->numchannels)
54
+ || (!pmh->lastpattern) || (pmh->lastpattern >= MAX_PATTERNS))
55
+ return FALSE;
56
+ if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks
57
+ + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength)
58
+ return FALSE;
59
+ _this->m_nType = MOD_TYPE_MTM;
60
+ _this->m_nSamples = pmh->numsamples;
61
+ _this->m_nChannels = pmh->numchannels;
62
+ // Reading instruments
63
+ for (UINT i=1; i<=_this->m_nSamples; i++)
64
+ {
65
+ MTMSAMPLE *pms = (MTMSAMPLE *)(lpStream + dwMemPos);
66
+ _this->Ins[i].nVolume = pms->volume << 2;
67
+ _this->Ins[i].nGlobalVol = 64;
68
+ DWORD len = pms->length;
69
+ if ((len > 4) && (len <= MAX_SAMPLE_LENGTH))
70
+ {
71
+ _this->Ins[i].nLength = len;
72
+ _this->Ins[i].nLoopStart = pms->reppos;
73
+ _this->Ins[i].nLoopEnd = pms->repend;
74
+ if (_this->Ins[i].nLoopEnd > _this->Ins[i].nLength)
75
+ _this->Ins[i].nLoopEnd = _this->Ins[i].nLength;
76
+ if (_this->Ins[i].nLoopStart + 4 >= _this->Ins[i].nLoopEnd)
77
+ _this->Ins[i].nLoopStart = _this->Ins[i].nLoopEnd = 0;
78
+ if (_this->Ins[i].nLoopEnd) _this->Ins[i].uFlags |= CHN_LOOP;
79
+ _this->Ins[i].nFineTune = MOD2XMFineTune(pms->finetune);
80
+ if (pms->attribute & 0x01)
81
+ {
82
+ _this->Ins[i].uFlags |= CHN_16BIT;
83
+ _this->Ins[i].nLength >>= 1;
84
+ _this->Ins[i].nLoopStart >>= 1;
85
+ _this->Ins[i].nLoopEnd >>= 1;
86
+ }
87
+ _this->Ins[i].nPan = 128;
88
+ }
89
+ dwMemPos += 37;
90
+ }
91
+ // Setting Channel Pan Position
92
+ for (UINT ich=0; ich<_this->m_nChannels; ich++)
93
+ {
94
+ _this->ChnSettings[ich].nPan = ((pmh->panpos[ich] & 0x0F) << 4) + 8;
95
+ _this->ChnSettings[ich].nVolume = 64;
96
+ }
97
+ // Reading pattern order
98
+ SDL_memcpy(_this->Order, lpStream + dwMemPos, pmh->lastorder+1);
99
+ dwMemPos += 128;
100
+ // Reading Patterns
101
+ LPCBYTE pTracks = lpStream + dwMemPos;
102
+ dwMemPos += 192 * pmh->numtracks;
103
+ LPWORD pSeq = (LPWORD)(lpStream + dwMemPos);
104
+ for (UINT pat=0; pat<=pmh->lastpattern; pat++)
105
+ {
106
+ _this->PatternSize[pat] = 64;
107
+ if ((_this->Patterns[pat] = CSoundFile_AllocatePattern(64, _this->m_nChannels)) == NULL) break;
108
+ for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < _this->m_nChannels))
109
+ {
110
+ LPCBYTE p = pTracks + 192 * (pSeq[n]-1);
111
+ MODCOMMAND *m = _this->Patterns[pat] + n;
112
+ for (UINT i=0; i<64; i++, m+=_this->m_nChannels, p+=3)
113
+ {
114
+ if (p[0] & 0xFC) m->note = (p[0] >> 2) + 37;
115
+ m->instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
116
+ UINT cmd = p[1] & 0x0F;
117
+ UINT param = p[2];
118
+ if (cmd == 0x0A)
119
+ {
120
+ if (param & 0xF0) param &= 0xF0; else param &= 0x0F;
121
+ }
122
+ m->command = cmd;
123
+ m->param = param;
124
+ if ((cmd) || (param)) CSoundFile_ConvertModCommand(_this, m);
125
+ }
126
+ }
127
+ pSeq += 32;
128
+ }
129
+ dwMemPos += 64*(pmh->lastpattern+1);
130
+ dwMemPos += pmh->commentsize;
131
+ // Reading Samples
132
+ for (UINT ismp=1; ismp<=_this->m_nSamples; ismp++)
133
+ {
134
+ if (dwMemPos >= dwMemLength) break;
135
+ dwMemPos += CSoundFile_ReadSample(_this, &_this->Ins[ismp], (_this->Ins[ismp].uFlags & CHN_16BIT) ? RS_PCM16U : RS_PCM8U,
136
+ (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
137
+ }
138
+ _this->m_nMinPeriod = 64;
139
+ _this->m_nMaxPeriod = 32767;
140
+ return TRUE;
141
+ }
142
+
@@ -0,0 +1,192 @@
1
+ /*
2
+ * This source code is public domain.
3
+ *
4
+ * Authors: Olivier Lapicque <olivierl@jps.net>,
5
+ * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
6
+ */
7
+
8
+ //////////////////////////////////////////////
9
+ // Oktalyzer (OKT) module loader //
10
+ //////////////////////////////////////////////
11
+ #include "libmodplug.h"
12
+
13
+ typedef struct OKTFILEHEADER
14
+ {
15
+ DWORD okta; // "OKTA"
16
+ DWORD song; // "SONG"
17
+ DWORD cmod; // "CMOD"
18
+ DWORD fixed8;
19
+ BYTE chnsetup[8];
20
+ DWORD samp; // "SAMP"
21
+ DWORD samplen;
22
+ } OKTFILEHEADER;
23
+
24
+
25
+ typedef struct OKTSAMPLE
26
+ {
27
+ CHAR name[20];
28
+ DWORD length;
29
+ WORD loopstart;
30
+ WORD looplen;
31
+ BYTE pad1;
32
+ BYTE volume;
33
+ BYTE pad2;
34
+ BYTE pad3;
35
+ } OKTSAMPLE;
36
+
37
+
38
+ BOOL CSoundFile_ReadOKT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength)
39
+ //---------------------------------------------------------------
40
+ {
41
+ const OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream;
42
+ DWORD dwMemPos = sizeof(OKTFILEHEADER);
43
+ UINT nsamples = 0, npatterns = 0, norders = 0;
44
+
45
+ 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;
50
+ _this->m_nType = MOD_TYPE_OKT;
51
+ _this->m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7];
52
+ if (_this->m_nChannels > MAX_CHANNELS) _this->m_nChannels = MAX_CHANNELS;
53
+ nsamples = bswapBE32(pfh->samplen) >> 5;
54
+ _this->m_nSamples = nsamples;
55
+ if (_this->m_nSamples >= MAX_SAMPLES) _this->m_nSamples = MAX_SAMPLES-1;
56
+ // Reading samples
57
+ for (UINT smp=1; smp <= nsamples; smp++)
58
+ {
59
+ if (dwMemPos >= dwMemLength) return TRUE;
60
+ if (smp < MAX_SAMPLES)
61
+ {
62
+ OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos);
63
+ MODINSTRUMENT *pins = &_this->Ins[smp];
64
+ pins->uFlags = 0;
65
+ pins->nLength = bswapBE32(psmp->length) & ~1;
66
+ pins->nLoopStart = bswapBE16(psmp->loopstart);
67
+ pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen);
68
+ if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
69
+ pins->nGlobalVol = 64;
70
+ pins->nVolume = psmp->volume << 2;
71
+ pins->nC4Speed = 8363;
72
+ }
73
+ dwMemPos += sizeof(OKTSAMPLE);
74
+ }
75
+ // SPEE
76
+ if (dwMemPos >= dwMemLength) return TRUE;
77
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053)
78
+ {
79
+ _this->m_nDefaultSpeed = lpStream[dwMemPos+9];
80
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
81
+ }
82
+ // SLEN
83
+ if (dwMemPos >= dwMemLength) return TRUE;
84
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53)
85
+ {
86
+ npatterns = lpStream[dwMemPos+9];
87
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
88
+ }
89
+ // PLEN
90
+ if (dwMemPos >= dwMemLength) return TRUE;
91
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50)
92
+ {
93
+ norders = lpStream[dwMemPos+9];
94
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
95
+ }
96
+ // PATT
97
+ if (dwMemPos >= dwMemLength) return TRUE;
98
+ if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150)
99
+ {
100
+ UINT orderlen = norders;
101
+ if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1;
102
+ for (UINT i=0; i<orderlen; i++) _this->Order[i] = lpStream[dwMemPos+10+i];
103
+ for (UINT j=orderlen; j>1; j--) { if (_this->Order[j-1]) break; _this->Order[j-1] = 0xFF; }
104
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
105
+ }
106
+ // PBOD
107
+ UINT npat = 0;
108
+ while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250))
109
+ {
110
+ DWORD dwPos = dwMemPos + 10;
111
+ UINT rows = lpStream[dwMemPos+9];
112
+ if (!rows) rows = 64;
113
+ if (npat < MAX_PATTERNS)
114
+ {
115
+ if ((_this->Patterns[npat] = CSoundFile_AllocatePattern(rows, _this->m_nChannels)) == NULL) return TRUE;
116
+ MODCOMMAND *m = _this->Patterns[npat];
117
+ _this->PatternSize[npat] = rows;
118
+ UINT imax = _this->m_nChannels*rows;
119
+ for (UINT i=0; i<imax; i++, m++, dwPos+=4)
120
+ {
121
+ if (dwPos+4 > dwMemLength) break;
122
+ const BYTE *p = lpStream+dwPos;
123
+ UINT note = p[0];
124
+ if (note)
125
+ {
126
+ m->note = note + 48;
127
+ m->instr = p[1] + 1;
128
+ }
129
+ UINT command = p[2];
130
+ UINT param = p[3];
131
+ m->param = param;
132
+ switch(command)
133
+ {
134
+ // 0: no effect
135
+ case 0:
136
+ break;
137
+ // 1: Portamento Up
138
+ case 1:
139
+ case 17:
140
+ case 30:
141
+ if (param) m->command = CMD_PORTAMENTOUP;
142
+ break;
143
+ // 2: Portamento Down
144
+ case 2:
145
+ case 13:
146
+ case 21:
147
+ if (param) m->command = CMD_PORTAMENTODOWN;
148
+ break;
149
+ // 10: Arpeggio
150
+ case 10:
151
+ case 11:
152
+ case 12:
153
+ m->command = CMD_ARPEGGIO;
154
+ break;
155
+ // 15: Filter
156
+ case 15:
157
+ m->command = CMD_MODCMDEX;
158
+ m->param = param & 0x0F;
159
+ break;
160
+ // 25: Position Jump
161
+ case 25:
162
+ m->command = CMD_POSITIONJUMP;
163
+ break;
164
+ // 28: Set Speed
165
+ case 28:
166
+ m->command = CMD_SPEED;
167
+ break;
168
+ // 31: Volume Control
169
+ case 31:
170
+ if (param <= 0x40) m->command = CMD_VOLUME; else
171
+ if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else
172
+ if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else
173
+ if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else
174
+ if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; }
175
+ break;
176
+ }
177
+ }
178
+ }
179
+ npat++;
180
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
181
+ }
182
+ // SBOD
183
+ UINT nsmp = 1;
184
+ while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253))
185
+ {
186
+ if (nsmp < MAX_SAMPLES) CSoundFile_ReadSample(_this, &_this->Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8);
187
+ dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
188
+ nsmp++;
189
+ }
190
+ return TRUE;
191
+ }
192
+
@@ -0,0 +1,1143 @@
1
+ /*
2
+
3
+ MikMod Sound System
4
+
5
+ By Jake Stine of Divine Entertainment (1996-2000)
6
+
7
+ Support:
8
+ If you find problems with this code, send mail to:
9
+ air@divent.org
10
+
11
+ Distribution / Code rights:
12
+ Use this source code in any fashion you see fit. Giving me credit where
13
+ credit is due is optional, depending on your own levels of integrity and
14
+ honesty.
15
+
16
+ -----------------------------------------
17
+ Module: LOAD_PAT
18
+
19
+ PAT sample loader.
20
+ by Peter Grootswagers (2006)
21
+ <email:pgrootswagers@planet.nl>
22
+
23
+ It's primary purpose is loading samples for the .abc and .mid modules
24
+ Can also be used stand alone, in that case a tune (frere Jacques)
25
+ is generated using al samples available in the .pat file
26
+
27
+ Portability:
28
+ All systems - all compilers (hopefully)
29
+ */
30
+
31
+ #include "libmodplug.h"
32
+
33
+ #include <stdlib.h>
34
+ #include <time.h>
35
+ #include <string.h>
36
+ #include <math.h>
37
+ #include <ctype.h>
38
+ #ifndef _WIN32
39
+ #include <limits.h> // for PATH_MAX
40
+ #endif
41
+ #ifndef PATH_MAX
42
+ #define PATH_MAX 256
43
+ #endif
44
+
45
+ #include "load_pat.h"
46
+
47
+ #ifdef MSC_VER
48
+ #define DIRDELIM '\\'
49
+ #define TIMIDITYCFG "C:\\TIMIDITY\\TIMIDITY.CFG"
50
+ #define PATHFORPAT "C:\\TIMIDITY\\INSTRUMENTS"
51
+ #else
52
+ #define DIRDELIM '/'
53
+ #define TIMIDITYCFG "/usr/local/share/timidity/timidity.cfg"
54
+ #define PATHFORPAT "/usr/local/share/timidity/instruments"
55
+ #endif
56
+
57
+ #define PAT_ENV_PATH2CFG "MMPAT_PATH_TO_CFG"
58
+
59
+ /* !!! FIXME: global state */
60
+ // 128 gm and 63 drum
61
+ #define MAXSMP 191
62
+ static char midipat[MAXSMP][PATH_MAX];
63
+ static char pathforpat[PATH_MAX];
64
+ static char timiditycfg[PATH_MAX];
65
+
66
+ #pragma pack(1)
67
+
68
+ typedef struct {
69
+ char header[12]; // ascizz GF1PATCH110
70
+ char gravis_id[10]; // allways ID#000002
71
+ char description[60];
72
+ BYTE instruments;
73
+ BYTE voices;
74
+ BYTE channels;
75
+ WORD waveforms;
76
+ WORD master_volume;
77
+ DWORD data_size;
78
+ char reserved[36];
79
+ } PatchHeader;
80
+
81
+ typedef struct {
82
+ WORD instrument_id;
83
+ char instrument_name[16];
84
+ DWORD instrument_size;
85
+ BYTE layers;
86
+ char reserved[40];
87
+ } InstrumentHeader;
88
+
89
+ typedef struct {
90
+ BYTE layer_dup;
91
+ BYTE layer_id;
92
+ DWORD layer_size;
93
+ BYTE samples;
94
+ char reserved[40];
95
+ } LayerHeader;
96
+
97
+ typedef struct {
98
+ char wave_name[7];
99
+ BYTE fractions;
100
+ DWORD wave_size;
101
+ DWORD start_loop;
102
+ DWORD end_loop;
103
+ WORD sample_rate;
104
+ DWORD low_frequency ;
105
+ DWORD high_frequency;
106
+ DWORD root_frequency;
107
+ short int tune;
108
+ BYTE balance;
109
+ BYTE envelope_rate[6];
110
+ BYTE envelope_offset[6];
111
+ BYTE tremolo_sweep;
112
+ BYTE tremolo_rate;
113
+ BYTE tremolo_depth;
114
+ BYTE vibrato_sweep;
115
+ BYTE vibrato_rate;
116
+ BYTE vibrato_depth;
117
+ BYTE modes;
118
+ DWORD scale_frequency;
119
+ DWORD scale_factor;
120
+ char reserved[32];
121
+ } WaveHeader;
122
+
123
+ // WaveHeader.modes bits
124
+ #define PAT_16BIT 1
125
+ #define PAT_UNSIGNED 2
126
+ #define PAT_LOOP 4
127
+ #define PAT_PINGPONG 8
128
+ #define PAT_BACKWARD 16
129
+ #define PAT_SUSTAIN 32
130
+ #define PAT_ENVELOPE 64
131
+ #define PAT_CLAMPED 128
132
+
133
+ #define C4SPD 8363
134
+ #define C4mHz 523251
135
+ #define C4 523.251f
136
+ #define PI 3.141592653589793f
137
+ #define OMEGA ((2.0f * PI * C4)/(float)C4SPD)
138
+
139
+ /**************************************************************************
140
+ **************************************************************************/
141
+ /* !!! FIXME: global state */
142
+ static BYTE pat_gm_used[MAXSMP];
143
+ static BYTE pat_loops[MAXSMP];
144
+
145
+ /**************************************************************************
146
+ **************************************************************************/
147
+
148
+ static SDL_INLINE int IsAlpha(const char c) {
149
+ return ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) );
150
+ }
151
+
152
+ static SDL_INLINE int IsBlank(const char c) {
153
+ return ( (c == ' ') || (c == '\t') );
154
+ }
155
+
156
+
157
+ typedef struct _PATHANDLE
158
+ {
159
+ char patname[16];
160
+ int samples;
161
+ } PATHANDLE;
162
+
163
+ // local prototypes
164
+ static int pat_getopt(const char *s, const char *o, int dflt);
165
+
166
+ static void pat_message(const char *s1, const char *s2)
167
+ {
168
+ char txt[256];
169
+ if( SDL_strlen(s1) + SDL_strlen(s2) > 255 ) return;
170
+ SDL_snprintf(txt, sizeof (txt), s1, s2);
171
+ SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "load_pat > %s\n", txt);
172
+ }
173
+
174
+ void pat_resetsmp(void)
175
+ {
176
+ int i;
177
+ for( i=0; i<MAXSMP; i++ ) {
178
+ pat_loops[i] = 0;
179
+ pat_gm_used[i] = 0;
180
+ }
181
+ }
182
+
183
+ int pat_numsmp()
184
+ {
185
+ return SDL_strlen((const char *)pat_gm_used);
186
+ }
187
+
188
+ int pat_numinstr(void)
189
+ {
190
+ return SDL_strlen((const char *)pat_gm_used);
191
+ }
192
+
193
+ int pat_smptogm(int smp)
194
+ {
195
+ if( smp < MAXSMP )
196
+ return pat_gm_used[smp - 1];
197
+ return 1;
198
+ }
199
+
200
+ int pat_gmtosmp(int gm)
201
+ {
202
+ int smp;
203
+ for( smp=0; pat_gm_used[smp]; smp++ )
204
+ if( pat_gm_used[smp] == gm )
205
+ return smp+1;
206
+ if( smp < MAXSMP ) {
207
+ pat_gm_used[smp] = gm;
208
+ return smp+1;
209
+ }
210
+ return 1;
211
+ }
212
+
213
+ int pat_smplooped(int smp)
214
+ {
215
+ if( smp < MAXSMP ) return pat_loops[smp - 1];
216
+ return 1;
217
+ }
218
+
219
+ const char *pat_gm_name(int gm)
220
+ {
221
+ static char buf[40];
222
+ if( gm < 1 || gm > MAXSMP ) {
223
+ SDL_snprintf(buf, sizeof (buf), "invalid gm %d", gm);
224
+ return buf;
225
+ }
226
+ return midipat[gm - 1];
227
+ }
228
+
229
+ int pat_gm_drumnr(int n)
230
+ {
231
+ if( n < 25 ) return 129;
232
+ if( n+129-25 < MAXSMP )
233
+ return 129+n-25; // timidity.cfg drum patches start at 25
234
+ return MAXSMP;
235
+ }
236
+
237
+ int pat_gm_drumnote(int n)
238
+ {
239
+ char *p;
240
+ p = SDL_strchr(midipat[pat_gm_drumnr(n)-1], ':');
241
+ if( p ) return pat_getopt(p+1, "note", n);
242
+ return n;
243
+ }
244
+
245
+ static float pat_sinus(int i)
246
+ {
247
+ float res = SDL_sinf(OMEGA * (float)i);
248
+ return res;
249
+ }
250
+
251
+ static float pat_square(int i)
252
+ {
253
+ float res = 30.0f * SDL_sinf(OMEGA * (float)i);
254
+ if( res > 0.99f ) return 0.99f;
255
+ if( res < -0.99f ) return -0.99f;
256
+ return res;
257
+ }
258
+
259
+ static float pat_sawtooth(int i)
260
+ {
261
+ float res = OMEGA * (float)i;
262
+ while( res > 2 * PI )
263
+ res -= 2 * PI;
264
+ i = 2;
265
+ if( res > PI ) {
266
+ res = PI - res;
267
+ i = -2;
268
+ }
269
+ res = (float)i * res / PI;
270
+ if( res > 0.9f ) return 1.0f - res;
271
+ if( res < -0.9f ) return 1.0f + res;
272
+ return res;
273
+ }
274
+
275
+ typedef float (*PAT_SAMPLE_FUN)(int);
276
+
277
+ static PAT_SAMPLE_FUN pat_fun[] = { pat_sinus, pat_square, pat_sawtooth };
278
+
279
+ long _mm_getfsize(MMSTREAM *mmpat) {
280
+ long fsize;
281
+ _mm_fseek(mmpat, 0L, SEEK_END);
282
+ fsize = _mm_ftell(mmpat);
283
+ _mm_fseek(mmpat, 0L, SEEK_SET);
284
+ return(fsize);
285
+ }
286
+
287
+ void pat_init_patnames(void)
288
+ {
289
+ int z, i, nsources, isdrumset, nskip, pfnlen;
290
+ char *p, *q;
291
+ char line[PATH_MAX];
292
+ char cfgsources[5][PATH_MAX];
293
+ MMSTREAM *mmcfg;
294
+ SDL_memset(cfgsources, 0, sizeof (cfgsources));
295
+ SDL_strlcpy(pathforpat, PATHFORPAT, PATH_MAX);
296
+ SDL_strlcpy(timiditycfg, TIMIDITYCFG, PATH_MAX);
297
+ p = SDL_getenv(PAT_ENV_PATH2CFG);
298
+ if( p ) {
299
+ SDL_snprintf(timiditycfg, sizeof (timiditycfg), "%s/timidity.cfg", p);
300
+ SDL_snprintf(pathforpat, sizeof (pathforpat), "%s", p);
301
+ }
302
+ SDL_strlcpy(cfgsources[0], timiditycfg, PATH_MAX - 1);
303
+ nsources = 1;
304
+
305
+ for( i=0; i<MAXSMP; i++ ) midipat[i][0] = '\0';
306
+
307
+ for ( z=0; z<5; z++ ) {
308
+ if (cfgsources[z][0] == 0) continue;
309
+ mmcfg = _mm_fopen(cfgsources[z],"r");
310
+ if( !mmcfg ) {
311
+ pat_message("can not open %s, use environment variable " PAT_ENV_PATH2CFG " for the directory", cfgsources[z]);
312
+ }
313
+ else {
314
+ // read in bank 0 and drum patches
315
+ isdrumset = 0;
316
+ _mm_fgets(mmcfg, line, PATH_MAX);
317
+ while( !_mm_feof(mmcfg) ) {
318
+ if( SDL_isdigit(line[0]) || (IsBlank(line[0]) && SDL_isdigit(line[1])) ) {
319
+ p = line;
320
+ // get pat number
321
+ while ( SDL_isspace(*p) ) p ++;
322
+ i = SDL_atoi(p);
323
+ while ( SDL_isdigit(*p) ) p ++;
324
+ while ( SDL_isspace(*p) ) p ++;
325
+ // get pat file name
326
+ if( *p && i < MAXSMP && i >= 0 && *p != '#' ) {
327
+ q = isdrumset ? midipat[pat_gm_drumnr(i)-1] : midipat[i];
328
+ pfnlen = 0;
329
+ while( *p && !SDL_isspace(*p) && *p != '#' && pfnlen < 128 ) {
330
+ pfnlen ++;
331
+ *q++ = *p++;
332
+ }
333
+ if( IsBlank(*p) && *(p+1) != '#' && pfnlen < 128 ) {
334
+ *q++ = ':'; pfnlen ++;
335
+ while( SDL_isspace(*p) ) {
336
+ while( SDL_isspace(*p) ) p++;
337
+ if ( *p == '#' ) { // comment
338
+
339
+ } else while( *p && !SDL_isspace(*p) && pfnlen < 128 ) {
340
+ pfnlen ++;
341
+ *q++ = *p++;
342
+ }
343
+ if( SDL_isspace(*p) ) { *q++ = ' '; pfnlen++; }
344
+ }
345
+ }
346
+ *q++ = '\0';
347
+ }
348
+ }
349
+ if( !SDL_strncmp(line,"drumset",7) ) isdrumset = 1;
350
+ if( !SDL_strncmp(line,"source",6) && nsources < 5 ) {
351
+ q = cfgsources[nsources];
352
+ p = &line[7];
353
+ while ( SDL_isspace(*p) ) p ++;
354
+ pfnlen = 0;
355
+ while ( *p && *p != '#' && !SDL_isspace(*p) && pfnlen < 128 ) {
356
+ pfnlen ++;
357
+ *q++ = *p++;
358
+ }
359
+ *q = 0; // null termination
360
+ nsources++;
361
+ }
362
+ _mm_fgets(mmcfg, line, PATH_MAX);
363
+
364
+ } /* end file parsing */
365
+ _mm_fclose(mmcfg);
366
+ }
367
+ }
368
+ q = midipat[0];
369
+ nskip = 0;
370
+ // make all empty patches duplicates the previous valid one.
371
+ for( i=0; i<MAXSMP; i++ ) {
372
+ if( midipat[i][0] ) q = midipat[i];
373
+ else {
374
+ if( midipat[i] != q)
375
+ SDL_strlcpy(midipat[i], q, PATH_MAX);
376
+ if( midipat[i][0] == '\0' ) nskip++;
377
+ }
378
+ }
379
+ if( nskip ) {
380
+ for( i=MAXSMP; i-- > 0; ) {
381
+ if( midipat[i][0] ) q = midipat[i];
382
+ else if( midipat[i] != q )
383
+ SDL_strlcpy(midipat[i], q, PATH_MAX);
384
+ }
385
+ }
386
+ }
387
+
388
+ static char *pat_build_path(char *fname, const size_t fnamelen, int pat)
389
+ {
390
+ char *ps;
391
+ char *patfile = midipat[pat];
392
+ int isabspath = (patfile[0] == '/');
393
+ if ( isabspath ) patfile ++;
394
+ ps = SDL_strrchr(patfile, ':');
395
+ if( ps ) {
396
+ SDL_snprintf(fname, fnamelen, "%s%c%s", isabspath ? "" : pathforpat, DIRDELIM, patfile);
397
+ char *replaceptr = SDL_strrchr(fname, ':');
398
+ SDL_assert(replaceptr != NULL);
399
+ *replaceptr = '\0';
400
+ SDL_strlcat(fname, ".pat", fnamelen);
401
+ return ps;
402
+ }
403
+ SDL_snprintf(fname, fnamelen, "%s%c%s.pat", isabspath ? "" : pathforpat, DIRDELIM, patfile);
404
+ return 0;
405
+ }
406
+
407
+ static void pat_read_patname(PATHANDLE *h, MMFILE *mmpat) {
408
+ InstrumentHeader ih;
409
+ mmfseek(mmpat,sizeof(PatchHeader), SEEK_SET);
410
+ mmreadUBYTES((BYTE *)&ih, sizeof(InstrumentHeader), mmpat);
411
+ SDL_strlcpy(h->patname, ih.instrument_name, 16);
412
+ h->patname[15] = '\0';
413
+ }
414
+
415
+ static void pat_read_layerheader(MMSTREAM *mmpat, LayerHeader *hl)
416
+ {
417
+ _mm_fseek(mmpat,sizeof(PatchHeader)+sizeof(InstrumentHeader), SEEK_SET);
418
+ _mm_read_UBYTES((BYTE *)hl, sizeof(LayerHeader), mmpat);
419
+ }
420
+
421
+ static void pat_get_layerheader(MMFILE *mmpat, LayerHeader *hl)
422
+ {
423
+ InstrumentHeader ih;
424
+ mmfseek(mmpat,sizeof(PatchHeader), SEEK_SET);
425
+ mmreadUBYTES((BYTE *)&ih, sizeof(InstrumentHeader), mmpat);
426
+ mmreadUBYTES((BYTE *)hl, sizeof(LayerHeader), mmpat);
427
+ SDL_strlcpy(hl->reserved, ih.instrument_name, 40);
428
+ }
429
+
430
+ static int pat_read_numsmp(MMFILE *mmpat) {
431
+ LayerHeader hl;
432
+ pat_get_layerheader(mmpat, &hl);
433
+ return hl.samples;
434
+ }
435
+
436
+ static void pat_read_waveheader(MMSTREAM *mmpat, WaveHeader *hw, int layer)
437
+ {
438
+ long int pos, bestpos=0;
439
+ LayerHeader hl;
440
+ ULONG bestfreq, freqdist;
441
+ int i;
442
+ // read the very first and maybe only sample
443
+ pat_read_layerheader(mmpat, &hl);
444
+ if( hl.samples > 1 ) {
445
+ if( layer ) {
446
+ if( layer > hl.samples ) layer = hl.samples; // you don't fool me....
447
+ for( i=1; i<layer; i++ ) {
448
+ _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat);
449
+ _mm_fseek(mmpat, hw->wave_size, SEEK_CUR);
450
+ }
451
+ }
452
+ else {
453
+ bestfreq = C4mHz * 1000; // big enough
454
+ for( i=0; i<hl.samples; i++ ) {
455
+ pos = _mm_ftell(mmpat);
456
+ _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat);
457
+ if( hw->root_frequency > C4mHz )
458
+ freqdist = hw->root_frequency - C4mHz;
459
+ else
460
+ freqdist = 2 * (C4mHz - hw->root_frequency);
461
+ if( freqdist < bestfreq ) {
462
+ bestfreq = freqdist;
463
+ bestpos = pos;
464
+ }
465
+ _mm_fseek(mmpat, hw->wave_size, SEEK_CUR);
466
+ }
467
+ _mm_fseek(mmpat, bestpos, SEEK_SET);
468
+ }
469
+ }
470
+ _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat);
471
+ SDL_strlcpy(hw->reserved, hl.reserved, 32);
472
+ hw->reserved[31] = 0;
473
+ if( hw->start_loop >= hw->wave_size ) {
474
+ hw->start_loop = 0;
475
+ hw->end_loop = 0;
476
+ hw->modes &= ~PAT_LOOP; // mask off loop indicator
477
+ }
478
+ if( hw->end_loop > hw->wave_size )
479
+ hw->end_loop = hw->wave_size;
480
+ }
481
+
482
+ static void pat_get_waveheader(MMFILE *mmpat, WaveHeader *hw, int layer)
483
+ {
484
+ long int pos, bestpos=0;
485
+ LayerHeader hl;
486
+ ULONG bestfreq, freqdist;
487
+ int i;
488
+ // read the very first and maybe only sample
489
+ pat_get_layerheader(mmpat, &hl);
490
+ if( hl.samples > 1 ) {
491
+ if( layer ) {
492
+ if( layer > hl.samples ) layer = hl.samples; // you don't fool me....
493
+ for( i=1; i<layer; i++ ) {
494
+ mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat);
495
+ mmfseek(mmpat, hw->wave_size, SEEK_CUR);
496
+ if ( mmpat->error ) {
497
+ hw->wave_size = 0;
498
+ return;
499
+ }
500
+ }
501
+ }
502
+ else {
503
+ bestfreq = C4mHz * 1000; // big enough
504
+ for( i=0; i<hl.samples; i++ ) {
505
+ pos = mmftell(mmpat);
506
+ mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat);
507
+ if( hw->root_frequency > C4mHz )
508
+ freqdist = hw->root_frequency - C4mHz;
509
+ else
510
+ freqdist = 2 * (C4mHz - hw->root_frequency);
511
+ if( freqdist < bestfreq ) {
512
+ bestfreq = freqdist;
513
+ bestpos = pos;
514
+ }
515
+ mmfseek(mmpat, hw->wave_size, SEEK_CUR);
516
+ }
517
+ mmfseek(mmpat, bestpos, SEEK_SET);
518
+ }
519
+ }
520
+ mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat);
521
+ if( hw->start_loop >= hw->wave_size ) {
522
+ hw->start_loop = 0;
523
+ hw->end_loop = 0;
524
+ hw->modes &= ~PAT_LOOP; // mask off loop indicator
525
+ }
526
+ if( hw->end_loop > hw->wave_size )
527
+ hw->end_loop = hw->wave_size;
528
+ }
529
+
530
+ static int pat_readpat_attr(int pat, WaveHeader *hw, int layer)
531
+ {
532
+ char fname[128];
533
+ unsigned long fsize;
534
+ MMSTREAM *mmpat;
535
+ pat_build_path(fname, sizeof (fname), pat);
536
+ mmpat = _mm_fopen(fname, "r");
537
+ if( !mmpat )
538
+ return 0;
539
+ fsize = _mm_getfsize(mmpat);
540
+ pat_read_waveheader(mmpat, hw, layer);
541
+ _mm_fclose(mmpat);
542
+ if (hw->wave_size > fsize)
543
+ return 0;
544
+ return 1;
545
+ }
546
+
547
+ static void pat_amplify(char *b, int num, int amp, int m)
548
+ {
549
+ char *pb;
550
+ BYTE *pu;
551
+ short int *pi;
552
+ WORD *pw;
553
+ int i,n,v;
554
+ n = num;
555
+ if( m & PAT_16BIT ) { // 16 bit
556
+ n >>= 1;
557
+ if( m & 2 ) { // unsigned
558
+ pw = (WORD *)b;
559
+ for( i=0; i<n; i++ ) {
560
+ v = (((int)(*pw) - 0x8000) * amp) / 100;
561
+ if( v < -0x8000 ) v = -0x8000;
562
+ if( v > 0x7fff ) v = 0x7fff;
563
+ *pw++ = v + 0x8000;
564
+ }
565
+ }
566
+ else {
567
+ pi = (short int *)b;
568
+ for( i=0; i<n; i++ ) {
569
+ v = ((*pi) * amp) / 100;
570
+ if( v < -0x8000 ) v = -0x8000;
571
+ if( v > 0x7fff ) v = 0x7fff;
572
+ *pi++ = v;
573
+ }
574
+ }
575
+ }
576
+ else {
577
+ if( m & 2 ) { // unsigned
578
+ pu = (BYTE *)b;
579
+ for( i=0; i<n; i++ ) {
580
+ v = (((int)(*pu) - 0x80) * amp) / 100;
581
+ if( v < -0x80 ) v = -0x80;
582
+ if( v > 0x7f ) v = 0x7f;
583
+ *pu++ = v + 0x80;
584
+ }
585
+ }
586
+ else {
587
+ pb = (char *)b;
588
+ for( i=0; i<n; i++ ) {
589
+ v = ((*pb) * amp) / 100;
590
+ if( v < -0x80 ) v = -0x80;
591
+ if( v > 0x7f ) v = 0x7f;
592
+ *pb++ = v;
593
+ }
594
+ }
595
+ }
596
+ }
597
+
598
+ static int pat_getopt(const char *s, const char *o, int dflt)
599
+ {
600
+ const char *p;
601
+ if( !s ) return dflt;
602
+ p = SDL_strstr(s,o);
603
+ if( !p ) return dflt;
604
+ return SDL_atoi(SDL_strchr(p,'=')+1);
605
+ }
606
+
607
+ static void pat_readpat(int pat, char *dest, int num)
608
+ {
609
+ static int readlasttime = 0, wavesize = 0;
610
+ static MMSTREAM *mmpat = 0;
611
+ static char *opt = 0;
612
+ int amp;
613
+ char fname[128];
614
+ WaveHeader hw;
615
+ if( !readlasttime ) {
616
+ opt=pat_build_path(fname, sizeof (fname), pat);
617
+ mmpat = _mm_fopen(fname, "r");
618
+ if( !mmpat )
619
+ return;
620
+ pat_read_waveheader(mmpat, &hw, 0);
621
+ wavesize = hw.wave_size;
622
+ }
623
+ _mm_read_SBYTES(dest, num, mmpat);
624
+ amp = pat_getopt(opt,"amp",100);
625
+ if( amp != 100 ) pat_amplify(dest, num, amp, hw.modes);
626
+ readlasttime += num;
627
+ if( readlasttime < wavesize ) return;
628
+ readlasttime = 0;
629
+ _mm_fclose(mmpat);
630
+ mmpat = 0;
631
+ }
632
+
633
+ static BOOL dec_pat_Decompress16Bit(short int *dest, int cbcount, int samplenum)
634
+ {
635
+ int i;
636
+ PAT_SAMPLE_FUN f;
637
+ if( samplenum < MAXSMP ) pat_readpat(samplenum, (char *)dest, cbcount*2);
638
+ else {
639
+ f = pat_fun[(samplenum - MAXSMP) % 3];
640
+ for( i=0; i<cbcount; i++ )
641
+ dest[i] = (short int)(32000.0*f(i));
642
+ }
643
+ return cbcount;
644
+ }
645
+
646
+ // convert 8 bit data to 16 bit!
647
+ // We do the conversion in reverse so that the data we're converting isn't overwritten
648
+ // by the result.
649
+ static void pat_blowup_to16bit(short int *dest, int cbcount) {
650
+ char *s;
651
+ short int *d;
652
+ int t;
653
+ s = (char *)dest;
654
+ d = dest;
655
+ s += cbcount;
656
+ d += cbcount;
657
+ for(t=0; t<cbcount; t++)
658
+ { s--;
659
+ d--;
660
+ *d = (*s) << 8;
661
+ }
662
+ }
663
+
664
+ static BOOL dec_pat_Decompress8Bit(short int *dest, int cbcount, int samplenum)
665
+ {
666
+ int i;
667
+ PAT_SAMPLE_FUN f;
668
+ if( samplenum < MAXSMP ) pat_readpat(samplenum, (char *)dest, cbcount);
669
+ else {
670
+ f = pat_fun[(samplenum - MAXSMP) % 3];
671
+ for( i=0; i<cbcount; i++ )
672
+ dest[i] = (char)(120.0*f(i));
673
+ }
674
+ pat_blowup_to16bit(dest, cbcount);
675
+ return cbcount;
676
+ }
677
+
678
+ BOOL CSoundFile_TestPAT(const BYTE *lpStream, DWORD dwMemLength)
679
+ // =====================================================================================
680
+ {
681
+ PatchHeader ph;
682
+ if( dwMemLength < sizeof(PatchHeader) ) return 0;
683
+ SDL_memcpy((BYTE *)&ph, lpStream, sizeof(PatchHeader));
684
+ if( !SDL_strcmp(ph.header,"GF1PATCH110") && !SDL_strcmp(ph.gravis_id,"ID#000002") ) return 1;
685
+ return 0;
686
+ }
687
+
688
+ // =====================================================================================
689
+ static PATHANDLE *PAT_Init(void)
690
+ {
691
+ PATHANDLE *retval;
692
+ retval = (PATHANDLE *)SDL_calloc(1,sizeof(PATHANDLE));
693
+ if( !retval ) return NULL;
694
+ return retval;
695
+ }
696
+
697
+ // =====================================================================================
698
+ static void PAT_Cleanup(PATHANDLE *handle)
699
+ // =====================================================================================
700
+ {
701
+ if(handle) {
702
+ SDL_free(handle);
703
+ }
704
+ }
705
+
706
+ static char tune[] = "c d e c|c d e c|e f g..|e f g..|gagfe c|gagfe c|c G c..|c G c..|";
707
+ static int pat_note(int abc)
708
+ {
709
+ switch( abc ) {
710
+ case 'C': return 48;
711
+ case 'D': return 50;
712
+ case 'E': return 52;
713
+ case 'F': return 53;
714
+ case 'G': return 55;
715
+ case 'A': return 57;
716
+ case 'B': return 59;
717
+ case 'c': return 60;
718
+ case 'd': return 62;
719
+ case 'e': return 64;
720
+ case 'f': return 65;
721
+ case 'g': return 67;
722
+ case 'a': return 69;
723
+ case 'b': return 71;
724
+ default:
725
+ break;
726
+ }
727
+ return 0;
728
+ }
729
+
730
+ int pat_modnote(int midinote)
731
+ {
732
+ int n;
733
+ n = midinote;
734
+ n += 13;
735
+ return n;
736
+ }
737
+
738
+ static void PAT_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], PATHANDLE *h, int numpat)
739
+ // =====================================================================================
740
+ {
741
+ int pat,row,i,ch;
742
+ BYTE n,ins,vol;
743
+ int t;
744
+ int tt1, tt2;
745
+ MODCOMMAND *m;
746
+ if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS;
747
+
748
+ tt2 = (h->samples - 1) * 16 + 128;
749
+ for( pat = 0; pat < numpat; pat++ ) {
750
+ pattern[pat] = CSoundFile_AllocatePattern(64, h->samples);
751
+ if( !pattern[pat] ) return;
752
+ psize[pat] = 64;
753
+ for( row = 0; row < 64; row++ ) {
754
+ tt1 = (pat * 64 + row);
755
+ for( ch = 0; ch < h->samples; ch++ ) {
756
+ t = tt1 - ch * 16;
757
+ m = &pattern[pat][row * h->samples + ch];
758
+ m->param = 0;
759
+ m->command = CMD_NONE;
760
+ if( t >= 0 ) {
761
+ i = tt2 - 16 * ((h->samples - 1 - ch) & 3);
762
+ if( tt1 < i ) {
763
+ t = t % 64;
764
+ if( IsAlpha(tune[t]) ) {
765
+ n = pat_modnote(pat_note(tune[t]));
766
+ ins = ch + 1;
767
+ vol = 40;
768
+ if( (t % 16) == 0 ) {
769
+ vol += vol / 10;
770
+ if( vol > 64 ) vol = 64;
771
+ }
772
+ m->instr = ins;
773
+ m->note = n; // <- normal note
774
+ m->volcmd = VOLCMD_VOLUME;
775
+ m->vol = vol;
776
+ }
777
+ if( tt1 == i - 1 && ch == 0 && row < 63 ) {
778
+ m->command = CMD_PATTERNBREAK;
779
+ }
780
+ }
781
+ else {
782
+ if( tt1 == i ) {
783
+ m->param = 0;
784
+ m->command = CMD_KEYOFF;
785
+ m->volcmd = VOLCMD_VOLUME;
786
+ m->vol = 0;
787
+ }
788
+ }
789
+ }
790
+ }
791
+ }
792
+ }
793
+ }
794
+
795
+ // calculate the best speed that approximates the pat root frequency as a C note
796
+ static ULONG pat_patrate_to_C4SPD(ULONG patRate , ULONG patMilliHz)
797
+ {
798
+ ULONG u;
799
+ double x, y;
800
+ u = patMilliHz;
801
+ x = 0.1 * patRate;
802
+ x = x * C4mHz;
803
+ y = u * 0.4;
804
+ x = x / y;
805
+ u = (ULONG)(x+0.5);
806
+ return u;
807
+ }
808
+
809
+ // return relative position in samples for the rate starting with offset start ending with offset end
810
+ static int pat_envelope_rpos(int rate, int start, int end)
811
+ {
812
+ int r, p, t, s;
813
+ // rate byte is 3 bits exponent and 6 bits increment size
814
+ // eeiiiiii
815
+ // every 8 to the power ee the volume is incremented/decremented by iiiiii
816
+ // Thank you Gravis for this weirdness...
817
+ r = 3 - ((rate >> 6) & 3) * 3;
818
+ p = rate & 0x3f;
819
+ if( !p ) return 0;
820
+ t = end - start;
821
+ if( !t ) return 0;
822
+ if (t < 0) t = -t;
823
+ s = (t << r)/ p;
824
+ return s;
825
+ }
826
+
827
+ static void pat_modenv(WaveHeader *hw, int mpos[6], int mvol[6])
828
+ {
829
+ int i, sum, s;
830
+ BYTE *prate = hw->envelope_rate, *poffset = hw->envelope_offset;
831
+ for( i=0; i<6; i++ ) {
832
+ mpos[i] = 0;
833
+ mvol[i] = 64;
834
+ }
835
+ if( !SDL_memcmp(prate, "??????", 6) || poffset[5] >= 100 ) return; // weird rates or high env end volume
836
+ if( !(hw->modes & PAT_SUSTAIN) ) return; // no sustain thus no need for envelope
837
+ s = hw->wave_size;
838
+ if (s == 0) return;
839
+ if( hw->modes & PAT_16BIT )
840
+ s >>= 1;
841
+ // offsets 0 1 2 3 4 5 are distributed over 0 2 4 6 8 10, the odd numbers are set in between
842
+ sum = 0;
843
+ for( i=0; i<6; i++ ) {
844
+ mvol[i] = poffset[i];
845
+ mpos[i] = pat_envelope_rpos(prate[i], i? poffset[i-1]: 0, poffset[i]);
846
+ sum += mpos[i];
847
+ }
848
+ if( sum == 0 ) return;
849
+ if( sum > s ) {
850
+ for( i=0; i<6; i++ )
851
+ mpos[i] = (s * mpos[i]) / sum;
852
+ }
853
+ for( i=1; i<6; i++ )
854
+ mpos[i] += mpos[i-1];
855
+ for( i=0; i<6 ; i++ ) {
856
+ mpos[i] = (256 * mpos[i]) / s;
857
+ mpos[i]++;
858
+ if( i > 0 && mpos[i] <= mpos[i-1] ) {
859
+ if( mvol[i] == mvol[i-1] ) mpos[i] = mpos[i-1];
860
+ else mpos[i] = mpos[i-1] + 1;
861
+ }
862
+ if( mpos[i] > 256 ) mpos[i] = 256;
863
+ }
864
+ mvol[5] = 0; // kill Bill....
865
+ }
866
+
867
+ static void pat_setpat_inst(WaveHeader *hw, INSTRUMENTHEADER *d, int smp)
868
+ {
869
+ int u, inuse;
870
+ int envpoint[6], envvolume[6];
871
+ d->nMidiProgram = 0;
872
+ d->nFadeOut = 0;
873
+ d->nPan = 128;
874
+ d->nPPC = 5*12;
875
+ d->dwFlags = 0;
876
+ if( hw->modes & PAT_ENVELOPE ) d->dwFlags |= ENV_VOLUME;
877
+ if( hw->modes & PAT_SUSTAIN ) d->dwFlags |= ENV_VOLSUSTAIN;
878
+ if( (hw->modes & PAT_LOOP) && (hw->start_loop != hw->end_loop) ) d->dwFlags |= ENV_VOLLOOP;
879
+ d->nVolEnv = 6;
880
+ //if (!d->nVolEnv) d->dwFlags &= ~ENV_VOLUME;
881
+ d->nPanEnv = 0;
882
+ d->nVolSustainBegin = 1;
883
+ d->nVolSustainEnd = 1;
884
+ d->nVolLoopStart = 1;
885
+ d->nVolLoopEnd = 2;
886
+ d->nPanSustainBegin = 0;
887
+ d->nPanSustainEnd = 0;
888
+ d->nPanLoopStart = 0;
889
+ d->nPanLoopEnd = 0;
890
+ d->nGlobalVol = 64;
891
+ pat_modenv(hw, envpoint, envvolume);
892
+ inuse = 0;
893
+ for( u=0; u<6; u++)
894
+ {
895
+ if( envvolume[u] != 64 ) inuse = 1;
896
+ d->VolPoints[u] = envpoint[u];
897
+ d->VolEnv[u] = envvolume[u];
898
+ d->PanPoints[u] = 0;
899
+ d->PanEnv[u] = 0;
900
+ if (u)
901
+ {
902
+ if (d->VolPoints[u] < d->VolPoints[u-1])
903
+ {
904
+ d->VolPoints[u] &= 0xFF;
905
+ d->VolPoints[u] += d->VolPoints[u-1] & 0xFF00;
906
+ if (d->VolPoints[u] < d->VolPoints[u-1]) d->VolPoints[u] += 0x100;
907
+ }
908
+ }
909
+ }
910
+ if( !inuse ) d->nVolEnv = 0;
911
+ for( u=0; u<128; u++)
912
+ {
913
+ d->NoteMap[u] = u+1;
914
+ d->Keyboard[u] = smp;
915
+ }
916
+ }
917
+
918
+ static void PATinst(INSTRUMENTHEADER *d, int smp, int gm)
919
+ {
920
+ WaveHeader hw;
921
+ char s[32];
922
+ if( pat_readpat_attr(gm-1, &hw, 0) ) {
923
+ pat_setpat_inst(&hw, d, smp);
924
+ }
925
+ else {
926
+ hw.modes = PAT_16BIT|PAT_ENVELOPE|PAT_SUSTAIN|PAT_LOOP;
927
+ hw.start_loop = 0;
928
+ hw.end_loop = 30000;
929
+ hw.wave_size = 30000;
930
+ // envelope rates and offsets pinched from timidity's acpiano.pat sample no 1
931
+ hw.envelope_rate[0] = 0x3f;
932
+ hw.envelope_rate[1] = 0x3f;
933
+ hw.envelope_rate[2] = 0x3f;
934
+ hw.envelope_rate[3] = 0x08|(3<<6);
935
+ hw.envelope_rate[4] = 0x3f;
936
+ hw.envelope_rate[5] = 0x3f;
937
+ hw.envelope_offset[0] = 246;
938
+ hw.envelope_offset[1] = 246;
939
+ hw.envelope_offset[2] = 246;
940
+ hw.envelope_offset[3] = 0;
941
+ hw.envelope_offset[4] = 0;
942
+ hw.envelope_offset[5] = 0;
943
+ SDL_strlcpy(hw.reserved, midipat[gm-1], sizeof(hw.reserved));
944
+ pat_setpat_inst(&hw, d, smp);
945
+ }
946
+ SDL_strlcpy(s, midipat[gm-1], 12);
947
+ SDL_memset(d->filename, 0, 12);
948
+ SDL_strlcpy((char *)d->filename, s, sizeof (d->filename));
949
+ }
950
+
951
+ static void pat_setpat_attr(WaveHeader *hw, MODINSTRUMENT *q)
952
+ {
953
+ q->nC4Speed = pat_patrate_to_C4SPD(hw->sample_rate , hw->root_frequency);
954
+ q->nLength = hw->wave_size;
955
+ q->nLoopStart = hw->start_loop;
956
+ q->nLoopEnd = hw->end_loop;
957
+ q->nVolume = 256;
958
+ if( hw->modes & PAT_16BIT ) {
959
+ q->nLength >>= 1;
960
+ q->nLoopStart >>= 1;
961
+ q->nLoopEnd >>= 1;
962
+ }
963
+ if( hw->modes & PAT_LOOP ) {
964
+ q->uFlags |= CHN_LOOP;
965
+ if( hw->modes & PAT_PINGPONG ) q->uFlags |= CHN_PINGPONGSUSTAIN;
966
+ if( hw->modes & PAT_SUSTAIN ) q->uFlags |= CHN_SUSTAINLOOP;
967
+ }
968
+ }
969
+
970
+ // ==========================
971
+ // Load those darned Samples!
972
+ static void PATsample(CSoundFile *cs, MODINSTRUMENT *q, int smp, int gm)
973
+ {
974
+ WaveHeader hw;
975
+ q->nGlobalVol = 64;
976
+ q->nPan = 128;
977
+ q->uFlags = CHN_16BIT;
978
+ if( pat_readpat_attr(gm-1, &hw, 0) ) {
979
+ char *p;
980
+ pat_setpat_attr(&hw, q);
981
+ pat_loops[smp-1] = (q->uFlags & CHN_LOOP)? 1: 0;
982
+ if( hw.modes & PAT_16BIT ) p = (char *)SDL_malloc(hw.wave_size);
983
+ else p = (char *)SDL_malloc(hw.wave_size * sizeof(char)*2);
984
+ if( p ) {
985
+ if( hw.modes & PAT_16BIT ) {
986
+ dec_pat_Decompress16Bit((short int *)p, hw.wave_size>>1, gm - 1);
987
+ CSoundFile_ReadSample(cs, q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size);
988
+ }
989
+ else {
990
+ dec_pat_Decompress8Bit((short int *)p, hw.wave_size, gm - 1);
991
+ CSoundFile_ReadSample(cs, q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size * sizeof(short int));
992
+ }
993
+ SDL_free(p);
994
+ }
995
+ }
996
+ else {
997
+ char *p;
998
+ q->nC4Speed = C4SPD;
999
+ q->nLength = 30000;
1000
+ q->nLoopStart = 0;
1001
+ q->nLoopEnd = 30000;
1002
+ q->nVolume = 256;
1003
+ q->uFlags |= CHN_LOOP;
1004
+ q->uFlags |= CHN_16BIT;
1005
+ p = (char *)SDL_malloc(q->nLength*sizeof(char)*2);
1006
+ if( p ) {
1007
+ dec_pat_Decompress8Bit((short int *)p, q->nLength, smp + MAXSMP - 1);
1008
+ CSoundFile_ReadSample(cs, q, RS_PCM16S, (LPSTR)p, q->nLength*2);
1009
+ SDL_free(p);
1010
+ }
1011
+ }
1012
+ }
1013
+
1014
+ // =====================================================================================
1015
+ BOOL PAT_Load_Instruments(void *c)
1016
+ {
1017
+ uint32_t t;
1018
+ CSoundFile *of=(CSoundFile *)c;
1019
+ if( !pat_numsmp() ) pat_gmtosmp(1); // make sure there is a sample
1020
+ of->m_nSamples = pat_numsmp() + 1; // xmms modplug does not use slot zero
1021
+ of->m_nInstruments = pat_numinstr() + 1;
1022
+ for(t=1; t<of->m_nInstruments; t++) { // xmms modplug doesn't use slot zero
1023
+ if( (of->Headers[t] = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER))) == NULL ) return FALSE;
1024
+ SDL_memset(of->Headers[t], 0, sizeof(INSTRUMENTHEADER));
1025
+ PATinst(of->Headers[t], t, pat_smptogm(t));
1026
+ }
1027
+ for(t=1; t<of->m_nSamples; t++) { // xmms modplug doesn't use slot zero
1028
+ PATsample(of, &of->Ins[t], t, pat_smptogm(t));
1029
+ }
1030
+ // copy last of the mohicans to entry 0 for XMMS modinfo to work....
1031
+ t = of->m_nInstruments - 1;
1032
+ if( (of->Headers[0] = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER))) == NULL ) return FALSE;
1033
+ SDL_memcpy(of->Headers[0], of->Headers[t], sizeof(INSTRUMENTHEADER));
1034
+ t = of->m_nSamples - 1;
1035
+ SDL_memcpy(&of->Ins[0], &of->Ins[t], sizeof(MODINSTRUMENT));
1036
+ return TRUE;
1037
+ }
1038
+ // =====================================================================================
1039
+ BOOL CSoundFile_ReadPAT(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength)
1040
+ {
1041
+ static int avoid_reentry = 0;
1042
+ char buf[60];
1043
+ int t;
1044
+ PATHANDLE *h;
1045
+ int numpat;
1046
+ MMFILE mm, *mmfile;
1047
+ MODINSTRUMENT *q;
1048
+ INSTRUMENTHEADER *d;
1049
+ if( !CSoundFile_TestPAT(lpStream, dwMemLength) ) return FALSE;
1050
+ h = PAT_Init();
1051
+ if( !h ) return FALSE;
1052
+ mmfile = &mm;
1053
+ mm.mm = (char *)lpStream;
1054
+ mm.sz = dwMemLength;
1055
+ mm.pos = 0;
1056
+ mm.error = 0;
1057
+ while( avoid_reentry ) SDL_Delay(1);
1058
+ avoid_reentry = 1;
1059
+ pat_read_patname(h, mmfile);
1060
+ h->samples = pat_read_numsmp(mmfile);
1061
+ if( SDL_strlen(h->patname) )
1062
+ SDL_snprintf(buf,sizeof (buf),"%s canon %d-v (Fr. Jacques)", h->patname, h->samples);
1063
+ else
1064
+ SDL_snprintf(buf,sizeof (buf),"%d-voice canon (Fr. Jacques)", h->samples);
1065
+ if( SDL_strlen(buf) > 31 ) buf[31] = '\0'; // chop it of
1066
+ _this->m_nDefaultTempo = 60; // 120 / 2
1067
+ t = (h->samples - 1) * 16 + 128;
1068
+ if( t % 64 ) t += 64;
1069
+ t = t / 64;
1070
+ _this->m_nType = MOD_TYPE_PAT;
1071
+ _this->m_nInstruments = h->samples >= MAX_INSTRUMENTS-1 ? MAX_INSTRUMENTS-1 : h->samples + 1; // we know better but use each sample in the pat...
1072
+ _this->m_nSamples = h->samples >= MAX_SAMPLES-1 ? MAX_SAMPLES-1 : h->samples + 1; // xmms modplug does not use slot zero
1073
+ _this->m_nDefaultSpeed = 6;
1074
+ _this->m_nChannels = h->samples;
1075
+ numpat = t;
1076
+
1077
+ _this->m_dwSongFlags = SONG_LINEARSLIDES;
1078
+ _this->m_nMinPeriod = 28 << 2;
1079
+ _this->m_nMaxPeriod = 1712 << 3;
1080
+ // orderlist
1081
+ for(t=0; t < numpat; t++)
1082
+ _this->Order[t] = t;
1083
+ for(t=1; t<(int)_this->m_nInstruments; t++) { // xmms modplug doesn't use slot zero
1084
+ WaveHeader hw;
1085
+ char s[32];
1086
+ if( (d = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER))) == NULL ) {
1087
+ avoid_reentry = 0;
1088
+ return FALSE;
1089
+ }
1090
+ SDL_memset(d, 0, sizeof(INSTRUMENTHEADER));
1091
+ _this->Headers[t] = d;
1092
+ SDL_memset(d->filename, 0, 12);
1093
+ SDL_strlcpy((char *)d->filename, s, 12);
1094
+ pat_get_waveheader(mmfile, &hw, t);
1095
+ pat_setpat_inst(&hw, d, t);
1096
+ }
1097
+ for(t=1; t<(int)_this->m_nSamples; t++) { // xmms modplug doesn't use slot zero
1098
+ WaveHeader hw;
1099
+ char *p;
1100
+ q = &_this->Ins[t]; // we do not use slot zero
1101
+ q->nGlobalVol = 64;
1102
+ q->nPan = 128;
1103
+ q->uFlags = CHN_16BIT;
1104
+ pat_get_waveheader(mmfile, &hw, t);
1105
+ pat_setpat_attr(&hw, q);
1106
+ if ( hw.wave_size == 0 ) p = NULL;
1107
+ else if( hw.modes & PAT_16BIT ) p = (char *)SDL_malloc(hw.wave_size);
1108
+ else p = (char *)SDL_malloc(hw.wave_size * sizeof(char) * 2);
1109
+ if( p ) {
1110
+ mmreadSBYTES(p, hw.wave_size, mmfile);
1111
+ if( hw.modes & PAT_16BIT ) {
1112
+ CSoundFile_ReadSample(_this, q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size);
1113
+ }
1114
+ else {
1115
+ pat_blowup_to16bit((short int *)p, hw.wave_size);
1116
+ CSoundFile_ReadSample(_this, q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size * sizeof(short int));
1117
+ }
1118
+ SDL_free(p);
1119
+ }
1120
+ }
1121
+ // copy last of the mohicans to entry 0 for XMMS modinfo to work....
1122
+ t = _this->m_nInstruments - 1;
1123
+ if( (_this->Headers[0] = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER))) == NULL ) {
1124
+ avoid_reentry = 0;
1125
+ return FALSE;
1126
+ }
1127
+ SDL_memcpy(_this->Headers[0], _this->Headers[t], sizeof(INSTRUMENTHEADER));
1128
+ t = _this->m_nSamples - 1;
1129
+ SDL_memcpy(&_this->Ins[0], &_this->Ins[t], sizeof(MODINSTRUMENT));
1130
+ // ==============================
1131
+ // Load the pattern info now!
1132
+ PAT_ReadPatterns(_this->Patterns, _this->PatternSize, h, numpat);
1133
+ // ============================================================
1134
+ // set panning positions
1135
+ for(t=0; t<(int)_this->m_nChannels; t++) {
1136
+ _this->ChnSettings[t].nPan = 0x30+((t+2)%5)*((0xD0 - 0x30)/5); // 0x30 = std s3m val
1137
+ _this->ChnSettings[t].nVolume = 64;
1138
+ }
1139
+ avoid_reentry = 0; // it is safe now, I'm finished
1140
+ PAT_Cleanup(h); // we dont need it anymore
1141
+ return 1;
1142
+ }
1143
+