gosu 0.15.1 → 1.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/COPYING +1 -1
  4. data/dependencies/SDL/include/SDL.h +138 -0
  5. data/dependencies/SDL/include/SDL_assert.h +293 -0
  6. data/dependencies/SDL/include/SDL_atomic.h +295 -0
  7. data/dependencies/SDL/include/SDL_audio.h +859 -0
  8. data/dependencies/SDL/include/SDL_bits.h +121 -0
  9. data/dependencies/SDL/include/SDL_blendmode.h +123 -0
  10. data/dependencies/SDL/include/SDL_clipboard.h +71 -0
  11. data/dependencies/SDL/include/SDL_config.h +55 -0
  12. data/dependencies/SDL/include/SDL_config_android.h +182 -0
  13. data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
  14. data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
  15. data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
  16. data/dependencies/SDL/include/SDL_config_os2.h +188 -0
  17. data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
  18. data/dependencies/SDL/include/SDL_config_psp.h +165 -0
  19. data/dependencies/SDL/include/SDL_config_windows.h +288 -0
  20. data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
  21. data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
  22. data/dependencies/SDL/include/SDL_copying.h +20 -0
  23. data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
  24. data/dependencies/SDL/include/SDL_egl.h +1676 -0
  25. data/dependencies/SDL/include/SDL_endian.h +263 -0
  26. data/dependencies/SDL/include/SDL_error.h +112 -0
  27. data/dependencies/SDL/include/SDL_events.h +827 -0
  28. data/dependencies/SDL/include/SDL_filesystem.h +136 -0
  29. data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
  30. data/dependencies/SDL/include/SDL_gesture.h +87 -0
  31. data/dependencies/SDL/include/SDL_haptic.h +1247 -0
  32. data/dependencies/SDL/include/SDL_hints.h +1578 -0
  33. data/dependencies/SDL/include/SDL_joystick.h +499 -0
  34. data/dependencies/SDL/include/SDL_keyboard.h +217 -0
  35. data/dependencies/SDL/include/SDL_keycode.h +351 -0
  36. data/dependencies/SDL/include/SDL_loadso.h +81 -0
  37. data/dependencies/SDL/include/SDL_locale.h +101 -0
  38. data/dependencies/SDL/include/SDL_log.h +211 -0
  39. data/dependencies/SDL/include/SDL_main.h +180 -0
  40. data/dependencies/SDL/include/SDL_messagebox.h +146 -0
  41. data/dependencies/SDL/include/SDL_metal.h +117 -0
  42. data/dependencies/SDL/include/SDL_misc.h +75 -0
  43. data/dependencies/SDL/include/SDL_mouse.h +302 -0
  44. data/dependencies/SDL/include/SDL_mutex.h +251 -0
  45. data/dependencies/SDL/include/SDL_name.h +33 -0
  46. data/dependencies/SDL/include/SDL_opengl.h +2183 -0
  47. data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
  48. data/dependencies/SDL/include/SDL_opengles.h +39 -0
  49. data/dependencies/SDL/include/SDL_opengles2.h +52 -0
  50. data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
  51. data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
  52. data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
  53. data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
  54. data/dependencies/SDL/include/SDL_pixels.h +479 -0
  55. data/dependencies/SDL/include/SDL_platform.h +198 -0
  56. data/dependencies/SDL/include/SDL_power.h +75 -0
  57. data/dependencies/SDL/include/SDL_quit.h +58 -0
  58. data/dependencies/SDL/include/SDL_rect.h +174 -0
  59. data/dependencies/SDL/include/SDL_render.h +1158 -0
  60. data/dependencies/SDL/include/SDL_revision.h +2 -0
  61. data/dependencies/SDL/include/SDL_rwops.h +283 -0
  62. data/dependencies/SDL/include/SDL_scancode.h +413 -0
  63. data/dependencies/SDL/include/SDL_sensor.h +267 -0
  64. data/dependencies/SDL/include/SDL_shape.h +144 -0
  65. data/dependencies/SDL/include/SDL_stdinc.h +647 -0
  66. data/dependencies/SDL/include/SDL_surface.h +563 -0
  67. data/dependencies/SDL/include/SDL_system.h +325 -0
  68. data/dependencies/SDL/include/SDL_syswm.h +354 -0
  69. data/dependencies/SDL/include/SDL_test.h +69 -0
  70. data/dependencies/SDL/include/SDL_test_assert.h +105 -0
  71. data/dependencies/SDL/include/SDL_test_common.h +218 -0
  72. data/dependencies/SDL/include/SDL_test_compare.h +69 -0
  73. data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
  74. data/dependencies/SDL/include/SDL_test_font.h +81 -0
  75. data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
  76. data/dependencies/SDL/include/SDL_test_harness.h +134 -0
  77. data/dependencies/SDL/include/SDL_test_images.h +78 -0
  78. data/dependencies/SDL/include/SDL_test_log.h +67 -0
  79. data/dependencies/SDL/include/SDL_test_md5.h +129 -0
  80. data/dependencies/SDL/include/SDL_test_memory.h +63 -0
  81. data/dependencies/SDL/include/SDL_test_random.h +115 -0
  82. data/dependencies/SDL/include/SDL_thread.h +366 -0
  83. data/dependencies/SDL/include/SDL_timer.h +115 -0
  84. data/dependencies/SDL/include/SDL_touch.h +102 -0
  85. data/dependencies/SDL/include/SDL_types.h +29 -0
  86. data/dependencies/SDL/include/SDL_version.h +162 -0
  87. data/dependencies/SDL/include/SDL_video.h +1282 -0
  88. data/dependencies/SDL/include/SDL_vulkan.h +276 -0
  89. data/dependencies/SDL/include/begin_code.h +166 -0
  90. data/dependencies/SDL/include/close_code.h +40 -0
  91. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  92. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  93. data/dependencies/SDL_sound/SDL_sound.c +795 -0
  94. data/dependencies/SDL_sound/SDL_sound.h +725 -0
  95. data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
  96. data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
  97. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
  98. data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
  99. data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
  100. data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
  101. data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
  102. data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
  103. data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
  104. data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
  105. data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
  106. data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
  107. data/dependencies/SDL_sound/dr_flac.h +5906 -0
  108. data/dependencies/SDL_sound/dr_mp3.h +2832 -0
  109. data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
  110. data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
  111. data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
  112. data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
  113. data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
  114. data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
  115. data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
  116. data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
  117. data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
  118. data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
  119. data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
  120. data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
  121. data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
  122. data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
  123. data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
  124. data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
  125. data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
  126. data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
  127. data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
  128. data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
  129. data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
  130. data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
  131. data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
  132. data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
  133. data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
  134. data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
  135. data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
  136. data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
  137. data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
  138. data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
  139. data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
  140. data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
  141. data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
  142. data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
  143. data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
  144. data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
  145. data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
  146. data/dependencies/al_soft/AL/al.h +655 -0
  147. data/dependencies/al_soft/AL/alc.h +270 -0
  148. data/dependencies/al_soft/AL/alext.h +585 -0
  149. data/dependencies/al_soft/AL/efx-creative.h +3 -0
  150. data/dependencies/al_soft/AL/efx-presets.h +402 -0
  151. data/dependencies/al_soft/AL/efx.h +762 -0
  152. data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
  153. data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
  154. data/{src → dependencies/stb}/stb_image.h +330 -127
  155. data/{src → dependencies/stb}/stb_image_write.h +156 -85
  156. data/{src → dependencies/stb}/stb_truetype.h +192 -69
  157. data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
  158. data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
  159. data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
  160. data/ext/gosu/extconf.rb +53 -39
  161. data/{Gosu → include/Gosu}/Audio.hpp +6 -8
  162. data/include/Gosu/Bitmap.hpp +100 -0
  163. data/{Gosu → include/Gosu}/Buttons.hpp +104 -44
  164. data/{Gosu → include/Gosu}/Color.hpp +0 -0
  165. data/{Gosu → include/Gosu}/Directories.hpp +0 -0
  166. data/{Gosu → include/Gosu}/Font.hpp +1 -1
  167. data/{Gosu → include/Gosu}/Fwd.hpp +0 -5
  168. data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
  169. data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
  170. data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
  171. data/{Gosu → include/Gosu}/IO.hpp +0 -0
  172. data/{Gosu → include/Gosu}/Image.hpp +7 -6
  173. data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
  174. data/{Gosu → include/Gosu}/Input.hpp +39 -51
  175. data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
  176. data/{Gosu → include/Gosu}/Math.hpp +0 -0
  177. data/{Gosu → include/Gosu}/Platform.hpp +0 -0
  178. data/{Gosu → include/Gosu}/Text.hpp +0 -0
  179. data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
  180. data/{Gosu → include/Gosu}/Timing.hpp +0 -0
  181. data/{Gosu → include/Gosu}/Utility.hpp +15 -4
  182. data/{Gosu → include/Gosu}/Version.hpp +3 -3
  183. data/{Gosu → include/Gosu}/Window.hpp +46 -34
  184. data/lib/OpenAL32.dll +0 -0
  185. data/lib/SDL2.dll +0 -0
  186. data/lib/gosu.rb +0 -3
  187. data/lib/gosu/patches.rb +0 -23
  188. data/lib/gosu/preview.rb +1 -3
  189. data/lib/gosu/swig_patches.rb +6 -8
  190. data/lib64/OpenAL32.dll +0 -0
  191. data/lib64/SDL2.dll +0 -0
  192. data/rdoc/gosu.rb +112 -23
  193. data/src/Audio.cpp +50 -224
  194. data/src/AudioFile.hpp +20 -37
  195. data/src/AudioFileAudioToolbox.cpp +237 -0
  196. data/src/AudioFileSDLSound.cpp +147 -0
  197. data/src/AudioImpl.cpp +3 -12
  198. data/src/AudioImpl.hpp +3 -1
  199. data/src/Bitmap.cpp +85 -83
  200. data/src/BitmapIO.cpp +52 -58
  201. data/src/Font.cpp +4 -1
  202. data/src/Graphics.cpp +7 -4
  203. data/src/Image.cpp +13 -16
  204. data/src/Input.cpp +412 -164
  205. data/src/LargeImageData.cpp +2 -1
  206. data/src/MarkupParser.cpp +2 -1
  207. data/src/Resolution.cpp +8 -8
  208. data/src/RubyGosu.cxx +1184 -352
  209. data/src/RubyGosu.h +3 -2
  210. data/src/TexChunk.cpp +1 -1
  211. data/src/Text.cpp +1 -0
  212. data/src/TextBuilder.cpp +3 -1
  213. data/src/Texture.cpp +1 -1
  214. data/src/TrueTypeFont.cpp +2 -1
  215. data/src/TrueTypeFontWin.cpp +3 -3
  216. data/src/Utility.cpp +11 -7
  217. data/src/Window.cpp +90 -62
  218. data/src/WindowUIKit.cpp +21 -9
  219. metadata +195 -46
  220. data/Gosu/AutoLink.hpp +0 -14
  221. data/Gosu/Bitmap.hpp +0 -113
  222. data/lib/gosu/zen.rb +0 -89
  223. data/src/AudioToolboxFile.hpp +0 -210
  224. data/src/MPEGFile.hpp +0 -90
  225. data/src/OggFile.hpp +0 -92
  226. data/src/SndFile.hpp +0 -174
  227. data/src/WinMain.cpp +0 -64
