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.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/COPYING +1 -1
- data/dependencies/SDL/include/SDL.h +138 -0
- data/dependencies/SDL/include/SDL_assert.h +293 -0
- data/dependencies/SDL/include/SDL_atomic.h +295 -0
- data/dependencies/SDL/include/SDL_audio.h +859 -0
- data/dependencies/SDL/include/SDL_bits.h +121 -0
- data/dependencies/SDL/include/SDL_blendmode.h +123 -0
- data/dependencies/SDL/include/SDL_clipboard.h +71 -0
- data/dependencies/SDL/include/SDL_config.h +55 -0
- data/dependencies/SDL/include/SDL_config_android.h +182 -0
- data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
- data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
- data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
- data/dependencies/SDL/include/SDL_config_os2.h +188 -0
- data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
- data/dependencies/SDL/include/SDL_config_psp.h +165 -0
- data/dependencies/SDL/include/SDL_config_windows.h +288 -0
- data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
- data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
- data/dependencies/SDL/include/SDL_copying.h +20 -0
- data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
- data/dependencies/SDL/include/SDL_egl.h +1676 -0
- data/dependencies/SDL/include/SDL_endian.h +263 -0
- data/dependencies/SDL/include/SDL_error.h +112 -0
- data/dependencies/SDL/include/SDL_events.h +827 -0
- data/dependencies/SDL/include/SDL_filesystem.h +136 -0
- data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
- data/dependencies/SDL/include/SDL_gesture.h +87 -0
- data/dependencies/SDL/include/SDL_haptic.h +1247 -0
- data/dependencies/SDL/include/SDL_hints.h +1578 -0
- data/dependencies/SDL/include/SDL_joystick.h +499 -0
- data/dependencies/SDL/include/SDL_keyboard.h +217 -0
- data/dependencies/SDL/include/SDL_keycode.h +351 -0
- data/dependencies/SDL/include/SDL_loadso.h +81 -0
- data/dependencies/SDL/include/SDL_locale.h +101 -0
- data/dependencies/SDL/include/SDL_log.h +211 -0
- data/dependencies/SDL/include/SDL_main.h +180 -0
- data/dependencies/SDL/include/SDL_messagebox.h +146 -0
- data/dependencies/SDL/include/SDL_metal.h +117 -0
- data/dependencies/SDL/include/SDL_misc.h +75 -0
- data/dependencies/SDL/include/SDL_mouse.h +302 -0
- data/dependencies/SDL/include/SDL_mutex.h +251 -0
- data/dependencies/SDL/include/SDL_name.h +33 -0
- data/dependencies/SDL/include/SDL_opengl.h +2183 -0
- data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
- data/dependencies/SDL/include/SDL_opengles.h +39 -0
- data/dependencies/SDL/include/SDL_opengles2.h +52 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
- data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
- data/dependencies/SDL/include/SDL_pixels.h +479 -0
- data/dependencies/SDL/include/SDL_platform.h +198 -0
- data/dependencies/SDL/include/SDL_power.h +75 -0
- data/dependencies/SDL/include/SDL_quit.h +58 -0
- data/dependencies/SDL/include/SDL_rect.h +174 -0
- data/dependencies/SDL/include/SDL_render.h +1158 -0
- data/dependencies/SDL/include/SDL_revision.h +2 -0
- data/dependencies/SDL/include/SDL_rwops.h +283 -0
- data/dependencies/SDL/include/SDL_scancode.h +413 -0
- data/dependencies/SDL/include/SDL_sensor.h +267 -0
- data/dependencies/SDL/include/SDL_shape.h +144 -0
- data/dependencies/SDL/include/SDL_stdinc.h +647 -0
- data/dependencies/SDL/include/SDL_surface.h +563 -0
- data/dependencies/SDL/include/SDL_system.h +325 -0
- data/dependencies/SDL/include/SDL_syswm.h +354 -0
- data/dependencies/SDL/include/SDL_test.h +69 -0
- data/dependencies/SDL/include/SDL_test_assert.h +105 -0
- data/dependencies/SDL/include/SDL_test_common.h +218 -0
- data/dependencies/SDL/include/SDL_test_compare.h +69 -0
- data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
- data/dependencies/SDL/include/SDL_test_font.h +81 -0
- data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
- data/dependencies/SDL/include/SDL_test_harness.h +134 -0
- data/dependencies/SDL/include/SDL_test_images.h +78 -0
- data/dependencies/SDL/include/SDL_test_log.h +67 -0
- data/dependencies/SDL/include/SDL_test_md5.h +129 -0
- data/dependencies/SDL/include/SDL_test_memory.h +63 -0
- data/dependencies/SDL/include/SDL_test_random.h +115 -0
- data/dependencies/SDL/include/SDL_thread.h +366 -0
- data/dependencies/SDL/include/SDL_timer.h +115 -0
- data/dependencies/SDL/include/SDL_touch.h +102 -0
- data/dependencies/SDL/include/SDL_types.h +29 -0
- data/dependencies/SDL/include/SDL_version.h +162 -0
- data/dependencies/SDL/include/SDL_video.h +1282 -0
- data/dependencies/SDL/include/SDL_vulkan.h +276 -0
- data/dependencies/SDL/include/begin_code.h +166 -0
- data/dependencies/SDL/include/close_code.h +40 -0
- data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
- data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
- data/dependencies/SDL_sound/SDL_sound.c +795 -0
- data/dependencies/SDL_sound/SDL_sound.h +725 -0
- data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
- data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
- data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
- data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
- data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
- data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
- data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
- data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
- data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
- data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
- data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
- data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
- data/dependencies/SDL_sound/dr_flac.h +5906 -0
- data/dependencies/SDL_sound/dr_mp3.h +2832 -0
- data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
- data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
- data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
- data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
- data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
- data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
- data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
- data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
- data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
- data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
- data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
- data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
- data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
- data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
- data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
- data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
- data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
- data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
- data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
- data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
- data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
- data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
- data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
- data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
- data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
- data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
- data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
- data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
- data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
- data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
- data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
- data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
- data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
- data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
- data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
- data/dependencies/al_soft/AL/al.h +655 -0
- data/dependencies/al_soft/AL/alc.h +270 -0
- data/dependencies/al_soft/AL/alext.h +585 -0
- data/dependencies/al_soft/AL/efx-creative.h +3 -0
- data/dependencies/al_soft/AL/efx-presets.h +402 -0
- data/dependencies/al_soft/AL/efx.h +762 -0
- data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
- data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
- data/{src → dependencies/stb}/stb_image.h +330 -127
- data/{src → dependencies/stb}/stb_image_write.h +156 -85
- data/{src → dependencies/stb}/stb_truetype.h +192 -69
- data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
- data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
- data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
- data/ext/gosu/extconf.rb +53 -39
- data/{Gosu → include/Gosu}/Audio.hpp +6 -8
- data/include/Gosu/Bitmap.hpp +100 -0
- data/{Gosu → include/Gosu}/Buttons.hpp +104 -44
- data/{Gosu → include/Gosu}/Color.hpp +0 -0
- data/{Gosu → include/Gosu}/Directories.hpp +0 -0
- data/{Gosu → include/Gosu}/Font.hpp +1 -1
- data/{Gosu → include/Gosu}/Fwd.hpp +0 -5
- data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
- data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
- data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
- data/{Gosu → include/Gosu}/IO.hpp +0 -0
- data/{Gosu → include/Gosu}/Image.hpp +7 -6
- data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
- data/{Gosu → include/Gosu}/Input.hpp +39 -51
- data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
- data/{Gosu → include/Gosu}/Math.hpp +0 -0
- data/{Gosu → include/Gosu}/Platform.hpp +0 -0
- data/{Gosu → include/Gosu}/Text.hpp +0 -0
- data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
- data/{Gosu → include/Gosu}/Timing.hpp +0 -0
- data/{Gosu → include/Gosu}/Utility.hpp +15 -4
- data/{Gosu → include/Gosu}/Version.hpp +3 -3
- data/{Gosu → include/Gosu}/Window.hpp +46 -34
- data/lib/OpenAL32.dll +0 -0
- data/lib/SDL2.dll +0 -0
- data/lib/gosu.rb +0 -3
- data/lib/gosu/patches.rb +0 -23
- data/lib/gosu/preview.rb +1 -3
- data/lib/gosu/swig_patches.rb +6 -8
- data/lib64/OpenAL32.dll +0 -0
- data/lib64/SDL2.dll +0 -0
- data/rdoc/gosu.rb +112 -23
- data/src/Audio.cpp +50 -224
- data/src/AudioFile.hpp +20 -37
- data/src/AudioFileAudioToolbox.cpp +237 -0
- data/src/AudioFileSDLSound.cpp +147 -0
- data/src/AudioImpl.cpp +3 -12
- data/src/AudioImpl.hpp +3 -1
- data/src/Bitmap.cpp +85 -83
- data/src/BitmapIO.cpp +52 -58
- data/src/Font.cpp +4 -1
- data/src/Graphics.cpp +7 -4
- data/src/Image.cpp +13 -16
- data/src/Input.cpp +412 -164
- data/src/LargeImageData.cpp +2 -1
- data/src/MarkupParser.cpp +2 -1
- data/src/Resolution.cpp +8 -8
- data/src/RubyGosu.cxx +1184 -352
- data/src/RubyGosu.h +3 -2
- data/src/TexChunk.cpp +1 -1
- data/src/Text.cpp +1 -0
- data/src/TextBuilder.cpp +3 -1
- data/src/Texture.cpp +1 -1
- data/src/TrueTypeFont.cpp +2 -1
- data/src/TrueTypeFontWin.cpp +3 -3
- data/src/Utility.cpp +11 -7
- data/src/Window.cpp +90 -62
- data/src/WindowUIKit.cpp +21 -9
- metadata +195 -46
- data/Gosu/AutoLink.hpp +0 -14
- data/Gosu/Bitmap.hpp +0 -113
- data/lib/gosu/zen.rb +0 -89
- data/src/AudioToolboxFile.hpp +0 -210
- data/src/MPEGFile.hpp +0 -90
- data/src/OggFile.hpp +0 -92
- data/src/SndFile.hpp +0 -174
- 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
|
+
|