gosu 0.15.2 → 1.1.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) 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 +53 -39
  159. data/{Gosu → include/Gosu}/Audio.hpp +6 -8
  160. data/include/Gosu/Bitmap.hpp +100 -0
  161. data/{Gosu → include/Gosu}/Buttons.hpp +104 -44
  162. data/{Gosu → include/Gosu}/Color.hpp +0 -0
  163. data/{Gosu → include/Gosu}/Directories.hpp +0 -0
  164. data/{Gosu → include/Gosu}/Font.hpp +1 -1
  165. data/{Gosu → include/Gosu}/Fwd.hpp +0 -5
  166. data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
  167. data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
  168. data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
  169. data/{Gosu → include/Gosu}/IO.hpp +0 -0
  170. data/{Gosu → include/Gosu}/Image.hpp +7 -6
  171. data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
  172. data/{Gosu → include/Gosu}/Input.hpp +39 -51
  173. data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
  174. data/{Gosu → include/Gosu}/Math.hpp +0 -0
  175. data/{Gosu → include/Gosu}/Platform.hpp +0 -0
  176. data/{Gosu → include/Gosu}/Text.hpp +0 -0
  177. data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
  178. data/{Gosu → include/Gosu}/Timing.hpp +0 -0
  179. data/{Gosu → include/Gosu}/Utility.hpp +15 -4
  180. data/{Gosu → include/Gosu}/Version.hpp +3 -3
  181. data/{Gosu → include/Gosu}/Window.hpp +46 -34
  182. data/lib/OpenAL32.dll +0 -0
  183. data/lib/SDL2.dll +0 -0
  184. data/lib/gosu.rb +0 -3
  185. data/lib/gosu/patches.rb +0 -23
  186. data/lib/gosu/preview.rb +1 -3
  187. data/lib/gosu/swig_patches.rb +14 -12
  188. data/lib64/OpenAL32.dll +0 -0
  189. data/lib64/SDL2.dll +0 -0
  190. data/rdoc/gosu.rb +112 -23
  191. data/src/Audio.cpp +50 -224
  192. data/src/AudioFile.hpp +20 -37
  193. data/src/AudioFileAudioToolbox.cpp +237 -0
  194. data/src/AudioFileSDLSound.cpp +147 -0
  195. data/src/AudioImpl.cpp +3 -12
  196. data/src/AudioImpl.hpp +3 -1
  197. data/src/Bitmap.cpp +85 -83
  198. data/src/BitmapIO.cpp +52 -58
  199. data/src/Font.cpp +3 -1
  200. data/src/Graphics.cpp +7 -4
  201. data/src/Image.cpp +13 -16
  202. data/src/Input.cpp +412 -164
  203. data/src/LargeImageData.cpp +1 -1
  204. data/src/MarkupParser.cpp +2 -1
  205. data/src/Resolution.cpp +8 -8
  206. data/src/RubyGosu.cxx +1017 -196
  207. data/src/RubyGosu.h +4 -2
  208. data/src/TexChunk.cpp +1 -1
  209. data/src/TextBuilder.cpp +3 -1
  210. data/src/Texture.cpp +1 -1
  211. data/src/TrueTypeFont.cpp +1 -1
  212. data/src/TrueTypeFontWin.cpp +3 -3
  213. data/src/Utility.cpp +11 -7
  214. data/src/Window.cpp +90 -62
  215. data/src/WindowUIKit.cpp +21 -9
  216. metadata +194 -65
  217. data/Gosu/AutoLink.hpp +0 -14
  218. data/Gosu/Bitmap.hpp +0 -113
  219. data/Gosu/Channel.h +0 -25
  220. data/Gosu/Color.h +0 -38
  221. data/Gosu/Font.h +0 -36
  222. data/Gosu/Gosu.h +0 -79
  223. data/Gosu/Image.h +0 -54
  224. data/Gosu/Sample.h +0 -19
  225. data/Gosu/Song.h +0 -24
  226. data/Gosu/TextInput.h +0 -30
  227. data/Gosu/Window.h +0 -61
  228. data/lib/gosu/zen.rb +0 -89
  229. data/src/AudioToolboxFile.hpp +0 -210
  230. data/src/ChannelWrapper.cpp +0 -50
  231. data/src/ColorWrapper.cpp +0 -126
  232. data/src/Constants.cpp +0 -287
  233. data/src/FontWrapper.cpp +0 -74
  234. data/src/GosuWrapper.cpp +0 -232
  235. data/src/ImageWrapper.cpp +0 -168
  236. data/src/MPEGFile.hpp +0 -90
  237. data/src/OggFile.hpp +0 -92
  238. data/src/SampleWrapper.cpp +0 -30
  239. data/src/SndFile.hpp +0 -174
  240. data/src/SongWrapper.cpp +0 -52
  241. data/src/TextInputWrapper.cpp +0 -101
  242. data/src/WinMain.cpp +0 -64
  243. data/src/WindowWrapper.cpp +0 -289