@@ -0,0 +1,403 @@
1
+ /*
2
+ * This source code is public domain.
3
+ *
4
+ * Authors: Olivier Lapicque <olivierl@jps.net>
5
+ */
6
+
7
+ ///////////////////////////////////////////////////
8
+ //
9
+ // AMF module loader
10
+ //
11
+ // There is 2 types of AMF files:
12
+ // - ASYLUM Music Format
13
+ // - Advanced Music Format(DSM)
14
+ //
15
+ ///////////////////////////////////////////////////
16
+ #include "libmodplug.h"
17
+
18
+ #pragma pack(1)
19
+
20
+ typedef struct _AMFFILEHEADER
21
+ {
22
+ UCHAR szAMF[3];
23
+ UCHAR version;
24
+ CHAR title[32];
25
+ UCHAR numsamples;
26
+ UCHAR numorders;
27
+ USHORT numtracks;
28
+ UCHAR numchannels;
29
+ } AMFFILEHEADER;
30
+
31
+ typedef struct _AMFSAMPLE
32
+ {
33
+ UCHAR type;
34
+ CHAR samplename[32];
35
+ CHAR filename[13];
36
+ ULONG offset;
37
+ ULONG length;
38
+ USHORT c2spd;
39
+ UCHAR volume;
40
+ } AMFSAMPLE;
41
+
42
+
43
+ #pragma pack()
44
+
45
+
46
+ VOID AMF_Unpack(MODCOMMAND *pPat, const BYTE *pTrack, UINT nRows, UINT nChannels)
47
+ //-------------------------------------------------------------------------------
48
+ {
49
+ UINT lastinstr = 0;
50
+ UINT nTrkSize = bswapLE16(*(USHORT *)pTrack);
51
+ nTrkSize += (UINT)pTrack[2] << 16;
52
+ pTrack += 3;
53
+ while (nTrkSize--)
54
+ {
55
+ UINT row = pTrack[0];
56
+ UINT cmd = pTrack[1];
57
+ UINT arg = pTrack[2];
58
+ if (row >= nRows) break;
59
+ MODCOMMAND *m = pPat + row * nChannels;
60
+ if (cmd < 0x7F) // note+vol
61
+ {
62
+ m->note = cmd+1;
63
+ if (!m->instr) m->instr = lastinstr;
64
+ m->volcmd = VOLCMD_VOLUME;
65
+ m->vol = arg;
66
+ } else
67
+ if (cmd == 0x7F) // duplicate row
68
+ {
69
+ signed char rdelta = (signed char)arg;
70
+ int rowsrc = (int)row + (int)rdelta;
71
+ if ((rowsrc >= 0) && (rowsrc < (int)nRows)) SDL_memcpy(m, &pPat[rowsrc*nChannels],sizeof(pPat[rowsrc*nChannels]));
72
+ } else
73
+ if (cmd == 0x80) // instrument
74
+ {
75
+ m->instr = arg+1;
76
+ lastinstr = m->instr;
77
+ } else
78
+ if (cmd == 0x83) // volume
79
+ {
80
+ m->volcmd = VOLCMD_VOLUME;
81
+ m->vol = arg;
82
+ } else
83
+ // effect
84
+ {
85
+ UINT command = cmd & 0x7F;
86
+ UINT param = arg;
87
+ switch(command)
88
+ {
89
+ // 0x01: Set Speed
90
+ case 0x01: command = CMD_SPEED; break;
91
+ // 0x02: Volume Slide
92
+ // 0x0A: Tone Porta + Vol Slide
93
+ // 0x0B: Vibrato + Vol Slide
94
+ case 0x02: command = CMD_VOLUMESLIDE;
95
+ case 0x0A: if (command == 0x0A) command = CMD_TONEPORTAVOL;
96
+ case 0x0B: if (command == 0x0B) command = CMD_VIBRATOVOL;
97
+ if (param & 0x80) param = (-(signed char)param)&0x0F;
98
+ else param = (param&0x0F)<<4;
99
+ break;
100
+ // 0x04: Porta Up/Down
101
+ case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = (-(signed char)param)&0x7F; }
102
+ else { command = CMD_PORTAMENTODOWN; } break;
103
+ // 0x06: Tone Portamento
104
+ case 0x06: command = CMD_TONEPORTAMENTO; break;
105
+ // 0x07: Tremor
106
+ case 0x07: command = CMD_TREMOR; break;
107
+ // 0x08: Arpeggio
108
+ case 0x08: command = CMD_ARPEGGIO; break;
109
+ // 0x09: Vibrato
110
+ case 0x09: command = CMD_VIBRATO; break;
111
+ // 0x0C: Pattern Break
112
+ case 0x0C: command = CMD_PATTERNBREAK; break;
113
+ // 0x0D: Position Jump
114
+ case 0x0D: command = CMD_POSITIONJUMP; break;
115
+ // 0x0F: Retrig
116
+ case 0x0F: command = CMD_RETRIG; break;
117
+ // 0x10: Offset
118
+ case 0x10: command = CMD_OFFSET; break;
119
+ // 0x11: Fine Volume Slide
120
+ case 0x11: if (param) { command = CMD_VOLUMESLIDE;
121
+ if (param & 0x80) param = 0xF0|((-(signed char)param)&0x0F);
122
+ else param = 0x0F|((param&0x0F)<<4);
123
+ } else command = 0; break;
124
+ // 0x12: Fine Portamento
125
+ // 0x16: Extra Fine Portamento
126
+ case 0x12:
127
+ case 0x16: if (param) { int mask = (command == 0x16) ? 0xE0 : 0xF0;
128
+ command = (param & 0x80) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN;
129
+ if (param & 0x80) param = mask|((-(signed char)param)&0x0F);
130
+ else param |= mask;
131
+ } else command = 0; break;
132
+ // 0x13: Note Delay
133
+ case 0x13: command = CMD_S3MCMDEX; param = 0xD0|(param & 0x0F); break;
134
+ // 0x14: Note Cut
135
+ case 0x14: command = CMD_S3MCMDEX; param = 0xC0|(param & 0x0F); break;
136
+ // 0x15: Set Tempo
137
+ case 0x15: command = CMD_TEMPO; break;
138
+ // 0x17: Panning
139
+ case 0x17: param = (param+64)&0x7F;
140
+ if (m->command) { if (!m->volcmd) { m->volcmd = VOLCMD_PANNING; m->vol = param/2; } command = 0; }
141
+ else { command = CMD_PANNING8; }
142
+ // Unknown effects
143
+ default: command = param = 0;
144
+ }
145
+ if (command)
146
+ {
147
+ m->command = command;
148
+ m->param = param;
149
+ }
150
+ }
151
+ pTrack += 3;
152
+ }
153
+ }
154
+
155
+
156
+
157
+ BOOL CSoundFile_ReadAMF(CSoundFile *_this, LPCBYTE lpStream, const DWORD dwMemLength)
158
+ //-----------------------------------------------------------
159
+ {
160
+ const AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream;
161
+ DWORD dwMemPos;
162
+
163
+ if ((!lpStream) || (dwMemLength < 2048)) return FALSE;
164
+ if ((!SDL_strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096))
165
+ {
166
+ UINT numorders, numpats, numsamples;
167
+
168
+ dwMemPos = 32;
169
+ numpats = lpStream[dwMemPos+3];
170
+ numorders = lpStream[dwMemPos+4];
171
+ numsamples = 64;
172
+ dwMemPos += 6;
173
+ if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders)
174
+ || (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE;
175
+ _this->m_nType = MOD_TYPE_AMF0;
176
+ _this->m_nChannels = 8;
177
+ _this->m_nInstruments = 0;
178
+ _this->m_nSamples = 31;
179
+ _this->m_nDefaultTempo = 125;
180
+ _this->m_nDefaultSpeed = 6;
181
+ for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
182
+ {
183
+ _this->Order[iOrd] = (iOrd < numorders) ? lpStream[dwMemPos+iOrd] : 0xFF;
184
+ }
185
+ dwMemPos = 294; // ???
186
+ for (UINT iSmp=0; iSmp<numsamples; iSmp++)
187
+ {
188
+ MODINSTRUMENT *psmp = &_this->Ins[iSmp+1];
189
+ psmp->nFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]);
190
+ psmp->nVolume = lpStream[dwMemPos+23];
191
+ psmp->nGlobalVol = 64;
192
+ if (psmp->nVolume > 0x40) psmp->nVolume = 0x40;
193
+ psmp->nVolume <<= 2;
194
+ psmp->nLength = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+25)));
195
+ psmp->nLoopStart = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+29)));
196
+ psmp->nLoopEnd = psmp->nLoopStart + bswapLE32(*((LPDWORD)(lpStream+dwMemPos+33)));
197
+ if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength))
198
+ {
199
+ psmp->uFlags = CHN_LOOP;
200
+ } else
201
+ {
202
+ psmp->nLoopStart = psmp->nLoopEnd = 0;
203
+ }
204
+ if ((psmp->nLength) && (iSmp>31)) _this->m_nSamples = iSmp+1;
205
+ dwMemPos += 37;
206
+ }
207
+ for (UINT iPat=0; iPat<numpats; iPat++)
208
+ {
209
+ MODCOMMAND *p = CSoundFile_AllocatePattern(64, _this->m_nChannels);
210
+ if (!p) break;
211
+ _this->Patterns[iPat] = p;
212
+ _this->PatternSize[iPat] = 64;
213
+ const UCHAR *pin = lpStream + dwMemPos;
214
+ for (UINT i=0; i<8*64; i++)
215
+ {
216
+ p->note = 0;
217
+
218
+ if (pin[0])
219
+ {
220
+ p->note = pin[0] + 13;
221
+ }
222
+ p->instr = pin[1];
223
+ p->command = pin[2];
224
+ p->param = pin[3];
225
+ if (p->command > 0x0F)
226
+ {
227
+ p->command = 0;
228
+ }
229
+ CSoundFile_ConvertModCommand(_this, p);
230
+ pin += 4;
231
+ p++;
232
+ }
233
+ dwMemPos += 64*32;
234
+ }
235
+ // Read samples
236
+ for (UINT iData=0; iData<_this->m_nSamples; iData++)
237
+ {
238
+ MODINSTRUMENT *psmp = &_this->Ins[iData+1];
239
+ if (psmp->nLength)
240
+ {
241
+ if (dwMemPos > dwMemLength) return FALSE;
242
+ dwMemPos += CSoundFile_ReadSample(_this, psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
243
+ }
244
+ }
245
+ return TRUE;
246
+ }
247
+ ////////////////////////////
248
+ // DSM/AMF
249
+ USHORT *ptracks[MAX_PATTERNS];
250
+ DWORD sampleseekpos[MAX_SAMPLES];
251
+
252
+ if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F')
253
+ || (pfh->version < 10) || (pfh->version > 14) || (!bswapLE16(pfh->numtracks))
254
+ || (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS)
255
+ || (!pfh->numsamples) || (pfh->numsamples >= MAX_SAMPLES)
256
+ || (pfh->numchannels < 4) || (pfh->numchannels > 32))
257
+ return FALSE;
258
+ dwMemPos = sizeof(AMFFILEHEADER);
259
+ _this->m_nType = MOD_TYPE_AMF;
260
+ _this->m_nChannels = pfh->numchannels;
261
+ _this->m_nSamples = pfh->numsamples;
262
+ _this->m_nInstruments = 0;
263
+ // Setup Channel Pan Positions
264
+ if (pfh->version >= 11)
265
+ {
266
+ signed char *panpos = (signed char *)(lpStream + dwMemPos);
267
+ UINT nchannels = (pfh->version >= 13) ? 32 : 16;
268
+ for (UINT i=0; i<nchannels; i++)
269
+ {
270
+ int pan = (panpos[i] + 64) * 2;
271
+ if (pan < 0) pan = 0;
272
+ if (pan > 256) { pan = 128; _this->ChnSettings[i].dwFlags |= CHN_SURROUND; }
273
+ _this->ChnSettings[i].nPan = pan;
274
+ }
275
+ dwMemPos += nchannels;
276
+ } else
277
+ {
278
+ for (UINT i=0; i<16; i++)
279
+ {
280
+ _this->ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0;
281
+ }
282
+ dwMemPos += 16;
283
+ }
284
+ // Get Tempo/Speed
285
+ _this->m_nDefaultTempo = 125;
286
+ _this->m_nDefaultSpeed = 6;
287
+ if (pfh->version >= 13)
288
+ {
289
+ if (lpStream[dwMemPos] >= 32) _this->m_nDefaultTempo = lpStream[dwMemPos];
290
+ if (lpStream[dwMemPos+1] <= 32) _this->m_nDefaultSpeed = lpStream[dwMemPos+1];
291
+ dwMemPos += 2;
292
+ }
293
+ // Setup sequence list
294
+ for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
295
+ {
296
+ _this->Order[iOrd] = 0xFF;
297
+ if (iOrd < pfh->numorders)
298
+ {
299
+ _this->Order[iOrd] = iOrd;
300
+ _this->PatternSize[iOrd] = 64;
301
+ if (pfh->version >= 14)
302
+ {
303
+ _this->PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos));
304
+ dwMemPos += 2;
305
+ }
306
+ ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos);
307
+ dwMemPos += _this->m_nChannels * sizeof(USHORT);
308
+ }
309
+ }
310
+ if (dwMemPos + _this->m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE;
311
+ // Read Samples
312
+ UINT maxsampleseekpos = 0;
313
+ for (UINT iIns=0; iIns<_this->m_nSamples; iIns++)
314
+ {
315
+ MODINSTRUMENT *pins = &_this->Ins[iIns+1];
316
+ const AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos);
317
+
318
+ dwMemPos += sizeof(AMFSAMPLE);
319
+ pins->nLength = bswapLE32(psh->length);
320
+ pins->nC4Speed = bswapLE16(psh->c2spd);
321
+ pins->nGlobalVol = 64;
322
+ pins->nVolume = psh->volume * 4;
323
+ if (pfh->version >= 11)
324
+ {
325
+ pins->nLoopStart = bswapLE32(*(DWORD *)(lpStream+dwMemPos));
326
+ pins->nLoopEnd = bswapLE32(*(DWORD *)(lpStream+dwMemPos+4));
327
+ dwMemPos += 8;
328
+ } else
329
+ {
330
+ pins->nLoopStart = bswapLE16(*(WORD *)(lpStream+dwMemPos));
331
+ pins->nLoopEnd = pins->nLength;
332
+ dwMemPos += 2;
333
+ }
334
+ sampleseekpos[iIns] = 0;
335
+ if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1))
336
+ {
337
+ sampleseekpos[iIns] = bswapLE32(psh->offset);
338
+ if (bswapLE32(psh->offset) > maxsampleseekpos)
339
+ maxsampleseekpos = bswapLE32(psh->offset);
340
+ if ((pins->nLoopEnd > pins->nLoopStart + 2)
341
+ && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP;
342
+ }
343
+ }
344
+ // Read Track Mapping Table
345
+ USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos);
346
+ UINT realtrackcnt = 0;
347
+ dwMemPos += pfh->numtracks * sizeof(USHORT);
348
+ for (UINT iTrkMap=0; iTrkMap<pfh->numtracks; iTrkMap++)
349
+ {
350
+ if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap];
351
+ }
352
+ // Store tracks positions
353
+ BYTE **pTrackData = (BYTE **) SDL_malloc(sizeof (BYTE *) * realtrackcnt);
354
+ if (!pTrackData) return TRUE;
355
+ SDL_memset(pTrackData, 0, sizeof(BYTE *) * realtrackcnt);
356
+ for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos <= dwMemLength - 3)
357
+ {
358
+ UINT nTrkSize = bswapLE16(*(USHORT *)(lpStream+dwMemPos));
359
+ nTrkSize += (UINT)lpStream[dwMemPos+2] << 16;
360
+ if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength)
361
+ {
362
+ pTrackData[iTrack] = (BYTE *)(lpStream + dwMemPos);
363
+ }
364
+ dwMemPos += nTrkSize * 3 + 3;
365
+ }
366
+ // Create the patterns from the list of tracks
367
+ for (UINT iPat=0; iPat<pfh->numorders; iPat++)
368
+ {
369
+ MODCOMMAND *p = CSoundFile_AllocatePattern(_this->PatternSize[iPat], _this->m_nChannels);
370
+ if (!p) break;
371
+ _this->Patterns[iPat] = p;
372
+ for (UINT iChn=0; iChn<_this->m_nChannels; iChn++)
373
+ {
374
+ UINT nTrack = bswapLE16(ptracks[iPat][iChn]);
375
+ if ((nTrack) && (nTrack <= pfh->numtracks))
376
+ {
377
+ UINT realtrk = bswapLE16(pTrackMap[nTrack-1]);
378
+ if (realtrk)
379
+ {
380
+ realtrk--;
381
+ if ((realtrk < realtrackcnt) && (pTrackData[realtrk]))
382
+ {
383
+ AMF_Unpack(p+iChn, pTrackData[realtrk], _this->PatternSize[iPat], _this->m_nChannels);
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ SDL_free(pTrackData);
390
+ // Read Sample Data
391
+ for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++)
392
+ {
393
+ if (dwMemPos >= dwMemLength) break;
394
+ for (UINT iSmp=0; iSmp<_this->m_nSamples; iSmp++) if (iSeek == sampleseekpos[iSmp])
395
+ {
396
+ MODINSTRUMENT *pins = &_this->Ins[iSmp+1];
397
+ dwMemPos += CSoundFile_ReadSample(_this, pins, RS_PCM8U, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
398
+ break;
399
+ }
400
+ }
401
+ return TRUE;
402
+ }
403
+
@@ -0,0 +1,587 @@
1
+ /*
2
+ * This source code is public domain.
3
+ *
4
+ * Authors: Olivier Lapicque <olivierl@jps.net>
5
+ */
6
+
7
+ //////////////////////////////////////////////
8
+ // AMS module loader //
9
+ //////////////////////////////////////////////
10
+ #include "libmodplug.h"
11
+
12
+ #pragma pack(1)
13
+
14
+ typedef struct AMSFILEHEADER
15
+ {
16
+ char szHeader[7]; // "Extreme" // changed from CHAR
17
+ BYTE verlo, verhi; // 0x??,0x01
18
+ BYTE chncfg;
19
+ BYTE samples;
20
+ WORD patterns;
21
+ WORD orders;
22
+ BYTE vmidi;
23
+ WORD extra;
24
+ } AMSFILEHEADER;
25
+
26
+ typedef struct AMSSAMPLEHEADER
27
+ {
28
+ DWORD length;
29
+ DWORD loopstart;
30
+ DWORD loopend;
31
+ BYTE finetune_and_pan;
32
+ WORD samplerate; // C-2 = 8363
33
+ BYTE volume; // 0-127
34
+ BYTE infobyte;
35
+ } AMSSAMPLEHEADER;
36
+
37
+
38
+ #pragma pack()
39
+
40
+
41
+ BOOL CSoundFile_ReadAMS(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
42
+ //-----------------------------------------------------------
43
+ {
44
+ BYTE pkinf[MAX_SAMPLES];
45
+ AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream;
46
+ DWORD dwMemPos;
47
+ UINT tmp, tmp2;
48
+
49
+ if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
50
+ if ((pfh->verhi != 0x01) || (SDL_strncmp(pfh->szHeader, "Extreme", 7))
51
+ || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples >= MAX_SAMPLES)
52
+ || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS))
53
+ {
54
+ return CSoundFile_ReadAMS2(_this, lpStream, dwMemLength);
55
+ }
56
+ dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra;
57
+ if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return FALSE;
58
+ _this->m_nType = MOD_TYPE_AMS;
59
+ _this->m_nInstruments = 0;
60
+ _this->m_nChannels = (pfh->chncfg & 0x1F) + 1;
61
+ _this->m_nSamples = pfh->samples;
62
+ for (UINT nSmp=1; nSmp<=_this->m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER))
63
+ {
64
+ AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos);
65
+ MODINSTRUMENT *pins = &_this->Ins[nSmp];
66
+ pins->nLength = psh->length;
67
+ pins->nLoopStart = psh->loopstart;
68
+ pins->nLoopEnd = psh->loopend;
69
+ pins->nGlobalVol = 64;
70
+ pins->nVolume = psh->volume << 1;
71
+ pins->nC4Speed = psh->samplerate;
72
+ pins->nPan = (psh->finetune_and_pan & 0xF0);
73
+ if (pins->nPan < 0x80) pins->nPan += 0x10;
74
+ pins->nFineTune = MOD2XMFineTune(psh->finetune_and_pan & 0x0F);
75
+ pins->uFlags = (psh->infobyte & 0x80) ? CHN_16BIT : 0;
76
+ if ((pins->nLoopEnd <= pins->nLength) && (pins->nLoopStart+4 <= pins->nLoopEnd)) pins->uFlags |= CHN_LOOP;
77
+ pkinf[nSmp] = psh->infobyte;
78
+ }
79
+ // Read Song Name
80
+ tmp = lpStream[dwMemPos++];
81
+ if (dwMemPos + tmp + 1 >= dwMemLength) return TRUE;
82
+ dwMemPos += tmp;
83
+ // Read sample names
84
+ for (UINT sNam=1; sNam<=_this->m_nSamples; sNam++)
85
+ {
86
+ if (dwMemPos + 32 >= dwMemLength) return TRUE;
87
+ tmp = lpStream[dwMemPos++];
88
+ dwMemPos += tmp;
89
+ }
90
+ // Skip Channel names
91
+ for (UINT cNam=0; cNam<_this->m_nChannels; cNam++)
92
+ {
93
+ if (dwMemPos + 32 >= dwMemLength) return TRUE;
94
+ tmp = lpStream[dwMemPos++];
95
+ dwMemPos += tmp;
96
+ }
97
+ // Read Pattern Names
98
+ _this->m_lpszPatternNames = (char *) SDL_malloc(pfh->patterns * 32); // changed from CHAR
99
+ if (!_this->m_lpszPatternNames) return TRUE;
100
+ _this->m_nPatternNames = pfh->patterns;
101
+ SDL_memset(_this->m_lpszPatternNames, 0, _this->m_nPatternNames * 32);
102
+ for (UINT pNam=0; pNam < _this->m_nPatternNames; pNam++)
103
+ {
104
+ if (dwMemPos + 32 >= dwMemLength) return TRUE;
105
+ tmp = lpStream[dwMemPos++];
106
+ tmp2 = (tmp < 32) ? tmp : 31;
107
+ if (tmp2) SDL_memcpy(_this->m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2);
108
+ dwMemPos += tmp;
109
+ }
110
+ // Read Song Comments
111
+ tmp = *((WORD *)(lpStream+dwMemPos));
112
+ dwMemPos += 2;
113
+ if (dwMemPos + tmp >= dwMemLength) return TRUE;
114
+ if (tmp)
115
+ {
116
+ dwMemPos += tmp;
117
+ }
118
+ // Read Order List
119
+ for (UINT iOrd=0; iOrd<pfh->orders; iOrd++, dwMemPos += 2)
120
+ {
121
+ UINT n = *((WORD *)(lpStream+dwMemPos));
122
+ _this->Order[iOrd] = (BYTE)n;
123
+ }
124
+ // Read Patterns
125
+ for (UINT iPat=0; iPat<pfh->patterns; iPat++)
126
+ {
127
+ if (dwMemPos + 4 >= dwMemLength) return TRUE;
128
+ UINT len = *((DWORD *)(lpStream + dwMemPos));
129
+ dwMemPos += 4;
130
+ if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE;
131
+ _this->PatternSize[iPat] = 64;
132
+ MODCOMMAND *m = CSoundFile_AllocatePattern(_this->PatternSize[iPat], _this->m_nChannels);
133
+ if (!m) return TRUE;
134
+ _this->Patterns[iPat] = m;
135
+ const BYTE *p = lpStream + dwMemPos;
136
+ UINT row = 0, i = 0;
137
+ while ((row < _this->PatternSize[iPat]) && (i+2 < len))
138
+ {
139
+ BYTE b0 = p[i++];
140
+ BYTE b1 = p[i++];
141
+ BYTE b2 = 0;
142
+ UINT ch = b0 & 0x3F;
143
+ // Note+Instr
144
+ if (!(b0 & 0x40))
145
+ {
146
+ b2 = p[i++];
147
+ if (ch < _this->m_nChannels)
148
+ {
149
+ if (b1 & 0x7F) m[ch].note = (b1 & 0x7F) + 25;
150
+ m[ch].instr = b2;
151
+ }
152
+ if (b1 & 0x80)
153
+ {
154
+ b0 |= 0x40;
155
+ b1 = p[i++];
156
+ }
157
+ }
158
+ // Effect
159
+ if (b0 & 0x40)
160
+ {
161
+ anothercommand:
162
+ if (b1 & 0x40)
163
+ {
164
+ if (ch < _this->m_nChannels)
165
+ {
166
+ m[ch].volcmd = VOLCMD_VOLUME;
167
+ m[ch].vol = b1 & 0x3F;
168
+ }
169
+ } else
170
+ {
171
+ b2 = p[i++];
172
+ if (ch < _this->m_nChannels)
173
+ {
174
+ UINT cmd = b1 & 0x3F;
175
+ if (cmd == 0x0C)
176
+ {
177
+ m[ch].volcmd = VOLCMD_VOLUME;
178
+ m[ch].vol = b2 >> 1;
179
+ } else
180
+ if (cmd == 0x0E)
181
+ {
182
+ if (!m[ch].command)
183
+ {
184
+ UINT command = CMD_S3MCMDEX;
185
+ UINT param = b2;
186
+ switch(param & 0xF0)
187
+ {
188
+ case 0x00: if (param & 0x08) { param &= 0x07; param |= 0x90; } else {command=param=0;} break;
189
+ case 0x10: command = CMD_PORTAMENTOUP; param |= 0xF0; break;
190
+ case 0x20: command = CMD_PORTAMENTODOWN; param |= 0xF0; break;
191
+ case 0x30: param = (param & 0x0F) | 0x10; break;
192
+ case 0x40: param = (param & 0x0F) | 0x30; break;
193
+ case 0x50: param = (param & 0x0F) | 0x20; break;
194
+ case 0x60: param = (param & 0x0F) | 0xB0; break;
195
+ case 0x70: param = (param & 0x0F) | 0x40; break;
196
+ case 0x90: command = CMD_RETRIG; param &= 0x0F; break;
197
+ case 0xA0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param = (param << 4) | 0x0F; } else command=param=0; break;
198
+ case 0xB0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param |= 0xF0; } else command=param=0; break;
199
+ }
200
+ m[ch].command = command;
201
+ m[ch].param = param;
202
+ }
203
+ } else
204
+ {
205
+ m[ch].command = cmd;
206
+ m[ch].param = b2;
207
+ CSoundFile_ConvertModCommand(_this, &m[ch]);
208
+ }
209
+ }
210
+ }
211
+ if (b1 & 0x80)
212
+ {
213
+ b1 = p[i++];
214
+ if (i <= len) goto anothercommand;
215
+ }
216
+ }
217
+ if (b0 & 0x80)
218
+ {
219
+ row++;
220
+ m += _this->m_nChannels;
221
+ }
222
+ }
223
+ dwMemPos += len;
224
+ }
225
+ // Read Samples
226
+ for (UINT iSmp=1; iSmp<=_this->m_nSamples; iSmp++) if (_this->Ins[iSmp].nLength)
227
+ {
228
+ if (dwMemPos >= dwMemLength - 9) return TRUE;
229
+ UINT flags = (_this->Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
230
+ dwMemPos += CSoundFile_ReadSample(_this, &_this->Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
231
+ }
232
+ return TRUE;
233
+ }
234
+
235
+
236
+ /////////////////////////////////////////////////////////////////////
237
+ // AMS 2.2 loader
238
+
239
+ #pragma pack(1)
240
+
241
+ typedef struct AMS2FILEHEADER
242
+ {
243
+ DWORD dwHdr1; // AMShdr
244
+ WORD wHdr2;
245
+ BYTE b1A; // 0x1A
246
+ BYTE titlelen; // 30-bytes max
247
+ CHAR szTitle[30]; // [titlelen]
248
+ } AMS2FILEHEADER;
249
+
250
+ typedef struct AMS2SONGHEADER
251
+ {
252
+ WORD version;
253
+ BYTE instruments;
254
+ WORD patterns;
255
+ WORD orders;
256
+ WORD bpm;
257
+ BYTE speed;
258
+ BYTE channels;
259
+ BYTE commands;
260
+ BYTE rows;
261
+ WORD flags;
262
+ } AMS2SONGHEADER;
263
+
264
+ typedef struct AMS2INSTRUMENT
265
+ {
266
+ BYTE samples;
267
+ BYTE notemap[NOTE_MAX];
268
+ } AMS2INSTRUMENT;
269
+
270
+ typedef struct AMS2ENVELOPE
271
+ {
272
+ BYTE speed;
273
+ BYTE sustain;
274
+ BYTE loopbegin;
275
+ BYTE loopend;
276
+ BYTE points;
277
+ BYTE info[3];
278
+ } AMS2ENVELOPE;
279
+
280
+ typedef struct AMS2SAMPLE
281
+ {
282
+ DWORD length;
283
+ DWORD loopstart;
284
+ DWORD loopend;
285
+ WORD frequency;
286
+ BYTE finetune;
287
+ WORD c4speed;
288
+ CHAR transpose;
289
+ BYTE volume;
290
+ BYTE flags;
291
+ } AMS2SAMPLE;
292
+
293
+
294
+ #pragma pack()
295
+
296
+
297
+ BOOL CSoundFile_ReadAMS2(CSoundFile *_this, LPCBYTE lpStream, DWORD dwMemLength)
298
+ //------------------------------------------------------------
299
+ {
300
+ const AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream;
301
+ AMS2SONGHEADER *psh;
302
+ DWORD dwMemPos;
303
+ BYTE smpmap[16];
304
+ BYTE packedsamples[MAX_SAMPLES];
305
+
306
+ if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264)
307
+ || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE;
308
+ dwMemPos = pfh->titlelen + 8;
309
+ psh = (AMS2SONGHEADER *)(lpStream + dwMemPos);
310
+ if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments)
311
+ || (psh->instruments >= MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE;
312
+ dwMemPos += sizeof(AMS2SONGHEADER);
313
+ _this->m_nType = MOD_TYPE_AMS;
314
+ _this->m_nChannels = 32;
315
+ _this->m_nDefaultTempo = psh->bpm >> 8;
316
+ _this->m_nDefaultSpeed = psh->speed;
317
+ _this->m_nInstruments = psh->instruments;
318
+ _this->m_nSamples = 0;
319
+ if (psh->flags & 0x40) _this->m_dwSongFlags |= SONG_LINEARSLIDES;
320
+ for (UINT nIns=1; nIns<=_this->m_nInstruments; nIns++)
321
+ {
322
+ const UINT insnamelen = lpStream[dwMemPos];
323
+ CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1);
324
+ dwMemPos += insnamelen + 1;
325
+ AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos);
326
+ dwMemPos += sizeof(AMS2INSTRUMENT);
327
+ if (dwMemPos + 1024 >= dwMemLength) return TRUE;
328
+ AMS2ENVELOPE *volenv, *panenv, *pitchenv;
329
+ volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
330
+ dwMemPos += 5 + volenv->points*3;
331
+ panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
332
+ dwMemPos += 5 + panenv->points*3;
333
+ pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
334
+ dwMemPos += 5 + pitchenv->points*3;
335
+ INSTRUMENTHEADER *penv = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER));
336
+ if (!penv) return TRUE;
337
+ SDL_memset(smpmap, 0, sizeof(smpmap));
338
+ SDL_memset(penv, 0, sizeof(INSTRUMENTHEADER));
339
+ for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++)
340
+ {
341
+ if ((ismpmap >= 16) || (_this->m_nSamples+1 >= MAX_SAMPLES)) break;
342
+ _this->m_nSamples++;
343
+ smpmap[ismpmap] = _this->m_nSamples;
344
+ }
345
+ penv->nGlobalVol = 64;
346
+ penv->nPan = 128;
347
+ penv->nPPC = 60;
348
+ _this->Headers[nIns] = penv;
349
+ for (UINT inotemap=0; inotemap<NOTE_MAX; inotemap++)
350
+ {
351
+ penv->NoteMap[inotemap] = inotemap+1;
352
+ penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F];
353
+ }
354
+ // Volume Envelope
355
+ {
356
+ UINT pos = 0;
357
+ penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points;
358
+ penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain;
359
+ penv->nVolLoopStart = volenv->loopbegin;
360
+ penv->nVolLoopEnd = volenv->loopend;
361
+ for (UINT i=0; i<penv->nVolEnv; i++)
362
+ {
363
+ penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
364
+ pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8);
365
+ penv->VolPoints[i] = (WORD)pos;
366
+ }
367
+ }
368
+ penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3;
369
+ UINT envflags = lpStream[dwMemPos+3];
370
+ if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP;
371
+ if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN;
372
+ if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME;
373
+ dwMemPos += 5;
374
+ // Read Samples
375
+ for (UINT ismp=0; ismp<pins->samples; ismp++)
376
+ {
377
+ MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &_this->Ins[smpmap[ismp]] : NULL;
378
+ const UINT smpnamelen = lpStream[dwMemPos];
379
+ dwMemPos += smpnamelen + 1;
380
+ if (psmp)
381
+ {
382
+ AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos);
383
+ psmp->nGlobalVol = 64;
384
+ psmp->nPan = 128;
385
+ psmp->nLength = pams->length;
386
+ psmp->nLoopStart = pams->loopstart;
387
+ psmp->nLoopEnd = pams->loopend;
388
+ psmp->nC4Speed = pams->c4speed;
389
+ psmp->RelativeTone = pams->transpose;
390
+ psmp->nVolume = pams->volume / 2;
391
+ packedsamples[smpmap[ismp]] = pams->flags;
392
+ if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT;
393
+ if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP;
394
+ if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP;
395
+ }
396
+ dwMemPos += sizeof(AMS2SAMPLE);
397
+ }
398
+ }
399
+ if (dwMemPos + 256 >= dwMemLength) return TRUE;
400
+ // Comments
401
+ {
402
+ UINT composernamelen = lpStream[dwMemPos];
403
+ dwMemPos += composernamelen + 1;
404
+ // channel names
405
+ for (UINT i=0; i<32; i++)
406
+ {
407
+ const UINT chnnamlen = lpStream[dwMemPos];
408
+ dwMemPos += chnnamlen + 1;
409
+ if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE;
410
+ }
411
+ // packed comments (ignored)
412
+ UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos));
413
+ dwMemPos += songtextlen;
414
+ if (dwMemPos + 256 >= dwMemLength) return TRUE;
415
+ }
416
+ // Order List
417
+ {
418
+ for (UINT i=0; i<MAX_ORDERS; i++)
419
+ {
420
+ _this->Order[i] = 0xFF;
421
+ if (dwMemPos + 2 >= dwMemLength) return TRUE;
422
+ if (i < psh->orders)
423
+ {
424
+ _this->Order[i] = lpStream[dwMemPos];
425
+ dwMemPos += 2;
426
+ }
427
+ }
428
+ }
429
+ // Pattern Data
430
+ for (UINT ipat=0; ipat<psh->patterns; ipat++)
431
+ {
432
+ if (dwMemPos+8 >= dwMemLength) return TRUE;
433
+ UINT packedlen = *((LPDWORD)(lpStream+dwMemPos));
434
+ UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]);
435
+ //UINT patchn = 1 + (UINT)(lpStream[dwMemPos+5] & 0x1F);
436
+ //UINT patcmds = 1 + (UINT)(lpStream[dwMemPos+5] >> 5);
437
+ UINT patnamlen = lpStream[dwMemPos+6];
438
+ dwMemPos += 4;
439
+ if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8))
440
+ {
441
+ if ((patnamlen) && (patnamlen < MAX_PATTERNNAME))
442
+ {
443
+ char s[MAX_PATTERNNAME]; // changed from CHAR
444
+ SDL_memcpy(s, lpStream+dwMemPos+3, patnamlen);
445
+ s[patnamlen] = 0;
446
+ CSoundFile_SetPatternName(_this, ipat, s);
447
+ }
448
+ _this->PatternSize[ipat] = numrows;
449
+ _this->Patterns[ipat] = CSoundFile_AllocatePattern(numrows, _this->m_nChannels);
450
+ if (!_this->Patterns[ipat]) return TRUE;
451
+ // Unpack Pattern Data
452
+ LPCBYTE psrc = lpStream + dwMemPos;
453
+ UINT pos = 3 + patnamlen;
454
+ UINT row = 0;
455
+ while ((pos < packedlen) && (row < numrows))
456
+ {
457
+ MODCOMMAND *m = _this->Patterns[ipat] + row * _this->m_nChannels;
458
+ UINT byte1 = psrc[pos++];
459
+ UINT ch = byte1 & 0x1F;
460
+ // Read Note + Instr
461
+ if (!(byte1 & 0x40))
462
+ {
463
+ UINT byte2 = psrc[pos++];
464
+ UINT note = byte2 & 0x7F;
465
+ if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF;
466
+ m[ch].instr = psrc[pos++];
467
+ // Read Effect
468
+ while (byte2 & 0x80)
469
+ {
470
+ byte2 = psrc[pos++];
471
+ if (byte2 & 0x40)
472
+ {
473
+ m[ch].volcmd = VOLCMD_VOLUME;
474
+ m[ch].vol = byte2 & 0x3F;
475
+ } else
476
+ {
477
+ UINT command = byte2 & 0x3F;
478
+ UINT param = psrc[pos++];
479
+ if (command == 0x0C)
480
+ {
481
+ m[ch].volcmd = VOLCMD_VOLUME;
482
+ m[ch].vol = param / 2;
483
+ } else
484
+ if (command < 0x10)
485
+ {
486
+ m[ch].command = command;
487
+ m[ch].param = param;
488
+ CSoundFile_ConvertModCommand(_this, &m[ch]);
489
+ } else
490
+ {
491
+ // TODO: AMS effects
492
+ }
493
+ }
494
+ }
495
+ }
496
+ if (byte1 & 0x80) row++;
497
+ }
498
+ }
499
+ dwMemPos += packedlen;
500
+ }
501
+ // Read Samples
502
+ for (UINT iSmp=1; iSmp<=_this->m_nSamples; iSmp++) if (_this->Ins[iSmp].nLength)
503
+ {
504
+ if (dwMemPos >= dwMemLength - 9) return TRUE;
505
+ UINT flags;
506
+ if (packedsamples[iSmp] & 0x03)
507
+ {
508
+ flags = (_this->Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
509
+ } else
510
+ {
511
+ flags = (_this->Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
512
+ }
513
+ dwMemPos += CSoundFile_ReadSample(_this, &_this->Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
514
+ }
515
+ return TRUE;
516
+ }
517
+
518
+
519
+ /////////////////////////////////////////////////////////////////////
520
+ // AMS Sample unpacking
521
+
522
+ void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter)
523
+ {
524
+ UINT tmplen = dmax;
525
+ signed char *amstmp = (signed char *) SDL_malloc(tmplen);
526
+
527
+ if (!amstmp) return;
528
+ // Unpack Loop
529
+ {
530
+ signed char *p = amstmp;
531
+ UINT i=0, j=0;
532
+ while ((i < inputlen) && (j < tmplen))
533
+ {
534
+ signed char ch = psrc[i++];
535
+ if (ch == packcharacter)
536
+ {
537
+ BYTE ch2 = psrc[i++];
538
+ if (ch2)
539
+ {
540
+ ch = psrc[i++];
541
+ while (ch2--)
542
+ {
543
+ p[j++] = ch;
544
+ if (j >= tmplen) break;
545
+ }
546
+ } else p[j++] = packcharacter;
547
+ } else p[j++] = ch;
548
+ }
549
+ }
550
+ // Bit Unpack Loop
551
+ {
552
+ signed char *p = amstmp;
553
+ UINT bitcount = 0x80, dh;
554
+ UINT k=0;
555
+ for (UINT i=0; i<dmax; i++)
556
+ {
557
+ BYTE al = *p++;
558
+ dh = 0;
559
+ for (UINT count=0; count<8; count++)
560
+ {
561
+ UINT bl = al & bitcount;
562
+ bl = ((bl|(bl<<8)) >> ((dh+8-count) & 7)) & 0xFF;
563
+ bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF;
564
+ pdest[k++] |= bl;
565
+ if (k >= dmax)
566
+ {
567
+ k = 0;
568
+ dh++;
569
+ }
570
+ }
571
+ bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF;
572
+ }
573
+ }
574
+ // Delta Unpack
575
+ {
576
+ signed char old = 0;
577
+ for (UINT i=0; i<dmax; i++)
578
+ {
579
+ int pos = ((LPBYTE)pdest)[i];
580
+ if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F);
581
+ old -= (signed char)pos;
582
+ pdest[i] = old;
583
+ }
584
+ }
585
+ SDL_free(amstmp);
586
+ }
587
+