@@ -0,0 +1,2350 @@
1
+ /*
2
+ * This source code is public domain.
3
+ *
4
+ * Authors: Olivier Lapicque <olivierl@jps.net>
5
+ */
6
+
7
+ #include "libmodplug.h"
8
+ #include <stdlib.h>
9
+ #include "tables.h"
10
+
11
+ DWORD CSoundFile_GetLength(CSoundFile *_this, BOOL bAdjust, BOOL bTotal)
12
+ //----------------------------------------------------
13
+ {
14
+ UINT dwElapsedTime=0, nRow=0, nCurrentPattern=0, nNextPattern=0, nPattern=0;
15
+ UINT nMusicSpeed=_this->m_nDefaultSpeed, nMusicTempo=_this->m_nDefaultTempo, nNextRow=0;
16
+ UINT nMaxRow = 0, nMaxPattern = 0;
17
+ LONG nGlbVol = _this->m_nDefaultGlobalVolume, nOldGlbVolSlide = 0;
18
+ BYTE samples[MAX_CHANNELS];
19
+ BYTE instr[MAX_CHANNELS];
20
+ BYTE notes[MAX_CHANNELS];
21
+ BYTE vols[MAX_CHANNELS];
22
+ BYTE oldparam[MAX_CHANNELS];
23
+ BYTE chnvols[MAX_CHANNELS];
24
+ DWORD patloop[MAX_CHANNELS];
25
+
26
+ SDL_memset(instr, 0, sizeof(instr));
27
+ SDL_memset(notes, 0, sizeof(notes));
28
+ SDL_memset(vols, 0xFF, sizeof(vols));
29
+ SDL_memset(patloop, 0, sizeof(patloop));
30
+ SDL_memset(oldparam, 0, sizeof(oldparam));
31
+ SDL_memset(chnvols, 64, sizeof(chnvols));
32
+ SDL_memset(samples, 0, sizeof(samples));
33
+ for (UINT icv=0; icv<_this->m_nChannels; icv++)
34
+ chnvols[icv] = _this->ChnSettings[icv].nVolume;
35
+ nMaxRow = _this->m_nNextRow;
36
+ nMaxPattern = _this->m_nNextPattern;
37
+ for (;;)
38
+ {
39
+ UINT nSpeedCount = 0;
40
+ nRow = nNextRow;
41
+ nCurrentPattern = nNextPattern;
42
+ // Check if pattern is valid
43
+ nPattern = _this->Order[nCurrentPattern];
44
+ while (nPattern >= MAX_PATTERNS)
45
+ {
46
+ // End of song ?
47
+ if ((nPattern == 0xFF) || (nCurrentPattern >= MAX_ORDERS))
48
+ {
49
+ goto EndMod;
50
+ } else
51
+ {
52
+ nCurrentPattern++;
53
+ nPattern = (nCurrentPattern < MAX_ORDERS) ? _this->Order[nCurrentPattern] : 0xFF;
54
+ }
55
+ nNextPattern = nCurrentPattern;
56
+ }
57
+ // Weird stuff?
58
+ if ((nPattern >= MAX_PATTERNS) || (!_this->Patterns[nPattern])) break;
59
+ // Should never happen
60
+ if (nRow >= _this->PatternSize[nPattern]) nRow = 0;
61
+ // Update next position
62
+ nNextRow = nRow + 1;
63
+ if (nNextRow >= _this->PatternSize[nPattern])
64
+ {
65
+ nNextPattern = nCurrentPattern + 1;
66
+ nNextRow = 0;
67
+ }
68
+ if (!nRow)
69
+ {
70
+ for (UINT ipck=0; ipck<_this->m_nChannels; ipck++) patloop[ipck] = dwElapsedTime;
71
+ }
72
+ if (!bTotal)
73
+ {
74
+ if ((nCurrentPattern > nMaxPattern) || ((nCurrentPattern == nMaxPattern) && (nRow >= nMaxRow)))
75
+ {
76
+ if (bAdjust)
77
+ {
78
+ _this->m_nMusicSpeed = nMusicSpeed;
79
+ _this->m_nMusicTempo = nMusicTempo;
80
+ }
81
+ break;
82
+ }
83
+ }
84
+ MODCHANNEL *pChn = _this->Chn;
85
+ MODCOMMAND *p = _this->Patterns[nPattern] + nRow * _this->m_nChannels;
86
+ for (UINT nChn=0; nChn<_this->m_nChannels; p++,pChn++, nChn++) if (*((DWORD *)p))
87
+ {
88
+ UINT command = p->command;
89
+ UINT param = p->param;
90
+ UINT note = p->note;
91
+ if (p->instr) { instr[nChn] = p->instr; notes[nChn] = 0; vols[nChn] = 0xFF; }
92
+ if ((note) && (note <= NOTE_MAX)) notes[nChn] = note;
93
+ if (p->volcmd == VOLCMD_VOLUME) { vols[nChn] = p->vol; }
94
+ if (command) switch (command)
95
+ {
96
+ // Position Jump
97
+ case CMD_POSITIONJUMP:
98
+ if (param <= nCurrentPattern) goto EndMod;
99
+ nNextPattern = param;
100
+ nNextRow = 0;
101
+ if (bAdjust)
102
+ {
103
+ pChn->nPatternLoopCount = 0;
104
+ pChn->nPatternLoop = 0;
105
+ }
106
+ break;
107
+ // Pattern Break
108
+ case CMD_PATTERNBREAK:
109
+ nNextRow = param;
110
+ nNextPattern = nCurrentPattern + 1;
111
+ if (bAdjust)
112
+ {
113
+ pChn->nPatternLoopCount = 0;
114
+ pChn->nPatternLoop = 0;
115
+ }
116
+ break;
117
+ // Set Speed
118
+ case CMD_SPEED:
119
+ if (!param) break;
120
+ if ((param <= 0x20) || (_this->m_nType != MOD_TYPE_MOD))
121
+ {
122
+ if (param < 128) nMusicSpeed = param;
123
+ }
124
+ break;
125
+ // Set Tempo
126
+ case CMD_TEMPO:
127
+ if ((bAdjust) && (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))
128
+ {
129
+ if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
130
+ }
131
+ if (param >= 0x20) nMusicTempo = param; else
132
+ // Tempo Slide
133
+ if ((param & 0xF0) == 0x10)
134
+ {
135
+ nMusicTempo += param & 0x0F;
136
+ if (nMusicTempo > 255) nMusicTempo = 255;
137
+ } else
138
+ {
139
+ nMusicTempo -= param & 0x0F;
140
+ if (nMusicTempo < 32) nMusicTempo = 32;
141
+ }
142
+ break;
143
+ // Pattern Delay
144
+ case CMD_S3MCMDEX:
145
+ if ((param & 0xF0) == 0x60) { nSpeedCount = param & 0x0F; break; } else
146
+ if ((param & 0xF0) == 0xB0) { param &= 0x0F; param |= 0x60; }
147
+ case CMD_MODCMDEX:
148
+ if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else
149
+ if ((param & 0xF0) == 0x60)
150
+ {
151
+ if (param & 0x0F) dwElapsedTime += (dwElapsedTime - patloop[nChn]) * (param & 0x0F);
152
+ else patloop[nChn] = dwElapsedTime;
153
+ }
154
+ break;
155
+ }
156
+ if (!bAdjust) continue;
157
+ switch(command)
158
+ {
159
+ // Portamento Up/Down
160
+ case CMD_PORTAMENTOUP:
161
+ case CMD_PORTAMENTODOWN:
162
+ if (param) pChn->nOldPortaUpDown = param;
163
+ break;
164
+ // Tone-Portamento
165
+ case CMD_TONEPORTAMENTO:
166
+ if (param) pChn->nPortamentoSlide = param << 2;
167
+ break;
168
+ // Offset
169
+ case CMD_OFFSET:
170
+ if (param) pChn->nOldOffset = param;
171
+ break;
172
+ // Volume Slide
173
+ case CMD_VOLUMESLIDE:
174
+ case CMD_TONEPORTAVOL:
175
+ case CMD_VIBRATOVOL:
176
+ if (param) pChn->nOldVolumeSlide = param;
177
+ break;
178
+ // Set Volume
179
+ case CMD_VOLUME:
180
+ vols[nChn] = param;
181
+ break;
182
+ // Global Volume
183
+ case CMD_GLOBALVOLUME:
184
+ if (!(_this->m_nType & (MOD_TYPE_IT))) param <<= 1;
185
+ if (param > 128) param = 128;
186
+ nGlbVol = param << 1;
187
+ break;
188
+ // Global Volume Slide
189
+ case CMD_GLOBALVOLSLIDE:
190
+ if (param) nOldGlbVolSlide = param; else param = nOldGlbVolSlide;
191
+ if (((param & 0x0F) == 0x0F) && (param & 0xF0))
192
+ {
193
+ param >>= 4;
194
+ if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
195
+ nGlbVol += param << 1;
196
+ } else
197
+ if (((param & 0xF0) == 0xF0) && (param & 0x0F))
198
+ {
199
+ param = (param & 0x0F) << 1;
200
+ if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
201
+ nGlbVol -= param;
202
+ } else
203
+ if (param & 0xF0)
204
+ {
205
+ param >>= 4;
206
+ param <<= 1;
207
+ if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
208
+ nGlbVol += param * nMusicSpeed;
209
+ } else
210
+ {
211
+ param = (param & 0x0F) << 1;
212
+ if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
213
+ nGlbVol -= param * nMusicSpeed;
214
+ }
215
+ if (nGlbVol < 0) nGlbVol = 0;
216
+ if (nGlbVol > 256) nGlbVol = 256;
217
+ break;
218
+ case CMD_CHANNELVOLUME:
219
+ if (param <= 64) chnvols[nChn] = param;
220
+ break;
221
+ case CMD_CHANNELVOLSLIDE:
222
+ if (param) oldparam[nChn] = param; else param = oldparam[nChn];
223
+ pChn->nOldChnVolSlide = param;
224
+ if (((param & 0x0F) == 0x0F) && (param & 0xF0))
225
+ {
226
+ param = (param >> 4) + chnvols[nChn];
227
+ } else
228
+ if (((param & 0xF0) == 0xF0) && (param & 0x0F))
229
+ {
230
+ if (chnvols[nChn] > (int)(param & 0x0F)) param = chnvols[nChn] - (param & 0x0F);
231
+ else param = 0;
232
+ } else
233
+ if (param & 0x0F)
234
+ {
235
+ param = (param & 0x0F) * nMusicSpeed;
236
+ param = (chnvols[nChn] > param) ? chnvols[nChn] - param : 0;
237
+ } else param = ((param & 0xF0) >> 4) * nMusicSpeed + chnvols[nChn];
238
+ if (param > 64) param = 64;
239
+ chnvols[nChn] = param;
240
+ break;
241
+ }
242
+ }
243
+ nSpeedCount += nMusicSpeed;
244
+ dwElapsedTime += (2500 * nSpeedCount) / nMusicTempo;
245
+ }
246
+ EndMod:
247
+ if ((bAdjust) && (!bTotal))
248
+ {
249
+ _this->m_nGlobalVolume = nGlbVol;
250
+ _this->m_nOldGlbVolSlide = nOldGlbVolSlide;
251
+ for (UINT n=0; n<_this->m_nChannels; n++)
252
+ {
253
+ _this->Chn[n].nGlobalVol = chnvols[n];
254
+ if (notes[n]) _this->Chn[n].nNewNote = notes[n];
255
+ if (instr[n]) _this->Chn[n].nNewIns = instr[n];
256
+ if (vols[n] != 0xFF)
257
+ {
258
+ if (vols[n] > 64) vols[n] = 64;
259
+ _this->Chn[n].nVolume = vols[n] << 2;
260
+ }
261
+ }
262
+ }
263
+ return (dwElapsedTime+500) / 1000;
264
+ }
265
+
266
+
267
+ //////////////////////////////////////////////////////////////////////////////////////////////////
268
+ // Effects
269
+
270
+ void CSoundFile_InstrumentChange(CSoundFile *_this, MODCHANNEL *pChn, UINT instr, BOOL bPorta, BOOL bUpdVol, BOOL bResetEnv)
271
+ //--------------------------------------------------------------------------------------------------------
272
+ {
273
+ BOOL bInstrumentChanged = FALSE;
274
+
275
+ if (instr >= MAX_INSTRUMENTS) return;
276
+ INSTRUMENTHEADER *penv = _this->Headers[instr];
277
+ MODINSTRUMENT *psmp = &_this->Ins[instr];
278
+ UINT note = pChn->nNewNote;
279
+ if ((penv) && (note) && (note <= 128))
280
+ {
281
+ if (penv->NoteMap[note-1] >= 0xFE) return;
282
+ UINT n = penv->Keyboard[note-1];
283
+ psmp = ((n) && (n < MAX_SAMPLES)) ? &_this->Ins[n] : NULL;
284
+ } else
285
+ if (_this->m_nInstruments)
286
+ {
287
+ if (note >= 0xFE) return;
288
+ psmp = NULL;
289
+ }
290
+ // Update Volume
291
+ if (bUpdVol) pChn->nVolume = (psmp) ? psmp->nVolume : 0;
292
+ // bInstrumentChanged is used for IT carry-on env option
293
+ if (penv != pChn->pHeader)
294
+ {
295
+ bInstrumentChanged = TRUE;
296
+ pChn->pHeader = penv;
297
+ } else
298
+ {
299
+ // Special XM hack
300
+ if ((bPorta) && (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (penv)
301
+ && (pChn->pInstrument) && (psmp != pChn->pInstrument))
302
+ {
303
+ // FT2 doesn't change the sample in this case,
304
+ // but still uses the sample info from the old one (bug?)
305
+ return;
306
+ }
307
+ }
308
+ // Instrument adjust
309
+ pChn->nNewIns = 0;
310
+ if (psmp)
311
+ {
312
+ if (penv)
313
+ {
314
+ pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6;
315
+ if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan;
316
+ pChn->nNNA = penv->nNNA;
317
+ } else
318
+ {
319
+ pChn->nInsVol = psmp->nGlobalVol;
320
+ }
321
+ if (psmp->uFlags & CHN_PANNING) pChn->nPan = psmp->nPan;
322
+ }
323
+ // Reset envelopes
324
+ if (bResetEnv)
325
+ {
326
+ if ((!bPorta) || (!(_this->m_nType & MOD_TYPE_IT)) || (_this->m_dwSongFlags & SONG_ITCOMPATMODE)
327
+ || (!pChn->nLength) || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)))
328
+ {
329
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
330
+ if ((_this->m_nType & MOD_TYPE_IT) && (!bInstrumentChanged) && (penv) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE))))
331
+ {
332
+ if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0;
333
+ if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0;
334
+ if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0;
335
+ } else
336
+ {
337
+ pChn->nVolEnvPosition = 0;
338
+ pChn->nPanEnvPosition = 0;
339
+ pChn->nPitchEnvPosition = 0;
340
+ }
341
+ pChn->nAutoVibDepth = 0;
342
+ pChn->nAutoVibPos = 0;
343
+ } else
344
+ if ((penv) && (!(penv->dwFlags & ENV_VOLUME)))
345
+ {
346
+ pChn->nVolEnvPosition = 0;
347
+ pChn->nAutoVibDepth = 0;
348
+ pChn->nAutoVibPos = 0;
349
+ }
350
+ }
351
+ // Invalid sample ?
352
+ if (!psmp)
353
+ {
354
+ pChn->pInstrument = NULL;
355
+ pChn->nInsVol = 0;
356
+ return;
357
+ }
358
+ // Tone-Portamento doesn't reset the pingpong direction flag
359
+ if ((bPorta) && (psmp == pChn->pInstrument))
360
+ {
361
+ if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) return;
362
+ pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE);
363
+ pChn->dwFlags = (pChn->dwFlags & (0xFFFFFF00 | CHN_PINGPONGFLAG)) | (psmp->uFlags);
364
+ } else
365
+ {
366
+ pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE|CHN_VOLENV|CHN_PANENV|CHN_PITCHENV);
367
+ pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (psmp->uFlags);
368
+ if (penv)
369
+ {
370
+ if (penv->dwFlags & ENV_VOLUME) pChn->dwFlags |= CHN_VOLENV;
371
+ if (penv->dwFlags & ENV_PANNING) pChn->dwFlags |= CHN_PANENV;
372
+ if (penv->dwFlags & ENV_PITCH) pChn->dwFlags |= CHN_PITCHENV;
373
+ if ((penv->dwFlags & ENV_PITCH) && (penv->dwFlags & ENV_FILTER))
374
+ {
375
+ if (!pChn->nCutOff) pChn->nCutOff = 0x7F;
376
+ }
377
+ if (penv->nIFC & 0x80) pChn->nCutOff = penv->nIFC & 0x7F;
378
+ if (penv->nIFR & 0x80) pChn->nResonance = penv->nIFR & 0x7F;
379
+ }
380
+ pChn->nVolSwing = pChn->nPanSwing = 0;
381
+ }
382
+ pChn->pInstrument = psmp;
383
+ pChn->nLength = psmp->nLength;
384
+ pChn->nLoopStart = psmp->nLoopStart;
385
+ pChn->nLoopEnd = psmp->nLoopEnd;
386
+ pChn->nC4Speed = psmp->nC4Speed;
387
+ pChn->pSample = psmp->pSample;
388
+ pChn->nTranspose = psmp->RelativeTone;
389
+ pChn->nFineTune = psmp->nFineTune;
390
+ if (pChn->dwFlags & CHN_SUSTAINLOOP)
391
+ {
392
+ pChn->nLoopStart = psmp->nSustainStart;
393
+ pChn->nLoopEnd = psmp->nSustainEnd;
394
+ pChn->dwFlags |= CHN_LOOP;
395
+ if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP;
396
+ }
397
+ if ((pChn->dwFlags & CHN_LOOP) && (pChn->nLoopEnd < pChn->nLength)) pChn->nLength = pChn->nLoopEnd;
398
+ }
399
+
400
+
401
+ void CSoundFile_NoteChange(CSoundFile *_this, UINT nChn, int note, BOOL bPorta, BOOL bResetEnv)
402
+ //---------------------------------------------------------------------------
403
+ {
404
+ if (note < 1) return;
405
+ MODCHANNEL * const pChn = &_this->Chn[nChn];
406
+ MODINSTRUMENT *pins = pChn->pInstrument;
407
+ INSTRUMENTHEADER *penv = pChn->pHeader;
408
+ if ((penv) && (note <= 0x80))
409
+ {
410
+ UINT n = penv->Keyboard[note - 1];
411
+ if ((n) && (n < MAX_SAMPLES)) pins = &_this->Ins[n];
412
+ note = penv->NoteMap[note-1];
413
+ }
414
+ // Key Off
415
+ if (note >= 0x80) // 0xFE or invalid note => key off
416
+ {
417
+ // Key Off
418
+ CSoundFile_KeyOff(_this, nChn);
419
+ // Note Cut
420
+ if (note == 0xFE)
421
+ {
422
+ pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
423
+ if ((!(_this->m_nType & MOD_TYPE_IT)) || (_this->m_nInstruments)) pChn->nVolume = 0;
424
+ pChn->nFadeOutVol = 0;
425
+ }
426
+ return;
427
+ }
428
+ if (!pins) return;
429
+ if ((!bPorta) && (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MT2)))
430
+ {
431
+ pChn->nTranspose = pins->RelativeTone;
432
+ pChn->nFineTune = pins->nFineTune;
433
+ }
434
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2|MOD_TYPE_MED)) note += pChn->nTranspose;
435
+ if (note < 1) note = 1;
436
+ if (note > 132) note = 132;
437
+ pChn->nNote = note;
438
+ if ((!bPorta) || (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) pChn->nNewIns = 0;
439
+ UINT period = CSoundFile_GetPeriodFromNote(_this, note, pChn->nFineTune, pChn->nC4Speed);
440
+ if (period)
441
+ {
442
+ if ((!bPorta) || (!pChn->nPeriod)) pChn->nPeriod = period;
443
+ pChn->nPortamentoDest = period;
444
+ if ((!bPorta) || ((!pChn->nLength) && (!(_this->m_nType & MOD_TYPE_S3M))))
445
+ {
446
+ pChn->pInstrument = pins;
447
+ pChn->pSample = pins->pSample;
448
+ pChn->nLength = pins->nLength;
449
+ pChn->nLoopEnd = pins->nLength;
450
+ pChn->nLoopStart = 0;
451
+ pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (pins->uFlags);
452
+ if (pChn->dwFlags & CHN_SUSTAINLOOP)
453
+ {
454
+ pChn->nLoopStart = pins->nSustainStart;
455
+ pChn->nLoopEnd = pins->nSustainEnd;
456
+ pChn->dwFlags &= ~CHN_PINGPONGLOOP;
457
+ pChn->dwFlags |= CHN_LOOP;
458
+ if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP;
459
+ if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
460
+ } else
461
+ if (pChn->dwFlags & CHN_LOOP)
462
+ {
463
+ pChn->nLoopStart = pins->nLoopStart;
464
+ pChn->nLoopEnd = pins->nLoopEnd;
465
+ if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
466
+ }
467
+ pChn->nPos = 0;
468
+ pChn->nPosLo = 0;
469
+ if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((_this->m_nType & MOD_TYPE_IT) && (!(_this->m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0;
470
+ if (pChn->nTremoloType < 4) pChn->nTremoloPos = 0;
471
+ }
472
+ if (pChn->nPos >= pChn->nLength) pChn->nPos = pChn->nLoopStart;
473
+ } else bPorta = FALSE;
474
+ if ((!bPorta) || (!(_this->m_nType & MOD_TYPE_IT))
475
+ || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))
476
+ || ((_this->m_dwSongFlags & SONG_ITCOMPATMODE) && (pChn->nRowInstr)))
477
+ {
478
+ if ((_this->m_nType & MOD_TYPE_IT) && (pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))
479
+ {
480
+ pChn->nVolEnvPosition = 0;
481
+ pChn->nPanEnvPosition = 0;
482
+ pChn->nPitchEnvPosition = 0;
483
+ pChn->nAutoVibDepth = 0;
484
+ pChn->nAutoVibPos = 0;
485
+ pChn->dwFlags &= ~CHN_NOTEFADE;
486
+ pChn->nFadeOutVol = 65536;
487
+ }
488
+ if ((!bPorta) || (!(_this->m_dwSongFlags & SONG_ITCOMPATMODE)) || (pChn->nRowInstr))
489
+ {
490
+ if ((!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) || (pChn->nRowInstr))
491
+ {
492
+ pChn->dwFlags &= ~CHN_NOTEFADE;
493
+ pChn->nFadeOutVol = 65536;
494
+ }
495
+ }
496
+ }
497
+ pChn->dwFlags &= ~(CHN_EXTRALOUD|CHN_KEYOFF);
498
+ // Enable Ramping
499
+ if (!bPorta)
500
+ {
501
+ pChn->dwFlags &= ~CHN_FILTER;
502
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
503
+ pChn->nRetrigCount = 0;
504
+ pChn->nTremorCount = 0;
505
+ if (bResetEnv)
506
+ {
507
+ pChn->nVolSwing = pChn->nPanSwing = 0;
508
+ if (penv)
509
+ {
510
+ if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0;
511
+ if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0;
512
+ if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0;
513
+ if (_this->m_nType & MOD_TYPE_IT)
514
+ {
515
+ // Volume Swing
516
+ if (penv->nVolSwing)
517
+ {
518
+ int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
519
+ pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128);
520
+ }
521
+ // Pan Swing
522
+ if (penv->nPanSwing)
523
+ {
524
+ int d = ((LONG)penv->nPanSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
525
+ pChn->nPanSwing = (signed short)d;
526
+ }
527
+ }
528
+ }
529
+ pChn->nAutoVibDepth = 0;
530
+ pChn->nAutoVibPos = 0;
531
+ }
532
+ pChn->nLeftVol = pChn->nRightVol = 0;
533
+ BOOL bFlt = (_this->m_dwSongFlags & SONG_MPTFILTERMODE) ? FALSE : TRUE;
534
+ // Setup Initial Filter for this note
535
+ if (penv)
536
+ {
537
+ if (penv->nIFR & 0x80) { pChn->nResonance = penv->nIFR & 0x7F; bFlt = TRUE; }
538
+ if (penv->nIFC & 0x80) { pChn->nCutOff = penv->nIFC & 0x7F; bFlt = TRUE; }
539
+ } else
540
+ {
541
+ pChn->nVolSwing = pChn->nPanSwing = 0;
542
+ }
543
+ #ifndef NO_FILTER
544
+ if ((pChn->nCutOff < 0x7F) && (bFlt)) CSoundFile_SetupChannelFilter(_this, pChn, TRUE, 256);
545
+ #endif // NO_FILTER
546
+ }
547
+ }
548
+
549
+
550
+ UINT CSoundFile_GetNNAChannel(CSoundFile *_this, UINT nChn)
551
+ //---------------------------------------------
552
+ {
553
+ const MODCHANNEL *pChn = &_this->Chn[nChn];
554
+ // Check for empty channel
555
+ const MODCHANNEL *pi = &_this->Chn[_this->m_nChannels];
556
+ for (UINT i=_this->m_nChannels; i<MAX_CHANNELS; i++, pi++) if (!pi->nLength) return i;
557
+ if (!pChn->nFadeOutVol) return 0;
558
+ // All channels are used: check for lowest volume
559
+ UINT result = 0;
560
+ DWORD vol = 64*65536; // 25%
561
+ DWORD envpos = 0xFFFFFF;
562
+ const MODCHANNEL *pj = &_this->Chn[_this->m_nChannels];
563
+ for (UINT j=_this->m_nChannels; j<MAX_CHANNELS; j++, pj++)
564
+ {
565
+ if (!pj->nFadeOutVol) return j;
566
+ DWORD v = pj->nVolume;
567
+ if (pj->dwFlags & CHN_NOTEFADE)
568
+ v = v * pj->nFadeOutVol;
569
+ else
570
+ v <<= 16;
571
+ if (pj->dwFlags & CHN_LOOP) v >>= 1;
572
+ if ((v < vol) || ((v == vol) && (pj->nVolEnvPosition > envpos)))
573
+ {
574
+ envpos = pj->nVolEnvPosition;
575
+ vol = v;
576
+ result = j;
577
+ }
578
+ }
579
+ return result;
580
+ }
581
+
582
+
583
+ void CSoundFile_CheckNNA(CSoundFile *_this, UINT nChn, UINT instr, int note, BOOL bForceCut)
584
+ //------------------------------------------------------------------------
585
+ {
586
+ MODCHANNEL *pChn = &_this->Chn[nChn];
587
+ INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader = 0;
588
+ signed char *pSample;
589
+ if (note > 0x80) note = 0;
590
+ if (note < 1) return;
591
+ // Always NNA cut - using
592
+ if ((!(_this->m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!_this->m_nInstruments) || (bForceCut))
593
+ {
594
+ if ((_this->m_dwSongFlags & SONG_CPUVERYHIGH)
595
+ || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE)
596
+ || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return;
597
+ UINT n = CSoundFile_GetNNAChannel(_this, nChn);
598
+ if (!n) return;
599
+ MODCHANNEL *p = &_this->Chn[n];
600
+ // Copy Channel
601
+ SDL_memcpy(p, pChn, sizeof (*p));
602
+ p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
603
+ p->nMasterChn = nChn+1;
604
+ p->nCommand = 0;
605
+ // Cut the note
606
+ p->nFadeOutVol = 0;
607
+ p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
608
+ // Stop this channel
609
+ pChn->nLength = pChn->nPos = pChn->nPosLo = 0;
610
+ pChn->nROfs = pChn->nLOfs = 0;
611
+ pChn->nLeftVol = pChn->nRightVol = 0;
612
+ return;
613
+ }
614
+ if (instr >= MAX_INSTRUMENTS) instr = 0;
615
+ pSample = pChn->pSample;
616
+ pHeader = pChn->pHeader;
617
+ if ((instr) && (note))
618
+ {
619
+ pHeader = _this->Headers[instr];
620
+ if (pHeader)
621
+ {
622
+ UINT n = 0;
623
+ if (note <= 0x80)
624
+ {
625
+ n = pHeader->Keyboard[note-1];
626
+ note = pHeader->NoteMap[note-1];
627
+ if ((n) && (n < MAX_SAMPLES)) pSample = _this->Ins[n].pSample;
628
+ }
629
+ } else pSample = NULL;
630
+ }
631
+ if (!penv) return;
632
+ MODCHANNEL *p = pChn;
633
+ for (UINT i=nChn; i<MAX_CHANNELS; p++, i++)
634
+ if ((i >= _this->m_nChannels) || (p == pChn))
635
+ {
636
+ if (((p->nMasterChn == nChn+1) || (p == pChn)) && (p->pHeader))
637
+ {
638
+ BOOL bOk = FALSE;
639
+ // Duplicate Check Type
640
+ switch(p->pHeader->nDCT)
641
+ {
642
+ // Note
643
+ case DCT_NOTE:
644
+ if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE;
645
+ break;
646
+ // Sample
647
+ case DCT_SAMPLE:
648
+ if ((pSample) && (pSample == p->pSample)) bOk = TRUE;
649
+ break;
650
+ // Instrument
651
+ case DCT_INSTRUMENT:
652
+ if (pHeader == p->pHeader) bOk = TRUE;
653
+ break;
654
+ }
655
+ // Duplicate Note Action
656
+ if (bOk)
657
+ {
658
+ switch(p->pHeader->nDNA)
659
+ {
660
+ // Cut
661
+ case DNA_NOTECUT:
662
+ CSoundFile_KeyOff(_this, i);
663
+ p->nVolume = 0;
664
+ break;
665
+ // Note Off
666
+ case DNA_NOTEOFF:
667
+ CSoundFile_KeyOff(_this, i);
668
+ break;
669
+ // Note Fade
670
+ case DNA_NOTEFADE:
671
+ p->dwFlags |= CHN_NOTEFADE;
672
+ break;
673
+ }
674
+ if (!p->nVolume)
675
+ {
676
+ p->nFadeOutVol = 0;
677
+ p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
678
+ }
679
+ }
680
+ }
681
+ }
682
+ if (pChn->dwFlags & CHN_MUTE) return;
683
+ // New Note Action
684
+ if ((pChn->nVolume) && (pChn->nLength))
685
+ {
686
+ UINT n = CSoundFile_GetNNAChannel(_this, nChn);
687
+ if (n)
688
+ {
689
+ MODCHANNEL *p = &_this->Chn[n];
690
+ // Copy Channel
691
+ SDL_memcpy(p, pChn, sizeof (*p));
692
+ p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
693
+ p->nMasterChn = nChn+1;
694
+ p->nCommand = 0;
695
+ // Key Off the note
696
+ switch(pChn->nNNA)
697
+ {
698
+ case NNA_NOTEOFF: CSoundFile_KeyOff(_this, n); break;
699
+ case NNA_NOTECUT:
700
+ p->nFadeOutVol = 0;
701
+ case NNA_NOTEFADE: p->dwFlags |= CHN_NOTEFADE; break;
702
+ }
703
+ if (!p->nVolume)
704
+ {
705
+ p->nFadeOutVol = 0;
706
+ p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
707
+ }
708
+ // Stop this channel
709
+ pChn->nLength = pChn->nPos = pChn->nPosLo = 0;
710
+ pChn->nROfs = pChn->nLOfs = 0;
711
+ }
712
+ }
713
+ }
714
+
715
+
716
+ BOOL CSoundFile_ProcessEffects(CSoundFile *_this)
717
+ //-------------------------------
718
+ {
719
+ MODCHANNEL *pChn = _this->Chn;
720
+ int nBreakRow = -1, nPosJump = -1, nPatLoopRow = -1;
721
+
722
+ for (UINT nChn=0; nChn<_this->m_nChannels; nChn++, pChn++)
723
+ {
724
+ UINT instr = pChn->nRowInstr;
725
+ UINT volcmd = pChn->nRowVolCmd;
726
+ UINT vol = pChn->nRowVolume;
727
+ UINT cmd = pChn->nRowCommand;
728
+ UINT param = pChn->nRowParam;
729
+ int bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE;
730
+ UINT nStartTick = 0;
731
+
732
+ pChn->dwFlags &= ~CHN_FASTVOLRAMP;
733
+ // Process special effects (note delay, pattern delay, pattern loop)
734
+ if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX))
735
+ {
736
+ if ((!param) && (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param;
737
+ // Note Delay ?
738
+ if ((param & 0xF0) == 0xD0)
739
+ {
740
+ nStartTick = param & 0x0F;
741
+ } else
742
+ if (!_this->m_nTickCount)
743
+ {
744
+ // Pattern Loop ?
745
+ if ((((param & 0xF0) == 0x60) && (cmd == CMD_MODCMDEX))
746
+ || (((param & 0xF0) == 0xB0) && (cmd == CMD_S3MCMDEX)))
747
+ {
748
+ int nloop = CSoundFile_PatternLoop(_this, pChn, param & 0x0F);
749
+ if (nloop >= 0) nPatLoopRow = nloop;
750
+ } else
751
+ // Pattern Delay
752
+ if ((param & 0xF0) == 0xE0)
753
+ {
754
+ _this->m_nPatternDelay = param & 0x0F;
755
+ }
756
+ }
757
+ }
758
+
759
+ // Handles note/instrument/volume changes
760
+ if (_this->m_nTickCount == nStartTick) // can be delayed by a note delay effect
761
+ {
762
+ UINT note = pChn->nRowNote;
763
+ if (instr) pChn->nNewIns = instr;
764
+ // XM: Key-Off + Sample == Note Cut
765
+ if (_this->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2))
766
+ {
767
+ if ((note == 0xFF) && ((!pChn->pHeader) || (!(pChn->pHeader->dwFlags & ENV_VOLUME))))
768
+ {
769
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
770
+ pChn->nVolume = 0;
771
+ note = instr = 0;
772
+ }
773
+ }
774
+ if ((!note) && (instr))
775
+ {
776
+ if (_this->m_nInstruments)
777
+ {
778
+ if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume;
779
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
780
+ {
781
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
782
+ pChn->nVolEnvPosition = 0;
783
+ pChn->nPanEnvPosition = 0;
784
+ pChn->nPitchEnvPosition = 0;
785
+ pChn->nAutoVibDepth = 0;
786
+ pChn->nAutoVibPos = 0;
787
+ pChn->dwFlags &= ~CHN_NOTEFADE;
788
+ pChn->nFadeOutVol = 65536;
789
+ }
790
+ } else
791
+ {
792
+ if (instr < MAX_SAMPLES) pChn->nVolume = _this->Ins[instr].nVolume;
793
+ }
794
+ if (!(_this->m_nType & MOD_TYPE_IT)) instr = 0;
795
+ }
796
+ // Invalid Instrument ?
797
+ if (instr >= MAX_INSTRUMENTS) instr = 0;
798
+ // Note Cut/Off => ignore instrument
799
+ if (note >= 0xFE) instr = 0;
800
+ if ((note) && (note <= 128)) pChn->nNewNote = note;
801
+ // New Note Action ?
802
+ if ((note) && (note <= 128) && (!bPorta))
803
+ {
804
+ CSoundFile_CheckNNA(_this, nChn, instr, note, FALSE);
805
+ }
806
+ // Instrument Change ?
807
+ if (instr)
808
+ {
809
+ MODINSTRUMENT *psmp = pChn->pInstrument;
810
+ CSoundFile_InstrumentChange(_this, pChn, instr, bPorta, TRUE, TRUE);
811
+ pChn->nNewIns = 0;
812
+ // Special IT case: portamento+note causes sample change -> ignore portamento
813
+ if ((_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
814
+ && (psmp != pChn->pInstrument) && (note) && (note < 0x80))
815
+ {
816
+ bPorta = FALSE;
817
+ }
818
+ }
819
+ // New Note ?
820
+ if (note)
821
+ {
822
+ if ((!instr) && (pChn->nNewIns) && (note < 0x80))
823
+ {
824
+ CSoundFile_InstrumentChange(_this, pChn, pChn->nNewIns, bPorta, FALSE, (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
825
+ pChn->nNewIns = 0;
826
+ }
827
+ CSoundFile_NoteChange(_this, nChn, note, bPorta, (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
828
+ if ((bPorta) && (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (instr))
829
+ {
830
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
831
+ pChn->nVolEnvPosition = 0;
832
+ pChn->nPanEnvPosition = 0;
833
+ pChn->nPitchEnvPosition = 0;
834
+ pChn->nAutoVibDepth = 0;
835
+ pChn->nAutoVibPos = 0;
836
+ }
837
+ }
838
+ // Tick-0 only volume commands
839
+ if (volcmd == VOLCMD_VOLUME)
840
+ {
841
+ if (vol > 64) vol = 64;
842
+ pChn->nVolume = vol << 2;
843
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
844
+ } else
845
+ if (volcmd == VOLCMD_PANNING)
846
+ {
847
+ if (vol > 64) vol = 64;
848
+ pChn->nPan = vol << 2;
849
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
850
+ }
851
+ }
852
+
853
+ // Volume Column Effect (except volume & panning)
854
+ if ((volcmd > VOLCMD_PANNING) && (_this->m_nTickCount >= nStartTick))
855
+ {
856
+ if (volcmd == VOLCMD_TONEPORTAMENTO)
857
+ {
858
+ if (_this->m_nType & MOD_TYPE_IT)
859
+ CSoundFile_TonePortamento(_this, pChn, ImpulseTrackerPortaVolCmd[vol & 0x0F]);
860
+ else
861
+ CSoundFile_TonePortamento(_this, pChn, vol * 16);
862
+ } else
863
+ {
864
+ if (vol) pChn->nOldVolParam = vol; else vol = pChn->nOldVolParam;
865
+ switch(volcmd)
866
+ {
867
+ case VOLCMD_VOLSLIDEUP:
868
+ CSoundFile_VolumeSlide(_this, pChn, vol << 4);
869
+ break;
870
+
871
+ case VOLCMD_VOLSLIDEDOWN:
872
+ CSoundFile_VolumeSlide(_this, pChn, vol);
873
+ break;
874
+
875
+ case VOLCMD_FINEVOLUP:
876
+ if (_this->m_nType & MOD_TYPE_IT)
877
+ {
878
+ if (_this->m_nTickCount == nStartTick) CSoundFile_VolumeSlide(_this, pChn, (vol << 4) | 0x0F);
879
+ } else
880
+ CSoundFile_FineVolumeUp(_this, pChn, vol);
881
+ break;
882
+
883
+ case VOLCMD_FINEVOLDOWN:
884
+ if (_this->m_nType & MOD_TYPE_IT)
885
+ {
886
+ if (_this->m_nTickCount == nStartTick) CSoundFile_VolumeSlide(_this, pChn, 0xF0 | vol);
887
+ } else
888
+ CSoundFile_FineVolumeDown(_this, pChn, vol);
889
+ break;
890
+
891
+ case VOLCMD_VIBRATOSPEED:
892
+ CSoundFile_Vibrato(_this, pChn, vol << 4);
893
+ break;
894
+
895
+ case VOLCMD_VIBRATO:
896
+ CSoundFile_Vibrato(_this, pChn, vol);
897
+ break;
898
+
899
+ case VOLCMD_PANSLIDELEFT:
900
+ CSoundFile_PanningSlide(_this, pChn, vol);
901
+ break;
902
+
903
+ case VOLCMD_PANSLIDERIGHT:
904
+ CSoundFile_PanningSlide(_this, pChn, vol << 4);
905
+ break;
906
+
907
+ case VOLCMD_PORTAUP:
908
+ CSoundFile_PortamentoUp(_this, pChn, vol << 2);
909
+ break;
910
+
911
+ case VOLCMD_PORTADOWN:
912
+ CSoundFile_PortamentoDown(_this, pChn, vol << 2);
913
+ break;
914
+ }
915
+ }
916
+ }
917
+
918
+ // Effects
919
+ if (cmd) switch (cmd)
920
+ {
921
+ // Set Volume
922
+ case CMD_VOLUME:
923
+ if (!_this->m_nTickCount)
924
+ {
925
+ pChn->nVolume = (param < 64) ? param*4 : 256;
926
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
927
+ }
928
+ break;
929
+
930
+ // Portamento Up
931
+ case CMD_PORTAMENTOUP:
932
+ if ((!param) && (_this->m_nType & MOD_TYPE_MOD)) break;
933
+ CSoundFile_PortamentoUp(_this, pChn, param);
934
+ break;
935
+
936
+ // Portamento Down
937
+ case CMD_PORTAMENTODOWN:
938
+ if ((!param) && (_this->m_nType & MOD_TYPE_MOD)) break;
939
+ CSoundFile_PortamentoDown(_this, pChn, param);
940
+ break;
941
+
942
+ // Volume Slide
943
+ case CMD_VOLUMESLIDE:
944
+ if ((param) || (_this->m_nType != MOD_TYPE_MOD)) CSoundFile_VolumeSlide(_this, pChn, param);
945
+ break;
946
+
947
+ // Tone-Portamento
948
+ case CMD_TONEPORTAMENTO:
949
+ CSoundFile_TonePortamento(_this, pChn, param);
950
+ break;
951
+
952
+ // Tone-Portamento + Volume Slide
953
+ case CMD_TONEPORTAVOL:
954
+ if ((param) || (_this->m_nType != MOD_TYPE_MOD)) CSoundFile_VolumeSlide(_this, pChn, param);
955
+ CSoundFile_TonePortamento(_this, pChn, 0);
956
+ break;
957
+
958
+ // Vibrato
959
+ case CMD_VIBRATO:
960
+ CSoundFile_Vibrato(_this, pChn, param);
961
+ break;
962
+
963
+ // Vibrato + Volume Slide
964
+ case CMD_VIBRATOVOL:
965
+ if ((param) || (_this->m_nType != MOD_TYPE_MOD)) CSoundFile_VolumeSlide(_this, pChn, param);
966
+ CSoundFile_Vibrato(_this, pChn, 0);
967
+ break;
968
+
969
+ // Set Speed
970
+ case CMD_SPEED:
971
+ if (!_this->m_nTickCount) CSoundFile_SetSpeed(_this, param);
972
+ break;
973
+
974
+ // Set Tempo
975
+ case CMD_TEMPO:
976
+ if (!_this->m_nTickCount)
977
+ {
978
+ if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
979
+ {
980
+ if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
981
+ }
982
+ CSoundFile_SetTempo(_this, param);
983
+ }
984
+ break;
985
+
986
+ // Set Offset
987
+ case CMD_OFFSET:
988
+ if (_this->m_nTickCount) break;
989
+ if (param) pChn->nOldOffset = param; else param = pChn->nOldOffset;
990
+ param <<= 8;
991
+ param |= (UINT)(pChn->nOldHiOffset) << 16;
992
+ if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
993
+ {
994
+ if (bPorta)
995
+ pChn->nPos = param;
996
+ else
997
+ pChn->nPos += param;
998
+ if (pChn->nPos >= pChn->nLength)
999
+ {
1000
+ if (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))
1001
+ {
1002
+ pChn->nPos = pChn->nLoopStart;
1003
+ if ((_this->m_dwSongFlags & SONG_ITOLDEFFECTS) && (pChn->nLength > 4))
1004
+ {
1005
+ pChn->nPos = pChn->nLength - 2;
1006
+ }
1007
+ }
1008
+ }
1009
+ } else
1010
+ if ((param < pChn->nLength) && (_this->m_nType & (MOD_TYPE_MTM|MOD_TYPE_DMF)))
1011
+ {
1012
+ pChn->nPos = param;
1013
+ }
1014
+ break;
1015
+
1016
+ // Arpeggio
1017
+ case CMD_ARPEGGIO:
1018
+ if ((_this->m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break;
1019
+ if ((!param) && (!(_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break;
1020
+ pChn->nCommand = CMD_ARPEGGIO;
1021
+ if (param) pChn->nArpeggio = param;
1022
+ break;
1023
+
1024
+ // Retrig
1025
+ case CMD_RETRIG:
1026
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1027
+ {
1028
+ if (!(param & 0xF0)) param |= pChn->nRetrigParam & 0xF0;
1029
+ if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F;
1030
+ param |= 0x100; // increment retrig count on first row
1031
+ }
1032
+ if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam;
1033
+ CSoundFile_RetrigNote(_this, nChn, param);
1034
+ break;
1035
+
1036
+ // Tremor
1037
+ case CMD_TREMOR:
1038
+ if (_this->m_nTickCount) break;
1039
+ pChn->nCommand = CMD_TREMOR;
1040
+ if (param) pChn->nTremorParam = param;
1041
+ break;
1042
+
1043
+ // Set Global Volume
1044
+ case CMD_GLOBALVOLUME:
1045
+ if (_this->m_nTickCount) break;
1046
+ if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
1047
+ if (param > 128) param = 128;
1048
+ _this->m_nGlobalVolume = param << 1;
1049
+ break;
1050
+
1051
+ // Global Volume Slide
1052
+ case CMD_GLOBALVOLSLIDE:
1053
+ CSoundFile_GlobalVolSlide(_this, param);
1054
+ break;
1055
+
1056
+ // Set 8-bit Panning
1057
+ case CMD_PANNING8:
1058
+ if (_this->m_nTickCount) break;
1059
+ if (!(_this->m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND;
1060
+ if (_this->m_nType & (MOD_TYPE_IT|MOD_TYPE_XM|MOD_TYPE_MT2))
1061
+ {
1062
+ pChn->nPan = param;
1063
+ } else
1064
+ if (param <= 0x80)
1065
+ {
1066
+ pChn->nPan = param << 1;
1067
+ } else
1068
+ if (param == 0xA4)
1069
+ {
1070
+ pChn->dwFlags |= CHN_SURROUND;
1071
+ pChn->nPan = 0x80;
1072
+ }
1073
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
1074
+ break;
1075
+
1076
+ // Panning Slide
1077
+ case CMD_PANNINGSLIDE:
1078
+ CSoundFile_PanningSlide(_this, pChn, param);
1079
+ break;
1080
+
1081
+ // Tremolo
1082
+ case CMD_TREMOLO:
1083
+ CSoundFile_Tremolo(_this, pChn, param);
1084
+ break;
1085
+
1086
+ // Fine Vibrato
1087
+ case CMD_FINEVIBRATO:
1088
+ CSoundFile_FineVibrato(_this, pChn, param);
1089
+ break;
1090
+
1091
+ // MOD/XM Exx Extended Commands
1092
+ case CMD_MODCMDEX:
1093
+ CSoundFile_ExtendedMODCommands(_this, nChn, param);
1094
+ break;
1095
+
1096
+ // S3M/IT Sxx Extended Commands
1097
+ case CMD_S3MCMDEX:
1098
+ CSoundFile_ExtendedS3MCommands(_this, nChn, param);
1099
+ break;
1100
+
1101
+ // Key Off
1102
+ case CMD_KEYOFF:
1103
+ if (!_this->m_nTickCount) CSoundFile_KeyOff(_this, nChn);
1104
+ break;
1105
+
1106
+ // Extra-fine porta up/down
1107
+ case CMD_XFINEPORTAUPDOWN:
1108
+ switch(param & 0xF0)
1109
+ {
1110
+ case 0x10: CSoundFile_ExtraFinePortamentoUp(_this, pChn, param & 0x0F); break;
1111
+ case 0x20: CSoundFile_ExtraFinePortamentoDown(_this, pChn, param & 0x0F); break;
1112
+ // Modplug XM Extensions
1113
+ case 0x50:
1114
+ case 0x60:
1115
+ case 0x70:
1116
+ case 0x90:
1117
+ case 0xA0: CSoundFile_ExtendedS3MCommands(_this, nChn, param); break;
1118
+ }
1119
+ break;
1120
+
1121
+ // Set Channel Global Volume
1122
+ case CMD_CHANNELVOLUME:
1123
+ if (_this->m_nTickCount) break;
1124
+ if (param <= 64)
1125
+ {
1126
+ pChn->nGlobalVol = param;
1127
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
1128
+ }
1129
+ break;
1130
+
1131
+ // Channel volume slide
1132
+ case CMD_CHANNELVOLSLIDE:
1133
+ CSoundFile_ChannelVolSlide(_this, pChn, param);
1134
+ break;
1135
+
1136
+ // Panbrello (IT)
1137
+ case CMD_PANBRELLO:
1138
+ CSoundFile_Panbrello(_this, pChn, param);
1139
+ break;
1140
+
1141
+ // Set Envelope Position
1142
+ case CMD_SETENVPOSITION:
1143
+ if (!_this->m_nTickCount)
1144
+ {
1145
+ pChn->nVolEnvPosition = param;
1146
+ pChn->nPanEnvPosition = param;
1147
+ pChn->nPitchEnvPosition = param;
1148
+ if (pChn->pHeader)
1149
+ {
1150
+ INSTRUMENTHEADER *penv = pChn->pHeader;
1151
+ if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1]))
1152
+ {
1153
+ pChn->dwFlags &= ~CHN_PANENV;
1154
+ }
1155
+ }
1156
+ }
1157
+ break;
1158
+
1159
+ // Position Jump
1160
+ case CMD_POSITIONJUMP:
1161
+ nPosJump = param;
1162
+ break;
1163
+
1164
+ // Pattern Break
1165
+ case CMD_PATTERNBREAK:
1166
+ nBreakRow = param;
1167
+ break;
1168
+
1169
+ // Midi Controller
1170
+ case CMD_MIDI:
1171
+ if (_this->m_nTickCount) break;
1172
+ if (param < 0x80){
1173
+ CSoundFile_ProcessMidiMacro(_this, nChn, &_this->m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro << 5], param);
1174
+ } else {
1175
+ CSoundFile_ProcessMidiMacro(_this, nChn, &_this->m_MidiCfg.szMidiZXXExt[(param & 0x7F) << 5], 0);
1176
+ }
1177
+ break;
1178
+ }
1179
+ }
1180
+
1181
+ // Navigation Effects
1182
+ if (!_this->m_nTickCount)
1183
+ {
1184
+ // Pattern Loop
1185
+ if (nPatLoopRow >= 0)
1186
+ {
1187
+ _this->m_nNextPattern = _this->m_nCurrentPattern;
1188
+ _this->m_nNextRow = nPatLoopRow;
1189
+ if (_this->m_nPatternDelay) _this->m_nNextRow++;
1190
+ } else
1191
+ // Pattern Break / Position Jump only if no loop running
1192
+ if ((nBreakRow >= 0) || (nPosJump >= 0))
1193
+ {
1194
+ BOOL bNoLoop = FALSE;
1195
+ if (nPosJump < 0) nPosJump = _this->m_nCurrentPattern+1;
1196
+ if (nBreakRow < 0) nBreakRow = 0;
1197
+ // Modplug Tracker & ModPlugin allow backward jumps
1198
+ if ((nPosJump < (int)_this->m_nCurrentPattern)
1199
+ || ((nPosJump == (int)_this->m_nCurrentPattern) && (nBreakRow <= (int)_this->m_nRow)))
1200
+ {
1201
+ if (!CSoundFile_IsValidBackwardJump(_this, _this->m_nCurrentPattern, _this->m_nRow, nPosJump, nBreakRow))
1202
+ {
1203
+ if (_this->m_nRepeatCount)
1204
+ {
1205
+ if (_this->m_nRepeatCount > 0) _this->m_nRepeatCount--;
1206
+ } else
1207
+ {
1208
+ #ifdef MODPLUG_TRACKER
1209
+ if (_this->gdwSoundSetup & SNDMIX_NOBACKWARDJUMPS)
1210
+ #endif
1211
+ // Backward jump disabled
1212
+ bNoLoop = TRUE;
1213
+ //reset repeat count incase there are multiple loops.
1214
+ //(i.e. Unreal tracks)
1215
+ _this->m_nRepeatCount = _this->m_nInitialRepeatCount;
1216
+ }
1217
+ }
1218
+ }
1219
+ if (((!bNoLoop) && (nPosJump < MAX_ORDERS))
1220
+ && ((nPosJump != (int)_this->m_nCurrentPattern) || (nBreakRow != (int)_this->m_nRow)))
1221
+ {
1222
+ if (nPosJump != (int)_this->m_nCurrentPattern)
1223
+ {
1224
+ for (UINT i=0; i<_this->m_nChannels; i++) _this->Chn[i].nPatternLoopCount = 0;
1225
+ }
1226
+ _this->m_nNextPattern = nPosJump;
1227
+ _this->m_nNextRow = (UINT)nBreakRow;
1228
+ }
1229
+ }
1230
+ }
1231
+ return TRUE;
1232
+ }
1233
+
1234
+
1235
+ ////////////////////////////////////////////////////////////
1236
+ // Channels effects
1237
+
1238
+ void CSoundFile_PortamentoUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1239
+ //---------------------------------------------------------
1240
+ {
1241
+ if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
1242
+ if ((_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
1243
+ {
1244
+ if (param & 0x0F)
1245
+ {
1246
+ if ((param & 0xF0) == 0xF0)
1247
+ {
1248
+ CSoundFile_FinePortamentoUp(_this, pChn, param & 0x0F);
1249
+ } else
1250
+ if ((param & 0xF0) == 0xE0)
1251
+ {
1252
+ CSoundFile_ExtraFinePortamentoUp(_this, pChn, param & 0x0F);
1253
+ }
1254
+ }
1255
+ return;
1256
+ }
1257
+ // Regular Slide
1258
+ if (!(_this->m_dwSongFlags & SONG_FIRSTTICK) || (_this->m_nMusicSpeed == 1)) //rewbs.PortaA01fix
1259
+ {
1260
+ CSoundFile_DoFreqSlide(_this, pChn, -(int)(param * 4));
1261
+ }
1262
+ }
1263
+
1264
+
1265
+ void CSoundFile_PortamentoDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1266
+ //-----------------------------------------------------------
1267
+ {
1268
+ if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
1269
+ if ((_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
1270
+ {
1271
+ if (param & 0x0F)
1272
+ {
1273
+ if ((param & 0xF0) == 0xF0)
1274
+ {
1275
+ CSoundFile_FinePortamentoDown(_this, pChn, param & 0x0F);
1276
+ } else
1277
+ if ((param & 0xF0) == 0xE0)
1278
+ {
1279
+ CSoundFile_ExtraFinePortamentoDown(_this, pChn, param & 0x0F);
1280
+ }
1281
+ }
1282
+ return;
1283
+ }
1284
+ if (!(_this->m_dwSongFlags & SONG_FIRSTTICK) || (_this->m_nMusicSpeed == 1)) { //rewbs.PortaA01fix
1285
+ CSoundFile_DoFreqSlide(_this, pChn, (int)(param << 2));
1286
+ }
1287
+ }
1288
+
1289
+
1290
+ void CSoundFile_FinePortamentoUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1291
+ //-------------------------------------------------------------
1292
+ {
1293
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1294
+ {
1295
+ if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
1296
+ }
1297
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1298
+ {
1299
+ if ((pChn->nPeriod) && (param))
1300
+ {
1301
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1302
+ {
1303
+ pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536);
1304
+ } else
1305
+ {
1306
+ pChn->nPeriod -= (int)(param * 4);
1307
+ }
1308
+ if (pChn->nPeriod < 1) pChn->nPeriod = 1;
1309
+ }
1310
+ }
1311
+ }
1312
+
1313
+
1314
+ void CSoundFile_FinePortamentoDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1315
+ //---------------------------------------------------------------
1316
+ {
1317
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1318
+ {
1319
+ if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
1320
+ }
1321
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1322
+ {
1323
+ if ((pChn->nPeriod) && (param))
1324
+ {
1325
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1326
+ {
1327
+ pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536);
1328
+ } else
1329
+ {
1330
+ pChn->nPeriod += (int)(param * 4);
1331
+ }
1332
+ if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF;
1333
+ }
1334
+ }
1335
+ }
1336
+
1337
+
1338
+ void CSoundFile_ExtraFinePortamentoUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1339
+ //------------------------------------------------------------------
1340
+ {
1341
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1342
+ {
1343
+ if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
1344
+ }
1345
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1346
+ {
1347
+ if ((pChn->nPeriod) && (param))
1348
+ {
1349
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1350
+ {
1351
+ pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536);
1352
+ } else
1353
+ {
1354
+ pChn->nPeriod -= (int)(param);
1355
+ }
1356
+ if (pChn->nPeriod < 1) pChn->nPeriod = 1;
1357
+ }
1358
+ }
1359
+ }
1360
+
1361
+
1362
+ void CSoundFile_ExtraFinePortamentoDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1363
+ //--------------------------------------------------------------------
1364
+ {
1365
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1366
+ {
1367
+ if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
1368
+ }
1369
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1370
+ {
1371
+ if ((pChn->nPeriod) && (param))
1372
+ {
1373
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1374
+ {
1375
+ pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536);
1376
+ } else
1377
+ {
1378
+ pChn->nPeriod += (int)(param);
1379
+ }
1380
+ if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF;
1381
+ }
1382
+ }
1383
+ }
1384
+
1385
+
1386
+ // Portamento Slide
1387
+ void CSoundFile_TonePortamento(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1388
+ //-----------------------------------------------------------
1389
+ {
1390
+ if (param) pChn->nPortamentoSlide = param * 4;
1391
+ pChn->dwFlags |= CHN_PORTAMENTO;
1392
+ if ((pChn->nPeriod) && (pChn->nPortamentoDest) && (!(_this->m_dwSongFlags & SONG_FIRSTTICK)))
1393
+ {
1394
+ if (pChn->nPeriod < pChn->nPortamentoDest)
1395
+ {
1396
+ LONG delta = (int)pChn->nPortamentoSlide;
1397
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1398
+ {
1399
+ UINT n = pChn->nPortamentoSlide >> 2;
1400
+ if (n > 255) n = 255;
1401
+ delta = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536) - pChn->nPeriod;
1402
+ if (delta < 1) delta = 1;
1403
+ }
1404
+ pChn->nPeriod += delta;
1405
+ if (pChn->nPeriod > pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest;
1406
+ } else
1407
+ if (pChn->nPeriod > pChn->nPortamentoDest)
1408
+ {
1409
+ LONG delta = - (int)pChn->nPortamentoSlide;
1410
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1411
+ {
1412
+ UINT n = pChn->nPortamentoSlide >> 2;
1413
+ if (n > 255) n = 255;
1414
+ delta = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536) - pChn->nPeriod;
1415
+ if (delta > -1) delta = -1;
1416
+ }
1417
+ pChn->nPeriod += delta;
1418
+ if (pChn->nPeriod < pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest;
1419
+ }
1420
+ }
1421
+ }
1422
+
1423
+
1424
+ void CSoundFile_Vibrato(CSoundFile *_this, MODCHANNEL *p, UINT param)
1425
+ //-------------------------------------------------
1426
+ {
1427
+ if (param & 0x0F) p->nVibratoDepth = (param & 0x0F) * 4;
1428
+ if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F;
1429
+ p->dwFlags |= CHN_VIBRATO;
1430
+ }
1431
+
1432
+
1433
+ void CSoundFile_FineVibrato(CSoundFile *_this, MODCHANNEL *p, UINT param)
1434
+ //-----------------------------------------------------
1435
+ {
1436
+ if (param & 0x0F) p->nVibratoDepth = param & 0x0F;
1437
+ if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F;
1438
+ p->dwFlags |= CHN_VIBRATO;
1439
+ }
1440
+
1441
+
1442
+ void CSoundFile_Panbrello(CSoundFile *_this, MODCHANNEL *p, UINT param)
1443
+ //---------------------------------------------------
1444
+ {
1445
+ if (param & 0x0F) p->nPanbrelloDepth = param & 0x0F;
1446
+ if (param & 0xF0) p->nPanbrelloSpeed = (param >> 4) & 0x0F;
1447
+ p->dwFlags |= CHN_PANBRELLO;
1448
+ }
1449
+
1450
+
1451
+ void CSoundFile_VolumeSlide(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1452
+ //--------------------------------------------------------
1453
+ {
1454
+ if (param) pChn->nOldVolumeSlide = param; else param = pChn->nOldVolumeSlide;
1455
+ LONG newvolume = pChn->nVolume;
1456
+ if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_AMF))
1457
+ {
1458
+ if ((param & 0x0F) == 0x0F)
1459
+ {
1460
+ if (param & 0xF0)
1461
+ {
1462
+ CSoundFile_FineVolumeUp(_this, pChn, (param >> 4));
1463
+ return;
1464
+ } else
1465
+ {
1466
+ if ((_this->m_dwSongFlags & SONG_FIRSTTICK) && (!(_this->m_dwSongFlags & SONG_FASTVOLSLIDES)))
1467
+ {
1468
+ newvolume -= 0x0F * 4;
1469
+ }
1470
+ }
1471
+ } else
1472
+ if ((param & 0xF0) == 0xF0)
1473
+ {
1474
+ if (param & 0x0F)
1475
+ {
1476
+ CSoundFile_FineVolumeDown(_this, pChn, (param & 0x0F));
1477
+ return;
1478
+ } else
1479
+ {
1480
+ if ((_this->m_dwSongFlags & SONG_FIRSTTICK) && (!(_this->m_dwSongFlags & SONG_FASTVOLSLIDES)))
1481
+ {
1482
+ newvolume += 0x0F * 4;
1483
+ }
1484
+ }
1485
+ }
1486
+ }
1487
+ if ((!(_this->m_dwSongFlags & SONG_FIRSTTICK)) || (_this->m_dwSongFlags & SONG_FASTVOLSLIDES))
1488
+ {
1489
+ if (param & 0x0F) newvolume -= (int)((param & 0x0F) * 4);
1490
+ else newvolume += (int)((param & 0xF0) >> 2);
1491
+ if (_this->m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
1492
+ }
1493
+ if (newvolume < 0) newvolume = 0;
1494
+ if (newvolume > 256) newvolume = 256;
1495
+ pChn->nVolume = newvolume;
1496
+ }
1497
+
1498
+
1499
+ void CSoundFile_PanningSlide(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1500
+ //---------------------------------------------------------
1501
+ {
1502
+ LONG nPanSlide = 0;
1503
+ if (param) pChn->nOldPanSlide = param; else param = pChn->nOldPanSlide;
1504
+ if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
1505
+ {
1506
+ if (((param & 0x0F) == 0x0F) && (param & 0xF0))
1507
+ {
1508
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1509
+ {
1510
+ param = (param & 0xF0) >> 2;
1511
+ nPanSlide = - (int)param;
1512
+ }
1513
+ } else
1514
+ if (((param & 0xF0) == 0xF0) && (param & 0x0F))
1515
+ {
1516
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1517
+ {
1518
+ nPanSlide = (param & 0x0F) << 2;
1519
+ }
1520
+ } else
1521
+ {
1522
+ if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
1523
+ {
1524
+ if (param & 0x0F) nPanSlide = (int)((param & 0x0F) << 2);
1525
+ else nPanSlide = -(int)((param & 0xF0) >> 2);
1526
+ }
1527
+ }
1528
+ } else
1529
+ {
1530
+ if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
1531
+ {
1532
+ if (param & 0x0F) nPanSlide = -(int)((param & 0x0F) << 2);
1533
+ else nPanSlide = (int)((param & 0xF0) >> 2);
1534
+ }
1535
+ }
1536
+ if (nPanSlide)
1537
+ {
1538
+ nPanSlide += pChn->nPan;
1539
+ if (nPanSlide < 0) nPanSlide = 0;
1540
+ if (nPanSlide > 256) nPanSlide = 256;
1541
+ pChn->nPan = nPanSlide;
1542
+ }
1543
+ }
1544
+
1545
+
1546
+ void CSoundFile_FineVolumeUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1547
+ //---------------------------------------------------------
1548
+ {
1549
+ if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown;
1550
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1551
+ {
1552
+ pChn->nVolume += param * 4;
1553
+ if (pChn->nVolume > 256) pChn->nVolume = 256;
1554
+ if (_this->m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
1555
+ }
1556
+ }
1557
+
1558
+
1559
+ void CSoundFile_FineVolumeDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1560
+ //-----------------------------------------------------------
1561
+ {
1562
+ if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown;
1563
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK)
1564
+ {
1565
+ pChn->nVolume -= param * 4;
1566
+ if (pChn->nVolume < 0) pChn->nVolume = 0;
1567
+ if (_this->m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
1568
+ }
1569
+ }
1570
+
1571
+
1572
+ void CSoundFile_Tremolo(CSoundFile *_this, MODCHANNEL *p, UINT param)
1573
+ //-------------------------------------------------
1574
+ {
1575
+ if (param & 0x0F) p->nTremoloDepth = (param & 0x0F) << 2;
1576
+ if (param & 0xF0) p->nTremoloSpeed = (param >> 4) & 0x0F;
1577
+ p->dwFlags |= CHN_TREMOLO;
1578
+ }
1579
+
1580
+
1581
+ void CSoundFile_ChannelVolSlide(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1582
+ //------------------------------------------------------------
1583
+ {
1584
+ LONG nChnSlide = 0;
1585
+ if (param) pChn->nOldChnVolSlide = param; else param = pChn->nOldChnVolSlide;
1586
+ if (((param & 0x0F) == 0x0F) && (param & 0xF0))
1587
+ {
1588
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = param >> 4;
1589
+ } else
1590
+ if (((param & 0xF0) == 0xF0) && (param & 0x0F))
1591
+ {
1592
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = - (int)(param & 0x0F);
1593
+ } else
1594
+ {
1595
+ if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
1596
+ {
1597
+ if (param & 0x0F) nChnSlide = -(int)(param & 0x0F);
1598
+ else nChnSlide = (int)((param & 0xF0) >> 4);
1599
+ }
1600
+ }
1601
+ if (nChnSlide)
1602
+ {
1603
+ nChnSlide += pChn->nGlobalVol;
1604
+ if (nChnSlide < 0) nChnSlide = 0;
1605
+ if (nChnSlide > 64) nChnSlide = 64;
1606
+ pChn->nGlobalVol = nChnSlide;
1607
+ }
1608
+ }
1609
+
1610
+
1611
+ void CSoundFile_ExtendedMODCommands(CSoundFile *_this, UINT nChn, UINT param)
1612
+ //---------------------------------------------------------
1613
+ {
1614
+ MODCHANNEL *pChn = &_this->Chn[nChn];
1615
+ UINT command = param & 0xF0;
1616
+ param &= 0x0F;
1617
+ switch(command)
1618
+ {
1619
+ // E0x: Set Filter
1620
+ // E1x: Fine Portamento Up
1621
+ case 0x10: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FinePortamentoUp(_this, pChn, param); break;
1622
+ // E2x: Fine Portamento Down
1623
+ case 0x20: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FinePortamentoDown(_this, pChn, param); break;
1624
+ // E3x: Set Glissando Control
1625
+ case 0x30: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
1626
+ // E4x: Set Vibrato WaveForm
1627
+ case 0x40: pChn->nVibratoType = param & 0x07; break;
1628
+ // E5x: Set FineTune
1629
+ case 0x50: if (_this->m_nTickCount) break;
1630
+ pChn->nC4Speed = S3MFineTuneTable[param];
1631
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1632
+ pChn->nFineTune = param*2;
1633
+ else
1634
+ pChn->nFineTune = MOD2XMFineTune(param);
1635
+ if (pChn->nPeriod) pChn->nPeriod = CSoundFile_GetPeriodFromNote(_this, pChn->nNote, pChn->nFineTune, pChn->nC4Speed);
1636
+ break;
1637
+ // E6x: Pattern Loop
1638
+ // E7x: Set Tremolo WaveForm
1639
+ case 0x70: pChn->nTremoloType = param & 0x07; break;
1640
+ // E8x: Set 4-bit Panning
1641
+ case 0x80: if (!_this->m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
1642
+ // E9x: Retrig
1643
+ case 0x90: CSoundFile_RetrigNote(_this, nChn, param); break;
1644
+ // EAx: Fine Volume Up
1645
+ case 0xA0: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FineVolumeUp(_this, pChn, param); break;
1646
+ // EBx: Fine Volume Down
1647
+ case 0xB0: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FineVolumeDown(_this, pChn, param); break;
1648
+ // ECx: Note Cut
1649
+ case 0xC0: CSoundFile_NoteCut(_this, nChn, param); break;
1650
+ // EDx: Note Delay
1651
+ // EEx: Pattern Delay
1652
+ // EFx: MOD: Invert Loop, XM: Set Active Midi Macro
1653
+ case 0xF0: pChn->nActiveMacro = param; break;
1654
+ }
1655
+ }
1656
+
1657
+
1658
+ void CSoundFile_ExtendedS3MCommands(CSoundFile *_this, UINT nChn, UINT param)
1659
+ //---------------------------------------------------------
1660
+ {
1661
+ MODCHANNEL *pChn = &_this->Chn[nChn];
1662
+ UINT command = param & 0xF0;
1663
+ param &= 0x0F;
1664
+ switch(command)
1665
+ {
1666
+ // S0x: Set Filter
1667
+ // S1x: Set Glissando Control
1668
+ case 0x10: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
1669
+ // S2x: Set FineTune
1670
+ case 0x20: if (_this->m_nTickCount) break;
1671
+ pChn->nC4Speed = S3MFineTuneTable[param & 0x0F];
1672
+ pChn->nFineTune = MOD2XMFineTune(param);
1673
+ if (pChn->nPeriod) pChn->nPeriod = CSoundFile_GetPeriodFromNote(_this, pChn->nNote, pChn->nFineTune, pChn->nC4Speed);
1674
+ break;
1675
+ // S3x: Set Vibrato WaveForm
1676
+ case 0x30: pChn->nVibratoType = param & 0x07; break;
1677
+ // S4x: Set Tremolo WaveForm
1678
+ case 0x40: pChn->nTremoloType = param & 0x07; break;
1679
+ // S5x: Set Panbrello WaveForm
1680
+ case 0x50: pChn->nPanbrelloType = param & 0x07; break;
1681
+ // S6x: Pattern Delay for x frames
1682
+ case 0x60: _this->m_nFrameDelay = param; break;
1683
+ // S7x: Envelope Control
1684
+ case 0x70: if (_this->m_nTickCount) break;
1685
+ switch(param)
1686
+ {
1687
+ case 0:
1688
+ case 1:
1689
+ case 2:
1690
+ {
1691
+ MODCHANNEL *bkp = &_this->Chn[_this->m_nChannels];
1692
+ for (UINT i=_this->m_nChannels; i<MAX_CHANNELS; i++, bkp++)
1693
+ {
1694
+ if (bkp->nMasterChn == nChn+1)
1695
+ {
1696
+ if (param == 1) CSoundFile_KeyOff(_this, i); else
1697
+ if (param == 2) bkp->dwFlags |= CHN_NOTEFADE; else
1698
+ { bkp->dwFlags |= CHN_NOTEFADE; bkp->nFadeOutVol = 0; }
1699
+ }
1700
+ }
1701
+ }
1702
+ break;
1703
+ case 3: pChn->nNNA = NNA_NOTECUT; break;
1704
+ case 4: pChn->nNNA = NNA_CONTINUE; break;
1705
+ case 5: pChn->nNNA = NNA_NOTEOFF; break;
1706
+ case 6: pChn->nNNA = NNA_NOTEFADE; break;
1707
+ case 7: pChn->dwFlags &= ~CHN_VOLENV; break;
1708
+ case 8: pChn->dwFlags |= CHN_VOLENV; break;
1709
+ case 9: pChn->dwFlags &= ~CHN_PANENV; break;
1710
+ case 10: pChn->dwFlags |= CHN_PANENV; break;
1711
+ case 11: pChn->dwFlags &= ~CHN_PITCHENV; break;
1712
+ case 12: pChn->dwFlags |= CHN_PITCHENV; break;
1713
+ }
1714
+ break;
1715
+ // S8x: Set 4-bit Panning
1716
+ case 0x80: if (!_this->m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
1717
+ // S9x: Set Surround
1718
+ case 0x90: CSoundFile_ExtendedChannelEffect(_this, pChn, param & 0x0F); break;
1719
+ // SAx: Set 64k Offset
1720
+ case 0xA0: if (!_this->m_nTickCount)
1721
+ {
1722
+ pChn->nOldHiOffset = param;
1723
+ if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
1724
+ {
1725
+ DWORD pos = param << 16;
1726
+ if (pos < pChn->nLength) pChn->nPos = pos;
1727
+ }
1728
+ }
1729
+ break;
1730
+ // SBx: Pattern Loop
1731
+ // SCx: Note Cut
1732
+ case 0xC0: CSoundFile_NoteCut(_this, nChn, param); break;
1733
+ // SDx: Note Delay
1734
+ // case 0xD0: break;
1735
+ // SEx: Pattern Delay for x rows
1736
+ // SFx: S3M: Funk Repeat, IT: Set Active Midi Macro
1737
+ case 0xF0: pChn->nActiveMacro = param; break;
1738
+ }
1739
+ }
1740
+
1741
+
1742
+ void CSoundFile_ExtendedChannelEffect(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
1743
+ //------------------------------------------------------------------
1744
+ {
1745
+ // S9x and X9x commands (S3M/XM/IT only)
1746
+ if (_this->m_nTickCount) return;
1747
+ switch(param & 0x0F)
1748
+ {
1749
+ // S90: Surround Off
1750
+ case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break;
1751
+ // S91: Surround On
1752
+ case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break;
1753
+ ////////////////////////////////////////////////////////////
1754
+ // Modplug Extensions
1755
+ // S98: Reverb Off
1756
+ case 0x08:
1757
+ pChn->dwFlags &= ~CHN_REVERB;
1758
+ pChn->dwFlags |= CHN_NOREVERB;
1759
+ break;
1760
+ // S99: Reverb On
1761
+ case 0x09:
1762
+ pChn->dwFlags &= ~CHN_NOREVERB;
1763
+ pChn->dwFlags |= CHN_REVERB;
1764
+ break;
1765
+ // S9A: 2-Channels surround mode
1766
+ case 0x0A:
1767
+ _this->m_dwSongFlags &= ~SONG_SURROUNDPAN;
1768
+ break;
1769
+ // S9B: 4-Channels surround mode
1770
+ case 0x0B:
1771
+ _this->m_dwSongFlags |= SONG_SURROUNDPAN;
1772
+ break;
1773
+ // S9C: IT Filter Mode
1774
+ case 0x0C:
1775
+ _this->m_dwSongFlags &= ~SONG_MPTFILTERMODE;
1776
+ break;
1777
+ // S9D: MPT Filter Mode
1778
+ case 0x0D:
1779
+ _this->m_dwSongFlags |= SONG_MPTFILTERMODE;
1780
+ break;
1781
+ // S9E: Go forward
1782
+ case 0x0E:
1783
+ pChn->dwFlags &= ~(CHN_PINGPONGFLAG);
1784
+ break;
1785
+ // S9F: Go backward (set position at the end for non-looping samples)
1786
+ case 0x0F:
1787
+ if ((!(pChn->dwFlags & CHN_LOOP)) && (!pChn->nPos) && (pChn->nLength))
1788
+ {
1789
+ pChn->nPos = pChn->nLength - 1;
1790
+ pChn->nPosLo = 0xFFFF;
1791
+ }
1792
+ pChn->dwFlags |= CHN_PINGPONGFLAG;
1793
+ break;
1794
+ }
1795
+ }
1796
+
1797
+
1798
+ void CSoundFile_ProcessMidiMacro(CSoundFile *_this, UINT nChn, LPCSTR pszMidiMacro, UINT param)
1799
+ //---------------------------------------------------------------------------
1800
+ {
1801
+ MODCHANNEL *pChn = &_this->Chn[nChn];
1802
+ DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F;
1803
+ // Not Internal Device ?
1804
+ if (dwMacro != 0x30463046 && dwMacro != 0x31463046)
1805
+ {
1806
+ UINT pos = 0, nNib = 0, nBytes = 0;
1807
+ DWORD dwMidiCode = 0, dwByteCode = 0;
1808
+ while (pos+6 <= 32)
1809
+ {
1810
+ CHAR cData = pszMidiMacro[pos++];
1811
+ if (!cData) break;
1812
+ if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else
1813
+ if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else
1814
+ if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else
1815
+ if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else
1816
+ if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else
1817
+ if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else
1818
+ if (nNib >= 2)
1819
+ {
1820
+ nNib = 0;
1821
+ dwMidiCode |= dwByteCode << (nBytes*8);
1822
+ dwByteCode = 0;
1823
+ nBytes++;
1824
+ if (nBytes >= 3)
1825
+ {
1826
+ nBytes = 0;
1827
+ dwMidiCode = 0;
1828
+ }
1829
+ }
1830
+
1831
+ }
1832
+ return;
1833
+ }
1834
+ // Internal device
1835
+ pszMidiMacro += 4;
1836
+ // Filter ?
1837
+ if (pszMidiMacro[0] == '0')
1838
+ {
1839
+ CHAR cData1 = pszMidiMacro[2];
1840
+ DWORD dwParam = 0;
1841
+ if ((cData1 == 'z') || (cData1 == 'Z'))
1842
+ {
1843
+ dwParam = param;
1844
+ } else
1845
+ {
1846
+ CHAR cData2 = pszMidiMacro[3];
1847
+ if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else
1848
+ if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4;
1849
+ if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else
1850
+ if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A);
1851
+ }
1852
+ switch(pszMidiMacro[1])
1853
+ {
1854
+ // F0.F0.00.xx: Set CutOff
1855
+ case '0':
1856
+ {
1857
+ int oldcutoff = pChn->nCutOff;
1858
+ if (dwParam < 0x80) pChn->nCutOff = (BYTE)dwParam;
1859
+ #ifndef NO_FILTER
1860
+ oldcutoff -= pChn->nCutOff;
1861
+
1862
+ if (oldcutoff < 0) oldcutoff = -oldcutoff;
1863
+ if ((pChn->nVolume > 0) || (oldcutoff < 0x10)
1864
+ || (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol)))
1865
+ CSoundFile_SetupChannelFilter(_this, pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, 256);
1866
+ #endif // NO_FILTER
1867
+ }
1868
+ break;
1869
+
1870
+ // F0.F0.01.xx: Set Resonance
1871
+ case '1':
1872
+ if (dwParam < 0x80) pChn->nResonance = (BYTE)dwParam;
1873
+ #ifndef NO_FILTER
1874
+ CSoundFile_SetupChannelFilter(_this, pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, 256);
1875
+ #endif // NO_FILTER
1876
+
1877
+ break;
1878
+ }
1879
+
1880
+ }
1881
+ }
1882
+
1883
+
1884
+ void CSoundFile_RetrigNote(CSoundFile *_this, UINT nChn, UINT param)
1885
+ //------------------------------------------------
1886
+ {
1887
+ // Retrig: bit 8 is set if it's the new XM retrig
1888
+ MODCHANNEL *pChn = &_this->Chn[nChn];
1889
+ UINT nRetrigSpeed = param & 0x0F;
1890
+ UINT nRetrigCount = pChn->nRetrigCount;
1891
+ BOOL bDoRetrig = FALSE;
1892
+
1893
+ if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
1894
+ {
1895
+ if (!nRetrigSpeed) nRetrigSpeed = 1;
1896
+ if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE;
1897
+ nRetrigCount++;
1898
+ } else
1899
+ {
1900
+ UINT realspeed = nRetrigSpeed;
1901
+ if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++;
1902
+ if ((_this->m_nTickCount) || (param & 0x100))
1903
+ {
1904
+ if (!realspeed) realspeed = 1;
1905
+ if ((!(param & 0x100)) && (_this->m_nMusicSpeed) && (!(_this->m_nTickCount % realspeed))) bDoRetrig = TRUE;
1906
+ nRetrigCount++;
1907
+ } else if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) nRetrigCount = 0;
1908
+ if (nRetrigCount >= realspeed)
1909
+ {
1910
+ if ((_this->m_nTickCount) || ((param & 0x100) && (!pChn->nRowNote))) bDoRetrig = TRUE;
1911
+ }
1912
+ }
1913
+ if (bDoRetrig)
1914
+ {
1915
+ UINT dv = (param >> 4) & 0x0F;
1916
+ if (dv)
1917
+ {
1918
+ int vol = pChn->nVolume;
1919
+ if (retrigTable1[dv])
1920
+ vol = (vol * retrigTable1[dv]) >> 4;
1921
+ else
1922
+ vol += ((int)retrigTable2[dv]) << 2;
1923
+ if (vol < 0) vol = 0;
1924
+ if (vol > 256) vol = 256;
1925
+ pChn->nVolume = vol;
1926
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
1927
+ }
1928
+ UINT nNote = pChn->nNewNote;
1929
+ LONG nOldPeriod = pChn->nPeriod;
1930
+ if ((nNote) && (nNote <= NOTE_MAX) && (pChn->nLength)) CSoundFile_CheckNNA(_this, nChn, 0, nNote, TRUE);
1931
+ BOOL bResetEnv = FALSE;
1932
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
1933
+ {
1934
+ if ((pChn->nRowInstr) && (param < 0x100)) { CSoundFile_InstrumentChange(_this, pChn, pChn->nRowInstr, FALSE, FALSE, TRUE); bResetEnv = TRUE; }
1935
+ if (param < 0x100) bResetEnv = TRUE;
1936
+ }
1937
+ CSoundFile_NoteChange(_this, nChn, nNote, FALSE, bResetEnv);
1938
+ if ((_this->m_nType & MOD_TYPE_IT) && (!pChn->nRowNote) && (nOldPeriod)) pChn->nPeriod = nOldPeriod;
1939
+ if (!(_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) nRetrigCount = 0;
1940
+ }
1941
+ pChn->nRetrigCount = (BYTE)nRetrigCount;
1942
+ }
1943
+
1944
+
1945
+ void CSoundFile_DoFreqSlide(CSoundFile *_this, MODCHANNEL *pChn, LONG nFreqSlide)
1946
+ //-------------------------------------------------------------
1947
+ {
1948
+ // IT Linear slides
1949
+ if (!pChn->nPeriod) return;
1950
+ if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
1951
+ {
1952
+ if (nFreqSlide < 0)
1953
+ {
1954
+ UINT n = (- nFreqSlide) >> 2;
1955
+ if (n > 255) n = 255;
1956
+ pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536);
1957
+ } else
1958
+ {
1959
+ UINT n = (nFreqSlide) >> 2;
1960
+
1961
+ if (n > 255) n = 255;
1962
+ pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536);
1963
+ }
1964
+ } else
1965
+ {
1966
+ pChn->nPeriod += nFreqSlide;
1967
+ }
1968
+ if (pChn->nPeriod < 1)
1969
+ {
1970
+ pChn->nPeriod = 1;
1971
+ if (_this->m_nType & MOD_TYPE_IT)
1972
+ {
1973
+ pChn->dwFlags |= CHN_NOTEFADE;
1974
+ pChn->nFadeOutVol = 0;
1975
+ }
1976
+ }
1977
+ }
1978
+
1979
+
1980
+ void CSoundFile_NoteCut(CSoundFile *_this, UINT nChn, UINT nTick)
1981
+ //---------------------------------------------
1982
+ {
1983
+ if (_this->m_nTickCount == nTick)
1984
+ {
1985
+ MODCHANNEL *pChn = &_this->Chn[nChn];
1986
+ // if (_this->m_nInstruments) CSoundFile_KeyOff(_this, pChn); ?
1987
+ pChn->nVolume = 0;
1988
+ pChn->dwFlags |= CHN_FASTVOLRAMP;
1989
+ }
1990
+ }
1991
+
1992
+
1993
+ void CSoundFile_KeyOff(CSoundFile *_this, UINT nChn)
1994
+ //--------------------------------
1995
+ {
1996
+ MODCHANNEL *pChn = &_this->Chn[nChn];
1997
+ BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE;
1998
+ pChn->dwFlags |= CHN_KEYOFF;
1999
+ //if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV)))
2000
+ if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV)))
2001
+ {
2002
+ pChn->dwFlags |= CHN_NOTEFADE;
2003
+ }
2004
+ if (!pChn->nLength) return;
2005
+ if ((pChn->dwFlags & CHN_SUSTAINLOOP) && (pChn->pInstrument) && (bKeyOn))
2006
+ {
2007
+ MODINSTRUMENT *psmp = pChn->pInstrument;
2008
+ if (psmp->uFlags & CHN_LOOP)
2009
+ {
2010
+ if (psmp->uFlags & CHN_PINGPONGLOOP)
2011
+ pChn->dwFlags |= CHN_PINGPONGLOOP;
2012
+ else
2013
+ pChn->dwFlags &= ~(CHN_PINGPONGLOOP|CHN_PINGPONGFLAG);
2014
+ pChn->dwFlags |= CHN_LOOP;
2015
+ pChn->nLength = psmp->nLength;
2016
+ pChn->nLoopStart = psmp->nLoopStart;
2017
+ pChn->nLoopEnd = psmp->nLoopEnd;
2018
+ if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
2019
+ } else
2020
+ {
2021
+ pChn->dwFlags &= ~(CHN_LOOP|CHN_PINGPONGLOOP|CHN_PINGPONGFLAG);
2022
+ pChn->nLength = psmp->nLength;
2023
+ }
2024
+ }
2025
+ if (pChn->pHeader)
2026
+ {
2027
+ INSTRUMENTHEADER *penv = pChn->pHeader;
2028
+ if (((penv->dwFlags & ENV_VOLLOOP) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut))
2029
+ pChn->dwFlags |= CHN_NOTEFADE;
2030
+ }
2031
+ }
2032
+
2033
+
2034
+ //////////////////////////////////////////////////////////
2035
+ // CSoundFile: Global Effects
2036
+
2037
+
2038
+ void CSoundFile_SetSpeed(CSoundFile *_this, UINT param)
2039
+ //-----------------------------------
2040
+ {
2041
+ UINT max = (_this->m_nType == MOD_TYPE_IT) ? 256 : 128;
2042
+ // Modplug Tracker and Mod-Plugin don't do this check
2043
+ #ifndef MODPLUG_TRACKER
2044
+ // Big Hack!!!
2045
+ if ((!param) || (param >= 0x80) || ((_this->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E)))
2046
+ {
2047
+ if (CSoundFile_IsSongFinished(_this, _this->m_nCurrentPattern, _this->m_nRow+1))
2048
+ {
2049
+ CSoundFile_GlobalFadeSong(_this, 1000);
2050
+ }
2051
+ }
2052
+ #endif // MODPLUG_TRACKER
2053
+ if ((_this->m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80;
2054
+ if ((param) && (param <= max)) _this->m_nMusicSpeed = param;
2055
+ }
2056
+
2057
+
2058
+ void CSoundFile_SetTempo(CSoundFile *_this, UINT param)
2059
+ //-----------------------------------
2060
+ {
2061
+ if (param < 0x20)
2062
+ {
2063
+ // Tempo Slide
2064
+ if ((param & 0xF0) == 0x10)
2065
+ {
2066
+ _this->m_nMusicTempo += (param & 0x0F) * 2;
2067
+ if (_this->m_nMusicTempo > 255) _this->m_nMusicTempo = 255;
2068
+ } else
2069
+ {
2070
+ _this->m_nMusicTempo -= (param & 0x0F) * 2;
2071
+ if ((LONG)_this->m_nMusicTempo < 32) _this->m_nMusicTempo = 32;
2072
+ }
2073
+ } else
2074
+ {
2075
+ _this->m_nMusicTempo = param;
2076
+ }
2077
+ }
2078
+
2079
+
2080
+ int CSoundFile_PatternLoop(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
2081
+ //-------------------------------------------------------
2082
+ {
2083
+ if (param)
2084
+ {
2085
+ if (pChn->nPatternLoopCount)
2086
+ {
2087
+ pChn->nPatternLoopCount--;
2088
+ if (!pChn->nPatternLoopCount) return -1;
2089
+ } else
2090
+ {
2091
+ MODCHANNEL *p = _this->Chn;
2092
+ for (UINT i=0; i<_this->m_nChannels; i++, p++) if (p != pChn)
2093
+ {
2094
+ // Loop already done
2095
+ if (p->nPatternLoopCount) return -1;
2096
+ }
2097
+ pChn->nPatternLoopCount = param;
2098
+ }
2099
+ return pChn->nPatternLoop;
2100
+ } else
2101
+ {
2102
+ pChn->nPatternLoop = _this->m_nRow;
2103
+ }
2104
+ return -1;
2105
+ }
2106
+
2107
+
2108
+ void CSoundFile_GlobalVolSlide(CSoundFile *_this, UINT param)
2109
+ //-----------------------------------------
2110
+ {
2111
+ LONG nGlbSlide = 0;
2112
+ if (param) _this->m_nOldGlbVolSlide = param; else param = _this->m_nOldGlbVolSlide;
2113
+ if (((param & 0x0F) == 0x0F) && (param & 0xF0))
2114
+ {
2115
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = (param >> 4) * 2;
2116
+ } else
2117
+ if (((param & 0xF0) == 0xF0) && (param & 0x0F))
2118
+ {
2119
+ if (_this->m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = - (int)((param & 0x0F) * 2);
2120
+ } else
2121
+ {
2122
+ if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
2123
+ {
2124
+ if (param & 0xF0) nGlbSlide = (int)((param & 0xF0) >> 4) * 2;
2125
+ else nGlbSlide = -(int)((param & 0x0F) * 2);
2126
+ }
2127
+ }
2128
+ if (nGlbSlide)
2129
+ {
2130
+ if (_this->m_nType != MOD_TYPE_IT) nGlbSlide *= 2;
2131
+ nGlbSlide += _this->m_nGlobalVolume;
2132
+ if (nGlbSlide < 0) nGlbSlide = 0;
2133
+ if (nGlbSlide > 256) nGlbSlide = 256;
2134
+ _this->m_nGlobalVolume = nGlbSlide;
2135
+ }
2136
+ }
2137
+
2138
+
2139
+ DWORD CSoundFile_IsSongFinished(CSoundFile *_this, UINT nStartOrder, UINT nStartRow)
2140
+ //----------------------------------------------------------------------
2141
+ {
2142
+ UINT nOrd;
2143
+
2144
+ for (nOrd=nStartOrder; nOrd<MAX_ORDERS; nOrd++)
2145
+ {
2146
+ UINT nPat = _this->Order[nOrd];
2147
+ if (nPat != 0xFE)
2148
+ {
2149
+ MODCOMMAND *p;
2150
+
2151
+ if (nPat >= MAX_PATTERNS) break;
2152
+ p = _this->Patterns[nPat];
2153
+ if (p)
2154
+ {
2155
+ UINT len = _this->PatternSize[nPat] * _this->m_nChannels;
2156
+ UINT pos = (nOrd == nStartOrder) ? nStartRow : 0;
2157
+ pos *= _this->m_nChannels;
2158
+ while (pos < len)
2159
+ {
2160
+ UINT cmd;
2161
+ if ((p[pos].note) || (p[pos].volcmd)) return 0;
2162
+ cmd = p[pos].command;
2163
+ if (cmd == CMD_MODCMDEX)
2164
+ {
2165
+ UINT cmdex = p[pos].param & 0xF0;
2166
+ if ((!cmdex) || (cmdex == 0x60) || (cmdex == 0xE0) || (cmdex == 0xF0)) cmd = 0;
2167
+ }
2168
+ if ((cmd) && (cmd != CMD_SPEED) && (cmd != CMD_TEMPO)) return 0;
2169
+ pos++;
2170
+ }
2171
+ }
2172
+ }
2173
+ }
2174
+ return (nOrd < MAX_ORDERS) ? nOrd : MAX_ORDERS-1;
2175
+ }
2176
+
2177
+
2178
+ BOOL CSoundFile_IsValidBackwardJump(CSoundFile *_this, UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow)
2179
+ //----------------------------------------------------------------------------------------------------------
2180
+ {
2181
+ while ((nJumpOrder < MAX_PATTERNS) && (_this->Order[nJumpOrder] == 0xFE)) nJumpOrder++;
2182
+ if ((nStartOrder >= MAX_PATTERNS) || (nJumpOrder >= MAX_PATTERNS)) return FALSE;
2183
+ // Treat only case with jumps in the same pattern
2184
+ if (nJumpOrder > nStartOrder) return TRUE;
2185
+ if ((nJumpOrder < nStartOrder) || (nJumpRow >= _this->PatternSize[nStartOrder])
2186
+ || (!_this->Patterns[nStartOrder]) || (nStartRow >= 256) || (nJumpRow >= 256)) return FALSE;
2187
+ // See if the pattern is being played backward
2188
+ BYTE row_hist[256];
2189
+ SDL_memset(row_hist, 0, sizeof(row_hist));
2190
+ UINT nRows = _this->PatternSize[nStartOrder], row = nJumpRow;
2191
+ if (nRows > 256) nRows = 256;
2192
+ row_hist[nStartRow] = TRUE;
2193
+ while ((row < 256) && (!row_hist[row]))
2194
+ {
2195
+ if (row >= nRows) return TRUE;
2196
+ row_hist[row] = TRUE;
2197
+ MODCOMMAND *p = _this->Patterns[nStartOrder] + row * _this->m_nChannels;
2198
+ row++;
2199
+ int breakrow = -1, posjump = 0;
2200
+ for (UINT i=0; i<_this->m_nChannels; i++, p++)
2201
+ {
2202
+ if (p->command == CMD_POSITIONJUMP)
2203
+ {
2204
+ if (p->param < nStartOrder) return FALSE;
2205
+ if (p->param > nStartOrder) return TRUE;
2206
+ posjump = TRUE;
2207
+ } else
2208
+ if (p->command == CMD_PATTERNBREAK)
2209
+ {
2210
+ breakrow = p->param;
2211
+ }
2212
+ }
2213
+ if (breakrow >= 0)
2214
+ {
2215
+ if (!posjump) return TRUE;
2216
+ row = breakrow;
2217
+ }
2218
+ if (row >= nRows) return TRUE;
2219
+ }
2220
+ return FALSE;
2221
+ }
2222
+
2223
+
2224
+ //////////////////////////////////////////////////////
2225
+ // Note/Period/Frequency functions
2226
+
2227
+ UINT CSoundFile_GetNoteFromPeriod(CSoundFile *_this, UINT period)
2228
+ //---------------------------------------------------
2229
+ {
2230
+ if (!period) return 0;
2231
+ if (_this->m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
2232
+ {
2233
+ period >>= 2;
2234
+ for (UINT i=0; i<6*12; i++)
2235
+ {
2236
+ if (period >= ProTrackerPeriodTable[i])
2237
+ {
2238
+ if ((period != ProTrackerPeriodTable[i]) && (i))
2239
+ {
2240
+ UINT p1 = ProTrackerPeriodTable[i-1];
2241
+ UINT p2 = ProTrackerPeriodTable[i];
2242
+ if (p1 - period < (period - p2)) return i+36;
2243
+ }
2244
+ return i+1+36;
2245
+ }
2246
+ }
2247
+ return 6*12+36;
2248
+ } else
2249
+ {
2250
+ for (UINT i=1; i<NOTE_MAX; i++)
2251
+ {
2252
+ LONG n = CSoundFile_GetPeriodFromNote(_this, i, 0, 0);
2253
+ if ((n > 0) && (n <= (LONG)period)) return i;
2254
+ }
2255
+ return NOTE_MAX;
2256
+ }
2257
+ }
2258
+
2259
+
2260
+
2261
+ UINT CSoundFile_GetPeriodFromNote(CSoundFile *_this, UINT note, int nFineTune, UINT nC4Speed)
2262
+ //-------------------------------------------------------------------------------
2263
+ {
2264
+ if ((!note) || (note > 0xF0)) return 0;
2265
+ if (_this->m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV
2266
+ |MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM))
2267
+ {
2268
+ note--;
2269
+ if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
2270
+ {
2271
+ return (FreqS3MTable[note % 12] << 5) >> (note / 12);
2272
+ } else
2273
+ {
2274
+ if (!nC4Speed) nC4Speed = 8363;
2275
+ return _muldiv(8363, (FreqS3MTable[note % 12] << 5), nC4Speed << (note / 12));
2276
+ }
2277
+ } else
2278
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
2279
+ {
2280
+ if (note < 13) note = 13;
2281
+ note -= 13;
2282
+ if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
2283
+ {
2284
+ LONG l = ((NOTE_MAX - note) << 6) - (nFineTune / 2);
2285
+ if (l < 1) l = 1;
2286
+ return (UINT)l;
2287
+ } else
2288
+ {
2289
+ int finetune = nFineTune;
2290
+ UINT rnote = (note % 12) << 3;
2291
+ UINT roct = note / 12;
2292
+ int rfine = finetune / 16;
2293
+ int i = rnote + rfine + 8;
2294
+ if (i < 0) i = 0;
2295
+ if (i >= 104) i = 103;
2296
+ UINT per1 = XMPeriodTable[i];
2297
+ if ( finetune < 0 )
2298
+ {
2299
+ rfine--;
2300
+ finetune = -finetune;
2301
+ } else rfine++;
2302
+ i = rnote+rfine+8;
2303
+ if (i < 0) i = 0;
2304
+ if (i >= 104) i = 103;
2305
+ UINT per2 = XMPeriodTable[i];
2306
+ rfine = finetune & 0x0F;
2307
+ per1 *= 16-rfine;
2308
+ per2 *= rfine;
2309
+ return ((per1 + per2) << 1) >> roct;
2310
+ }
2311
+ } else
2312
+ {
2313
+ note--;
2314
+ nFineTune = XM2MODFineTune(nFineTune);
2315
+ if ((nFineTune) || (note < 36) || (note >= 36+6*12))
2316
+ return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12);
2317
+ else
2318
+ return (ProTrackerPeriodTable[note-36] << 2);
2319
+ }
2320
+ }
2321
+
2322
+
2323
+ UINT CSoundFile_GetFreqFromPeriod(CSoundFile *_this, UINT period, UINT nC4Speed, int nPeriodFrac)
2324
+ //-----------------------------------------------------------------------------------
2325
+ {
2326
+ if (!period) return 0;
2327
+ if (_this->m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
2328
+ {
2329
+ return (3546895L*4) / period;
2330
+ } else
2331
+ if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
2332
+ {
2333
+ if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
2334
+ return XMLinearTable[period % 768] >> (period / 768);
2335
+ else
2336
+ return 8363 * 1712L / period;
2337
+ } else
2338
+ {
2339
+ if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
2340
+ {
2341
+ if (!nC4Speed) nC4Speed = 8363;
2342
+ return _muldiv(nC4Speed, 1712L << 8, (period << 8)+nPeriodFrac);
2343
+ } else
2344
+ {
2345
+ return _muldiv(8363, 1712L << 8, (period << 8)+nPeriodFrac);
2346
+ }
2347
+ }
2348
+ }
2349
+
2350
+