summaryrefslogtreecommitdiff
path: root/apps/codecs/libasap/asap.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libasap/asap.c')
-rw-r--r--apps/codecs/libasap/asap.c3716
1 files changed, 1858 insertions, 1858 deletions
diff --git a/apps/codecs/libasap/asap.c b/apps/codecs/libasap/asap.c
index 87b537ef63..c79682c38b 100644
--- a/apps/codecs/libasap/asap.c
+++ b/apps/codecs/libasap/asap.c
@@ -25,78 +25,78 @@
25 25
26FUNC(int, ASAP_GetByte, (P(ASAP_State PTR, ast), P(int, addr))) 26FUNC(int, ASAP_GetByte, (P(ASAP_State PTR, ast), P(int, addr)))
27{ 27{
28 switch (addr & 0xff0f) { 28 switch (addr & 0xff0f) {
29 case 0xd20a: 29 case 0xd20a:
30 return PokeySound_GetRandom(ast, addr, ast _ cycle); 30 return PokeySound_GetRandom(ast, addr, ast _ cycle);
31 case 0xd20e: 31 case 0xd20e:
32 if ((addr & ast _ extra_pokey_mask) != 0) { 32 if ((addr & ast _ extra_pokey_mask) != 0) {
33 /* interrupts in the extra POKEY not emulated at the moment */ 33 /* interrupts in the extra POKEY not emulated at the moment */
34 return 0xff; 34 return 0xff;
35 } 35 }
36 return ast _ irqst; 36 return ast _ irqst;
37 case 0xd20f: 37 case 0xd20f:
38 /* just because some SAP files rely on this */ 38 /* just because some SAP files rely on this */
39 return 0xff; 39 return 0xff;
40 case 0xd40b: 40 case 0xd40b:
41 return ast _ scanline_number >> 1; 41 return ast _ scanline_number >> 1;
42 default: 42 default:
43 return dGetByte(addr); 43 return dGetByte(addr);
44 } 44 }
45} 45}
46 46
47FUNC(void, ASAP_PutByte, (P(ASAP_State PTR, ast), P(int, addr), P(int, data))) 47FUNC(void, ASAP_PutByte, (P(ASAP_State PTR, ast), P(int, addr), P(int, data)))
48{ 48{
49 if ((addr >> 8) == 0xd2) { 49 if ((addr >> 8) == 0xd2) {
50 if ((addr & (ast _ extra_pokey_mask + 0xf)) == 0xe) { 50 if ((addr & (ast _ extra_pokey_mask + 0xf)) == 0xe) {
51 ast _ irqst |= data ^ 0xff; 51 ast _ irqst |= data ^ 0xff;
52#define SET_TIMER_IRQ(ch) \ 52#define SET_TIMER_IRQ(ch) \
53 if ((data & ast _ irqst & ch) != 0) { \ 53 if ((data & ast _ irqst & ch) != 0) { \
54 if (ast _ timer##ch##_cycle == NEVER) { \ 54 if (ast _ timer##ch##_cycle == NEVER) { \
55 V(int, t) = ast _ base_pokey.tick_cycle##ch; \ 55 V(int, t) = ast _ base_pokey.tick_cycle##ch; \
56 while (t < ast _ cycle) \ 56 while (t < ast _ cycle) \
57 t += ast _ base_pokey.period_cycles##ch; \ 57 t += ast _ base_pokey.period_cycles##ch; \
58 ast _ timer##ch##_cycle = t; \ 58 ast _ timer##ch##_cycle = t; \
59 if (ast _ nearest_event_cycle > t) \ 59 if (ast _ nearest_event_cycle > t) \
60 ast _ nearest_event_cycle = t; \ 60 ast _ nearest_event_cycle = t; \
61 } \ 61 } \
62 } \ 62 } \
63 else \ 63 else \
64 ast _ timer##ch##_cycle = NEVER; 64 ast _ timer##ch##_cycle = NEVER;
65 SET_TIMER_IRQ(1); 65 SET_TIMER_IRQ(1);
66 SET_TIMER_IRQ(2); 66 SET_TIMER_IRQ(2);
67 SET_TIMER_IRQ(4); 67 SET_TIMER_IRQ(4);
68 } 68 }
69 else 69 else
70 PokeySound_PutByte(ast, addr, data); 70 PokeySound_PutByte(ast, addr, data);
71 } 71 }
72 else if ((addr & 0xff0f) == 0xd40a) { 72 else if ((addr & 0xff0f) == 0xd40a) {
73 if (ast _ cycle <= ast _ next_scanline_cycle - 8) 73 if (ast _ cycle <= ast _ next_scanline_cycle - 8)
74 ast _ cycle = ast _ next_scanline_cycle - 8; 74 ast _ cycle = ast _ next_scanline_cycle - 8;
75 else 75 else
76 ast _ cycle = ast _ next_scanline_cycle + 106; 76 ast _ cycle = ast _ next_scanline_cycle + 106;
77 } 77 }
78 else if ((addr & 0xff00) == ast _ module_info.covox_addr) { 78 else if ((addr & 0xff00) == ast _ module_info.covox_addr) {
79 V(PokeyState PTR, pst); 79 V(PokeyState PTR, pst);
80 addr &= 3; 80 addr &= 3;
81 if (addr == 0 || addr == 3) 81 if (addr == 0 || addr == 3)
82 pst = ADDRESSOF ast _ base_pokey; 82 pst = ADDRESSOF ast _ base_pokey;
83 else 83 else
84 pst = ADDRESSOF ast _ extra_pokey; 84 pst = ADDRESSOF ast _ extra_pokey;
85 pst _ delta_buffer[CYCLE_TO_SAMPLE(ast _ cycle)] += (data - UBYTE(ast _ covox[addr])) << DELTA_SHIFT_COVOX; 85 pst _ delta_buffer[CYCLE_TO_SAMPLE(ast _ cycle)] += (data - UBYTE(ast _ covox[addr])) << DELTA_SHIFT_COVOX;
86 ast _ covox[addr] = CAST(byte) (data); 86 ast _ covox[addr] = CAST(byte) (data);
87 } 87 }
88 else if ((addr & 0xff1f) == 0xd01f) { 88 else if ((addr & 0xff1f) == 0xd01f) {
89 V(int, sample) = CYCLE_TO_SAMPLE(ast _ cycle); 89 V(int, sample) = CYCLE_TO_SAMPLE(ast _ cycle);
90 V(int, delta); 90 V(int, delta);
91 data &= 8; 91 data &= 8;
92 /* NOT data - ast _ consol; reverse to the POKEY sound */ 92 /* NOT data - ast _ consol; reverse to the POKEY sound */
93 delta = (ast _ consol - data) << DELTA_SHIFT_GTIA; 93 delta = (ast _ consol - data) << DELTA_SHIFT_GTIA;
94 ast _ consol = data; 94 ast _ consol = data;
95 ast _ base_pokey.delta_buffer[sample] += delta; 95 ast _ base_pokey.delta_buffer[sample] += delta;
96 ast _ extra_pokey.delta_buffer[sample] += delta; 96 ast _ extra_pokey.delta_buffer[sample] += delta;
97 } 97 }
98 else 98 else
99 dPutByte(addr, data); 99 dPutByte(addr, data);
100} 100}
101 101
102#define UWORD(array, index) (UBYTE(array[index]) + (UBYTE(array[(index) + 1]) << 8)) 102#define UWORD(array, index) (UBYTE(array[index]) + (UBYTE(array[(index) + 1]) << 8))
@@ -110,61 +110,61 @@ FUNC(void, ASAP_PutByte, (P(ASAP_State PTR, ast), P(int, addr), P(int, data)))
110#define CMR_BASS_TABLE_OFFSET 0x70f 110#define CMR_BASS_TABLE_OFFSET 0x70f
111 111
112CONST_ARRAY(byte, cmr_bass_table) 112CONST_ARRAY(byte, cmr_bass_table)
113 0x5C, 0x56, 0x50, 0x4D, 0x47, 0x44, 0x41, 0x3E, 113 0x5C, 0x56, 0x50, 0x4D, 0x47, 0x44, 0x41, 0x3E,
114 0x38, 0x35, CAST(byte) (0x88), 0x7F, 0x79, 0x73, 0x6C, 0x67, 114 0x38, 0x35, CAST(byte) (0x88), 0x7F, 0x79, 0x73, 0x6C, 0x67,
115 0x60, 0x5A, 0x55, 0x51, 0x4C, 0x48, 0x43, 0x3F, 115 0x60, 0x5A, 0x55, 0x51, 0x4C, 0x48, 0x43, 0x3F,
116 0x3D, 0x39, 0x34, 0x33, 0x30, 0x2D, 0x2A, 0x28, 116 0x3D, 0x39, 0x34, 0x33, 0x30, 0x2D, 0x2A, 0x28,
117 0x25, 0x24, 0x21, 0x1F, 0x1E 117 0x25, 0x24, 0x21, 0x1F, 0x1E
118END_CONST_ARRAY; 118END_CONST_ARRAY;
119 119
120CONST_ARRAY(int, perframe2fastplay) 120CONST_ARRAY(int, perframe2fastplay)
121 312, 312 / 2, 312 / 3, 312 / 4 121 312, 312 / 2, 312 / 3, 312 / 4
122END_CONST_ARRAY; 122END_CONST_ARRAY;
123 123
124/* Loads native module (anything except SAP) and 6502 player routine. */ 124/* Loads native module (anything except SAP) and 6502 player routine. */
125PRIVATE FUNC(abool, load_native, ( 125PRIVATE FUNC(abool, load_native, (
126 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 126 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
127 P(CONST BYTEARRAY, module), P(int, module_len), P(RESOURCE, player))) 127 P(CONST BYTEARRAY, module), P(int, module_len), P(RESOURCE, player)))
128{ 128{
129 V(int, player_last_byte); 129 V(int, player_last_byte);
130 V(int, music_last_byte); 130 V(int, music_last_byte);
131 V(int, block_len); 131 V(int, block_len);
132 if ((UBYTE(module[0]) != 0xff || UBYTE(module[1]) != 0xff) 132 if ((UBYTE(module[0]) != 0xff || UBYTE(module[1]) != 0xff)
133 && (module[0] != 0 || module[1] != 0)) /* some CMC and clones start with zeros */ 133 && (module[0] != 0 || module[1] != 0)) /* some CMC and clones start with zeros */
134 return FALSE; 134 return FALSE;
135 module_info _ player = UWORD(player, 2); 135 module_info _ player = UWORD(player, 2);
136 player_last_byte = UWORD(player, 4); 136 player_last_byte = UWORD(player, 4);
137 module_info _ music = UWORD(module, 2); 137 module_info _ music = UWORD(module, 2);
138 if (module_info _ music <= player_last_byte) 138 if (module_info _ music <= player_last_byte)
139 return FALSE; 139 return FALSE;
140 music_last_byte = UWORD(module, 4); 140 music_last_byte = UWORD(module, 4);
141 if (module_info _ music <= 0xd7ff && music_last_byte >= 0xd000) 141 if (module_info _ music <= 0xd7ff && music_last_byte >= 0xd000)
142 return FALSE; 142 return FALSE;
143 block_len = music_last_byte + 1 - module_info _ music; 143 block_len = music_last_byte + 1 - module_info _ music;
144 if (6 + block_len != module_len) { 144 if (6 + block_len != module_len) {
145 V(int, info_addr); 145 V(int, info_addr);
146 V(int, info_len); 146 V(int, info_len);
147 if (module_info _ type != ASAP_TYPE_RMT || 11 + block_len > module_len) 147 if (module_info _ type != ASAP_TYPE_RMT || 11 + block_len > module_len)
148 return FALSE; 148 return FALSE;
149 /* allow optional info for Raster Music Tracker */ 149 /* allow optional info for Raster Music Tracker */
150 info_addr = UWORD(module, 6 + block_len); 150 info_addr = UWORD(module, 6 + block_len);
151 if (info_addr != module_info _ music + block_len) 151 if (info_addr != module_info _ music + block_len)
152 return FALSE; 152 return FALSE;
153 info_len = UWORD(module, 8 + block_len) + 1 - info_addr; 153 info_len = UWORD(module, 8 + block_len) + 1 - info_addr;
154 if (10 + block_len + info_len != module_len) 154 if (10 + block_len + info_len != module_len)
155 return FALSE; 155 return FALSE;
156 } 156 }
157 if (ast != NULL) { 157 if (ast != NULL) {
158 COPY_ARRAY(ast _ memory, module_info _ music, module, 6, block_len); 158 COPY_ARRAY(ast _ memory, module_info _ music, module, 6, block_len);
159 COPY_ARRAY(ast _ memory, module_info _ player, player, 6, player_last_byte + 1 - module_info _ player); 159 COPY_ARRAY(ast _ memory, module_info _ player, player, 6, player_last_byte + 1 - module_info _ player);
160 } 160 }
161 return TRUE; 161 return TRUE;
162} 162}
163 163
164PRIVATE FUNC(void, set_song_duration, (P(ASAP_ModuleInfo PTR, module_info), P(int, player_calls))) 164PRIVATE FUNC(void, set_song_duration, (P(ASAP_ModuleInfo PTR, module_info), P(int, player_calls)))
165{ 165{
166 module_info _ durations[module_info _ songs] = TO_INT(player_calls * module_info _ fastplay * 114000.0 / 1773447); 166 module_info _ durations[module_info _ songs] = TO_INT(player_calls * module_info _ fastplay * 114000.0 / 1773447);
167 module_info _ songs++; 167 module_info _ songs++;
168} 168}
169 169
170#define SEEN_THIS_CALL 1 170#define SEEN_THIS_CALL 1
@@ -173,901 +173,901 @@ PRIVATE FUNC(void, set_song_duration, (P(ASAP_ModuleInfo PTR, module_info), P(in
173 173
174PRIVATE FUNC(void, parse_cmc_song, (P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, pos))) 174PRIVATE FUNC(void, parse_cmc_song, (P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, pos)))
175{ 175{
176 V(int, tempo) = UBYTE(module[0x19]); 176 V(int, tempo) = UBYTE(module[0x19]);
177 V(int, player_calls) = 0; 177 V(int, player_calls) = 0;
178 V(int, rep_start_pos) = 0; 178 V(int, rep_start_pos) = 0;
179 V(int, rep_end_pos) = 0; 179 V(int, rep_end_pos) = 0;
180 V(int, rep_times) = 0; 180 V(int, rep_times) = 0;
181 NEW_ARRAY(byte, seen, 0x55); 181 NEW_ARRAY(byte, seen, 0x55);
182 INIT_ARRAY(seen); 182 INIT_ARRAY(seen);
183 while (pos >= 0 && pos < 0x55) { 183 while (pos >= 0 && pos < 0x55) {
184 V(int, p1); 184 V(int, p1);
185 V(int, p2); 185 V(int, p2);
186 V(int, p3); 186 V(int, p3);
187 if (pos == rep_end_pos && rep_times > 0) { 187 if (pos == rep_end_pos && rep_times > 0) {
188 for (p1 = 0; p1 < 0x55; p1++) 188 for (p1 = 0; p1 < 0x55; p1++)
189 if (seen[p1] == SEEN_THIS_CALL || seen[p1] == SEEN_REPEAT) 189 if (seen[p1] == SEEN_THIS_CALL || seen[p1] == SEEN_REPEAT)
190 seen[p1] = 0; 190 seen[p1] = 0;
191 rep_times--; 191 rep_times--;
192 pos = rep_start_pos; 192 pos = rep_start_pos;
193 } 193 }
194 if (seen[pos] != 0) { 194 if (seen[pos] != 0) {
195 if (seen[pos] != SEEN_THIS_CALL) 195 if (seen[pos] != SEEN_THIS_CALL)
196 module_info _ loops[module_info _ songs] = TRUE; 196 module_info _ loops[module_info _ songs] = TRUE;
197 break; 197 break;
198 } 198 }
199 seen[pos] = SEEN_THIS_CALL; 199 seen[pos] = SEEN_THIS_CALL;
200 p1 = UBYTE(module[0x206 + pos]); 200 p1 = UBYTE(module[0x206 + pos]);
201 p2 = UBYTE(module[0x25b + pos]); 201 p2 = UBYTE(module[0x25b + pos]);
202 p3 = UBYTE(module[0x2b0 + pos]); 202 p3 = UBYTE(module[0x2b0 + pos]);
203 if (p1 == 0xfe || p2 == 0xfe || p3 == 0xfe) { 203 if (p1 == 0xfe || p2 == 0xfe || p3 == 0xfe) {
204 pos++; 204 pos++;
205 continue; 205 continue;
206 } 206 }
207 p1 >>= 4; 207 p1 >>= 4;
208 if (p1 == 8) 208 if (p1 == 8)
209 break; 209 break;
210 if (p1 == 9) { 210 if (p1 == 9) {
211 pos = p2; 211 pos = p2;
212 continue; 212 continue;
213 } 213 }
214 if (p1 == 0xa) { 214 if (p1 == 0xa) {
215 pos -= p2; 215 pos -= p2;
216 continue; 216 continue;
217 } 217 }
218 if (p1 == 0xb) { 218 if (p1 == 0xb) {
219 pos += p2; 219 pos += p2;
220 continue; 220 continue;
221 } 221 }
222 if (p1 == 0xc) { 222 if (p1 == 0xc) {
223 tempo = p2; 223 tempo = p2;
224 pos++; 224 pos++;
225 continue; 225 continue;
226 } 226 }
227 if (p1 == 0xd) { 227 if (p1 == 0xd) {
228 pos++; 228 pos++;
229 rep_start_pos = pos; 229 rep_start_pos = pos;
230 rep_end_pos = pos + p2; 230 rep_end_pos = pos + p2;
231 rep_times = p3 - 1; 231 rep_times = p3 - 1;
232 continue; 232 continue;
233 } 233 }
234 if (p1 == 0xe) { 234 if (p1 == 0xe) {
235 module_info _ loops[module_info _ songs] = TRUE; 235 module_info _ loops[module_info _ songs] = TRUE;
236 break; 236 break;
237 } 237 }
238 p2 = rep_times > 0 ? SEEN_REPEAT : SEEN_BEFORE; 238 p2 = rep_times > 0 ? SEEN_REPEAT : SEEN_BEFORE;
239 for (p1 = 0; p1 < 0x55; p1++) 239 for (p1 = 0; p1 < 0x55; p1++)
240 if (seen[p1] == SEEN_THIS_CALL) 240 if (seen[p1] == SEEN_THIS_CALL)
241 seen[p1] = CAST(byte) p2; 241 seen[p1] = CAST(byte) p2;
242 player_calls += tempo * (module_info _ type == ASAP_TYPE_CM3 ? 48 : 64); 242 player_calls += tempo * (module_info _ type == ASAP_TYPE_CM3 ? 48 : 64);
243 pos++; 243 pos++;
244 } 244 }
245 set_song_duration(module_info, player_calls); 245 set_song_duration(module_info, player_calls);
246} 246}
247 247
248PRIVATE FUNC(abool, parse_cmc, ( 248PRIVATE FUNC(abool, parse_cmc, (
249 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 249 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
250 P(CONST BYTEARRAY, module), P(int, module_len), P(int, type), P(RESOURCE, player))) 250 P(CONST BYTEARRAY, module), P(int, module_len), P(int, type), P(RESOURCE, player)))
251{ 251{
252 V(int, last_pos); 252 V(int, last_pos);
253 V(int, pos); 253 V(int, pos);
254 if (module_len < 0x306) 254 if (module_len < 0x306)
255 return FALSE; 255 return FALSE;
256 module_info _ type = type; 256 module_info _ type = type;
257 if (!load_native(ast, module_info, module, module_len, player)) 257 if (!load_native(ast, module_info, module, module_len, player))
258 return FALSE; 258 return FALSE;
259 if (ast != NULL && type == ASAP_TYPE_CMR) 259 if (ast != NULL && type == ASAP_TYPE_CMR)
260 COPY_ARRAY(ast _ memory, 0x500 + CMR_BASS_TABLE_OFFSET, cmr_bass_table, 0, sizeof(cmr_bass_table)); 260 COPY_ARRAY(ast _ memory, 0x500 + CMR_BASS_TABLE_OFFSET, cmr_bass_table, 0, sizeof(cmr_bass_table));
261 last_pos = 0x54; 261 last_pos = 0x54;
262 while (--last_pos >= 0) { 262 while (--last_pos >= 0) {
263 if (UBYTE(module[0x206 + last_pos]) < 0xb0 263 if (UBYTE(module[0x206 + last_pos]) < 0xb0
264 || UBYTE(module[0x25b + last_pos]) < 0x40 264 || UBYTE(module[0x25b + last_pos]) < 0x40
265 || UBYTE(module[0x2b0 + last_pos]) < 0x40) 265 || UBYTE(module[0x2b0 + last_pos]) < 0x40)
266 break; 266 break;
267 if (module_info _ channels == 2) { 267 if (module_info _ channels == 2) {
268 if (UBYTE(module[0x306 + last_pos]) < 0xb0 268 if (UBYTE(module[0x306 + last_pos]) < 0xb0
269 || UBYTE(module[0x35b + last_pos]) < 0x40 269 || UBYTE(module[0x35b + last_pos]) < 0x40
270 || UBYTE(module[0x3b0 + last_pos]) < 0x40) 270 || UBYTE(module[0x3b0 + last_pos]) < 0x40)
271 break; 271 break;
272 } 272 }
273 } 273 }
274 module_info _ songs = 0; 274 module_info _ songs = 0;
275 parse_cmc_song(module_info, module, 0); 275 parse_cmc_song(module_info, module, 0);
276 for (pos = 0; pos < last_pos && module_info _ songs < ASAP_SONGS_MAX; pos++) 276 for (pos = 0; pos < last_pos && module_info _ songs < ASAP_SONGS_MAX; pos++)
277 if (UBYTE(module[0x206 + pos]) == 0x8f || UBYTE(module[0x206 + pos]) == 0xef) 277 if (UBYTE(module[0x206 + pos]) == 0x8f || UBYTE(module[0x206 + pos]) == 0xef)
278 parse_cmc_song(module_info, module, pos + 1); 278 parse_cmc_song(module_info, module, pos + 1);
279 return TRUE; 279 return TRUE;
280} 280}
281 281
282PRIVATE FUNC(abool, is_dlt_track_empty, (P(CONST BYTEARRAY, module), P(int, pos))) 282PRIVATE FUNC(abool, is_dlt_track_empty, (P(CONST BYTEARRAY, module), P(int, pos)))
283{ 283{
284 return UBYTE(module[0x2006 + pos]) >= 0x43 284 return UBYTE(module[0x2006 + pos]) >= 0x43
285 && UBYTE(module[0x2106 + pos]) >= 0x40 285 && UBYTE(module[0x2106 + pos]) >= 0x40
286 && UBYTE(module[0x2206 + pos]) >= 0x40 286 && UBYTE(module[0x2206 + pos]) >= 0x40
287 && UBYTE(module[0x2306 + pos]) >= 0x40; 287 && UBYTE(module[0x2306 + pos]) >= 0x40;
288} 288}
289 289
290PRIVATE FUNC(abool, is_dlt_pattern_end, (P(CONST BYTEARRAY, module), P(int, pos), P(int, i))) 290PRIVATE FUNC(abool, is_dlt_pattern_end, (P(CONST BYTEARRAY, module), P(int, pos), P(int, i)))
291{ 291{
292 V(int, ch); 292 V(int, ch);
293 for (ch = 0; ch < 4; ch++) { 293 for (ch = 0; ch < 4; ch++) {
294 V(int, pattern) = UBYTE(module[0x2006 + (ch << 8) + pos]); 294 V(int, pattern) = UBYTE(module[0x2006 + (ch << 8) + pos]);
295 if (pattern < 64) { 295 if (pattern < 64) {
296 V(int, offset) = 6 + (pattern << 7) + (i << 1); 296 V(int, offset) = 6 + (pattern << 7) + (i << 1);
297 if ((module[offset] & 0x80) == 0 && (module[offset + 1] & 0x80) != 0) 297 if ((module[offset] & 0x80) == 0 && (module[offset + 1] & 0x80) != 0)
298 return TRUE; 298 return TRUE;
299 } 299 }
300 } 300 }
301 return FALSE; 301 return FALSE;
302} 302}
303 303
304PRIVATE FUNC(void, parse_dlt_song, ( 304PRIVATE FUNC(void, parse_dlt_song, (
305 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), 305 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module),
306 P(BOOLARRAY, seen), P(int, pos))) 306 P(BOOLARRAY, seen), P(int, pos)))
307{ 307{
308 V(int, player_calls) = 0; 308 V(int, player_calls) = 0;
309 V(abool, loop) = FALSE; 309 V(abool, loop) = FALSE;
310 V(int, tempo) = 6; 310 V(int, tempo) = 6;
311 while (pos < 128 && !seen[pos] && is_dlt_track_empty(module, pos)) 311 while (pos < 128 && !seen[pos] && is_dlt_track_empty(module, pos))
312 seen[pos++] = TRUE; 312 seen[pos++] = TRUE;
313 module_info _ song_pos[module_info _ songs] = CAST(byte) pos; 313 module_info _ song_pos[module_info _ songs] = CAST(byte) pos;
314 while (pos < 128) { 314 while (pos < 128) {
315 V(int, p1); 315 V(int, p1);
316 if (seen[pos]) { 316 if (seen[pos]) {
317 loop = TRUE; 317 loop = TRUE;
318 break; 318 break;
319 } 319 }
320 seen[pos] = TRUE; 320 seen[pos] = TRUE;
321 p1 = module[0x2006 + pos]; 321 p1 = module[0x2006 + pos];
322 if (p1 == 0x40 || is_dlt_track_empty(module, pos)) 322 if (p1 == 0x40 || is_dlt_track_empty(module, pos))
323 break; 323 break;
324 if (p1 == 0x41) 324 if (p1 == 0x41)
325 pos = UBYTE(module[0x2086 + pos]); 325 pos = UBYTE(module[0x2086 + pos]);
326 else if (p1 == 0x42) 326 else if (p1 == 0x42)
327 tempo = UBYTE(module[0x2086 + pos++]); 327 tempo = UBYTE(module[0x2086 + pos++]);
328 else { 328 else {
329 V(int, i); 329 V(int, i);
330 for (i = 0; i < 64 && !is_dlt_pattern_end(module, pos, i); i++) 330 for (i = 0; i < 64 && !is_dlt_pattern_end(module, pos, i); i++)
331 player_calls += tempo; 331 player_calls += tempo;
332 pos++; 332 pos++;
333 } 333 }
334 } 334 }
335 if (player_calls > 0) { 335 if (player_calls > 0) {
336 module_info _ loops[module_info _ songs] = loop; 336 module_info _ loops[module_info _ songs] = loop;
337 set_song_duration(module_info, player_calls); 337 set_song_duration(module_info, player_calls);
338 } 338 }
339} 339}
340 340
341PRIVATE FUNC(abool, parse_dlt, ( 341PRIVATE FUNC(abool, parse_dlt, (
342 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 342 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
343 P(CONST BYTEARRAY, module), P(int, module_len))) 343 P(CONST BYTEARRAY, module), P(int, module_len)))
344{ 344{
345 V(int, pos); 345 V(int, pos);
346 NEW_ARRAY(abool, seen, 128); 346 NEW_ARRAY(abool, seen, 128);
347 if (module_len == 0x2c06) { 347 if (module_len == 0x2c06) {
348 if (ast != NULL) 348 if (ast != NULL)
349 ast _ memory[0x4c00] = 0; 349 ast _ memory[0x4c00] = 0;
350 } 350 }
351 else if (module_len != 0x2c07) 351 else if (module_len != 0x2c07)
352 return FALSE; 352 return FALSE;
353 module_info _ type = ASAP_TYPE_DLT; 353 module_info _ type = ASAP_TYPE_DLT;
354 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(dlt, obx)) 354 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(dlt, obx))
355 || module_info _ music != 0x2000) { 355 || module_info _ music != 0x2000) {
356 return FALSE; 356 return FALSE;
357 } 357 }
358 INIT_ARRAY(seen); 358 INIT_ARRAY(seen);
359 module_info _ songs = 0; 359 module_info _ songs = 0;
360 for (pos = 0; pos < 128 && module_info _ songs < ASAP_SONGS_MAX; pos++) { 360 for (pos = 0; pos < 128 && module_info _ songs < ASAP_SONGS_MAX; pos++) {
361 if (!seen[pos]) 361 if (!seen[pos])
362 parse_dlt_song(module_info, module, seen, pos); 362 parse_dlt_song(module_info, module, seen, pos);
363 } 363 }
364 return module_info _ songs > 0; 364 return module_info _ songs > 0;
365} 365}
366 366
367PRIVATE FUNC(void, parse_mpt_song, ( 367PRIVATE FUNC(void, parse_mpt_song, (
368 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), 368 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module),
369 P(BOOLARRAY, global_seen), P(int, song_len), P(int, pos))) 369 P(BOOLARRAY, global_seen), P(int, song_len), P(int, pos)))
370{ 370{
371 V(int, addr_to_offset) = UWORD(module, 2) - 6; 371 V(int, addr_to_offset) = UWORD(module, 2) - 6;
372 V(int, tempo) = UBYTE(module[0x1cf]); 372 V(int, tempo) = UBYTE(module[0x1cf]);
373 V(int, player_calls) = 0; 373 V(int, player_calls) = 0;
374 NEW_ARRAY(byte, seen, 256); 374 NEW_ARRAY(byte, seen, 256);
375 NEW_ARRAY(int, pattern_offset, 4); 375 NEW_ARRAY(int, pattern_offset, 4);
376 NEW_ARRAY(int, blank_rows, 4); 376 NEW_ARRAY(int, blank_rows, 4);
377 NEW_ARRAY(int, blank_rows_counter, 4); 377 NEW_ARRAY(int, blank_rows_counter, 4);
378 INIT_ARRAY(seen); 378 INIT_ARRAY(seen);
379 INIT_ARRAY(blank_rows); 379 INIT_ARRAY(blank_rows);
380 while (pos < song_len) { 380 while (pos < song_len) {
381 V(int, i); 381 V(int, i);
382 V(int, ch); 382 V(int, ch);
383 V(int, pattern_rows); 383 V(int, pattern_rows);
384 if (seen[pos] != 0) { 384 if (seen[pos] != 0) {
385 if (seen[pos] != SEEN_THIS_CALL) 385 if (seen[pos] != SEEN_THIS_CALL)
386 module_info _ loops[module_info _ songs] = TRUE; 386 module_info _ loops[module_info _ songs] = TRUE;
387 break; 387 break;
388 } 388 }
389 seen[pos] = SEEN_THIS_CALL; 389 seen[pos] = SEEN_THIS_CALL;
390 global_seen[pos] = TRUE; 390 global_seen[pos] = TRUE;
391 i = UBYTE(module[0x1d0 + pos * 2]); 391 i = UBYTE(module[0x1d0 + pos * 2]);
392 if (i == 0xff) { 392 if (i == 0xff) {
393 pos = UBYTE(module[0x1d1 + pos * 2]); 393 pos = UBYTE(module[0x1d1 + pos * 2]);
394 continue; 394 continue;
395 } 395 }
396 for (ch = 3; ch >= 0; ch--) { 396 for (ch = 3; ch >= 0; ch--) {
397 i = UBYTE(module[0x1c6 + ch]) + (UBYTE(module[0x1ca + ch]) << 8) - addr_to_offset; 397 i = UBYTE(module[0x1c6 + ch]) + (UBYTE(module[0x1ca + ch]) << 8) - addr_to_offset;
398 i = UBYTE(module[i + pos * 2]); 398 i = UBYTE(module[i + pos * 2]);
399 if (i >= 0x40) 399 if (i >= 0x40)
400 break; 400 break;
401 i <<= 1; 401 i <<= 1;
402 i = UWORD(module, 0x46 + i); 402 i = UWORD(module, 0x46 + i);
403 pattern_offset[ch] = i == 0 ? 0 : i - addr_to_offset; 403 pattern_offset[ch] = i == 0 ? 0 : i - addr_to_offset;
404 blank_rows_counter[ch] = 0; 404 blank_rows_counter[ch] = 0;
405 } 405 }
406 if (ch >= 0) 406 if (ch >= 0)
407 break; 407 break;
408 for (i = 0; i < song_len; i++) 408 for (i = 0; i < song_len; i++)
409 if (seen[i] == SEEN_THIS_CALL) 409 if (seen[i] == SEEN_THIS_CALL)
410 seen[i] = SEEN_BEFORE; 410 seen[i] = SEEN_BEFORE;
411 for (pattern_rows = UBYTE(module[0x1ce]); --pattern_rows >= 0; ) { 411 for (pattern_rows = UBYTE(module[0x1ce]); --pattern_rows >= 0; ) {
412 for (ch = 3; ch >= 0; ch--) { 412 for (ch = 3; ch >= 0; ch--) {
413 if (pattern_offset[ch] == 0 || --blank_rows_counter[ch] >= 0) 413 if (pattern_offset[ch] == 0 || --blank_rows_counter[ch] >= 0)
414 continue; 414 continue;
415 for (;;) { 415 for (;;) {
416 i = UBYTE(module[pattern_offset[ch]++]); 416 i = UBYTE(module[pattern_offset[ch]++]);
417 if (i < 0x40 || i == 0xfe) 417 if (i < 0x40 || i == 0xfe)
418 break; 418 break;
419 if (i < 0x80) 419 if (i < 0x80)
420 continue; 420 continue;
421 if (i < 0xc0) { 421 if (i < 0xc0) {
422 blank_rows[ch] = i - 0x80; 422 blank_rows[ch] = i - 0x80;
423 continue; 423 continue;
424 } 424 }
425 if (i < 0xd0) 425 if (i < 0xd0)
426 continue; 426 continue;
427 if (i < 0xe0) { 427 if (i < 0xe0) {
428 tempo = i - 0xcf; 428 tempo = i - 0xcf;
429 continue; 429 continue;
430 } 430 }
431 pattern_rows = 0; 431 pattern_rows = 0;
432 } 432 }
433 blank_rows_counter[ch] = blank_rows[ch]; 433 blank_rows_counter[ch] = blank_rows[ch];
434 } 434 }
435 player_calls += tempo; 435 player_calls += tempo;
436 } 436 }
437 pos++; 437 pos++;
438 } 438 }
439 if (player_calls > 0) 439 if (player_calls > 0)
440 set_song_duration(module_info, player_calls); 440 set_song_duration(module_info, player_calls);
441} 441}
442 442
443PRIVATE FUNC(abool, parse_mpt, ( 443PRIVATE FUNC(abool, parse_mpt, (
444 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 444 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
445 P(CONST BYTEARRAY, module), P(int, module_len))) 445 P(CONST BYTEARRAY, module), P(int, module_len)))
446{ 446{
447 V(int, track0_addr); 447 V(int, track0_addr);
448 V(int, pos); 448 V(int, pos);
449 V(int, song_len); 449 V(int, song_len);
450 /* seen[i] == TRUE if the track position i has been processed */ 450 /* seen[i] == TRUE if the track position i has been processed */
451 NEW_ARRAY(abool, global_seen, 256); 451 NEW_ARRAY(abool, global_seen, 256);
452 if (module_len < 0x1d0) 452 if (module_len < 0x1d0)
453 return FALSE; 453 return FALSE;
454 module_info _ type = ASAP_TYPE_MPT; 454 module_info _ type = ASAP_TYPE_MPT;
455 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(mpt, obx))) 455 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(mpt, obx)))
456 return FALSE; 456 return FALSE;
457 track0_addr = UWORD(module, 2) + 0x1ca; 457 track0_addr = UWORD(module, 2) + 0x1ca;
458 if (UBYTE(module[0x1c6]) + (UBYTE(module[0x1ca]) << 8) != track0_addr) 458 if (UBYTE(module[0x1c6]) + (UBYTE(module[0x1ca]) << 8) != track0_addr)
459 return FALSE; 459 return FALSE;
460 /* Calculate the length of the first track. Address of the second track minus 460 /* Calculate the length of the first track. Address of the second track minus
461 address of the first track equals the length of the first track in bytes. 461 address of the first track equals the length of the first track in bytes.
462 Divide by two to get number of track positions. */ 462 Divide by two to get number of track positions. */
463 song_len = (UBYTE(module[0x1c7]) + (UBYTE(module[0x1cb]) << 8) - track0_addr) >> 1; 463 song_len = (UBYTE(module[0x1c7]) + (UBYTE(module[0x1cb]) << 8) - track0_addr) >> 1;
464 if (song_len > 0xfe) 464 if (song_len > 0xfe)
465 return FALSE; 465 return FALSE;
466 INIT_ARRAY(global_seen); 466 INIT_ARRAY(global_seen);
467 module_info _ songs = 0; 467 module_info _ songs = 0;
468 for (pos = 0; pos < song_len && module_info _ songs < ASAP_SONGS_MAX; pos++) { 468 for (pos = 0; pos < song_len && module_info _ songs < ASAP_SONGS_MAX; pos++) {
469 if (!global_seen[pos]) { 469 if (!global_seen[pos]) {
470 module_info _ song_pos[module_info _ songs] = CAST(byte) pos; 470 module_info _ song_pos[module_info _ songs] = CAST(byte) pos;
471 parse_mpt_song(module_info, module, global_seen, song_len, pos); 471 parse_mpt_song(module_info, module, global_seen, song_len, pos);
472 } 472 }
473 } 473 }
474 return module_info _ songs > 0; 474 return module_info _ songs > 0;
475} 475}
476 476
477CONST_ARRAY(byte, rmt_volume_silent) 477CONST_ARRAY(byte, rmt_volume_silent)
478 16, 8, 4, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 478 16, 8, 4, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1
479END_CONST_ARRAY; 479END_CONST_ARRAY;
480 480
481PRIVATE FUNC(int, rmt_instrument_frames, ( 481PRIVATE FUNC(int, rmt_instrument_frames, (
482 P(CONST BYTEARRAY, module), P(int, instrument), 482 P(CONST BYTEARRAY, module), P(int, instrument),
483 P(int, volume), P(int, volume_frame), P(abool, extra_pokey))) 483 P(int, volume), P(int, volume_frame), P(abool, extra_pokey)))
484{ 484{
485 V(int, addr_to_offset) = UWORD(module, 2) - 6; 485 V(int, addr_to_offset) = UWORD(module, 2) - 6;
486 V(int, per_frame) = module[0xc]; 486 V(int, per_frame) = module[0xc];
487 V(int, player_call); 487 V(int, player_call);
488 V(int, player_calls); 488 V(int, player_calls);
489 V(int, index); 489 V(int, index);
490 V(int, index_end); 490 V(int, index_end);
491 V(int, index_loop); 491 V(int, index_loop);
492 V(int, volume_slide_depth); 492 V(int, volume_slide_depth);
493 V(int, volume_min); 493 V(int, volume_min);
494 V(int, volume_slide); 494 V(int, volume_slide);
495 V(abool, silent_loop); 495 V(abool, silent_loop);
496 instrument = UWORD(module, 0xe) - addr_to_offset + (instrument << 1); 496 instrument = UWORD(module, 0xe) - addr_to_offset + (instrument << 1);
497 if (module[instrument + 1] == 0) 497 if (module[instrument + 1] == 0)
498 return 0; 498 return 0;
499 instrument = UWORD(module, instrument) - addr_to_offset; 499 instrument = UWORD(module, instrument) - addr_to_offset;
500 player_calls = player_call = volume_frame * per_frame; 500 player_calls = player_call = volume_frame * per_frame;
501 index = UBYTE(module[instrument]) + 1 + player_call * 3; 501 index = UBYTE(module[instrument]) + 1 + player_call * 3;
502 index_end = UBYTE(module[instrument + 2]) + 3; 502 index_end = UBYTE(module[instrument + 2]) + 3;
503 index_loop = UBYTE(module[instrument + 3]); 503 index_loop = UBYTE(module[instrument + 3]);
504 if (index_loop >= index_end) 504 if (index_loop >= index_end)
505 return 0; /* error */ 505 return 0; /* error */
506 volume_slide_depth = UBYTE(module[instrument + 6]); 506 volume_slide_depth = UBYTE(module[instrument + 6]);
507 volume_min = UBYTE(module[instrument + 7]); 507 volume_min = UBYTE(module[instrument + 7]);
508 if (index >= index_end) 508 if (index >= index_end)
509 index = (index - index_end) % (index_end - index_loop) + index_loop; 509 index = (index - index_end) % (index_end - index_loop) + index_loop;
510 else { 510 else {
511 do { 511 do {
512 V(int, vol) = module[instrument + index]; 512 V(int, vol) = module[instrument + index];
513 if (extra_pokey) 513 if (extra_pokey)
514 vol >>= 4; 514 vol >>= 4;
515 if ((vol & 0xf) >= rmt_volume_silent[volume]) 515 if ((vol & 0xf) >= rmt_volume_silent[volume])
516 player_calls = player_call + 1; 516 player_calls = player_call + 1;
517 player_call++; 517 player_call++;
518 index += 3; 518 index += 3;
519 } while (index < index_end); 519 } while (index < index_end);
520 } 520 }
521 if (volume_slide_depth == 0) 521 if (volume_slide_depth == 0)
522 return player_calls / per_frame; 522 return player_calls / per_frame;
523 volume_slide = 128; 523 volume_slide = 128;
524 silent_loop = FALSE; 524 silent_loop = FALSE;
525 for (;;) { 525 for (;;) {
526 V(int, vol); 526 V(int, vol);
527 if (index >= index_end) { 527 if (index >= index_end) {
528 if (silent_loop) 528 if (silent_loop)
529 break; 529 break;
530 silent_loop = TRUE; 530 silent_loop = TRUE;
531 index = index_loop; 531 index = index_loop;
532 } 532 }
533 vol = module[instrument + index]; 533 vol = module[instrument + index];
534 if (extra_pokey) 534 if (extra_pokey)
535 vol >>= 4; 535 vol >>= 4;
536 if ((vol & 0xf) >= rmt_volume_silent[volume]) { 536 if ((vol & 0xf) >= rmt_volume_silent[volume]) {
537 player_calls = player_call + 1; 537 player_calls = player_call + 1;
538 silent_loop = FALSE; 538 silent_loop = FALSE;
539 } 539 }
540 player_call++; 540 player_call++;
541 index += 3; 541 index += 3;
542 volume_slide -= volume_slide_depth; 542 volume_slide -= volume_slide_depth;
543 if (volume_slide < 0) { 543 if (volume_slide < 0) {
544 volume_slide += 256; 544 volume_slide += 256;
545 if (--volume <= volume_min) 545 if (--volume <= volume_min)
546 break; 546 break;
547 } 547 }
548 } 548 }
549 return player_calls / per_frame; 549 return player_calls / per_frame;
550} 550}
551 551
552PRIVATE FUNC(void, parse_rmt_song, ( 552PRIVATE FUNC(void, parse_rmt_song, (
553 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), 553 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module),
554 P(BOOLARRAY, global_seen), P(int, song_len), P(int, pos_shift), P(int, pos))) 554 P(BOOLARRAY, global_seen), P(int, song_len), P(int, pos_shift), P(int, pos)))
555{ 555{
556 V(int, ch); 556 V(int, ch);
557 V(int, addr_to_offset) = UWORD(module, 2) - 6; 557 V(int, addr_to_offset) = UWORD(module, 2) - 6;
558 V(int, tempo) = UBYTE(module[0xb]); 558 V(int, tempo) = UBYTE(module[0xb]);
559 V(int, frames) = 0; 559 V(int, frames) = 0;
560 V(int, song_offset) = UWORD(module, 0x14) - addr_to_offset; 560 V(int, song_offset) = UWORD(module, 0x14) - addr_to_offset;
561 V(int, pattern_lo_offset) = UWORD(module, 0x10) - addr_to_offset; 561 V(int, pattern_lo_offset) = UWORD(module, 0x10) - addr_to_offset;
562 V(int, pattern_hi_offset) = UWORD(module, 0x12) - addr_to_offset; 562 V(int, pattern_hi_offset) = UWORD(module, 0x12) - addr_to_offset;
563 V(int, instrument_frames); 563 V(int, instrument_frames);
564 NEW_ARRAY(byte, seen, 256); 564 NEW_ARRAY(byte, seen, 256);
565 NEW_ARRAY(int, pattern_begin, 8); 565 NEW_ARRAY(int, pattern_begin, 8);
566 NEW_ARRAY(int, pattern_offset, 8); 566 NEW_ARRAY(int, pattern_offset, 8);
567 NEW_ARRAY(int, blank_rows, 8); 567 NEW_ARRAY(int, blank_rows, 8);
568 NEW_ARRAY(int, instrument_no, 8); 568 NEW_ARRAY(int, instrument_no, 8);
569 NEW_ARRAY(int, instrument_frame, 8); 569 NEW_ARRAY(int, instrument_frame, 8);
570 NEW_ARRAY(int, volume_value, 8); 570 NEW_ARRAY(int, volume_value, 8);
571 NEW_ARRAY(int, volume_frame, 8); 571 NEW_ARRAY(int, volume_frame, 8);
572 INIT_ARRAY(seen); 572 INIT_ARRAY(seen);
573 INIT_ARRAY(instrument_no); 573 INIT_ARRAY(instrument_no);
574 INIT_ARRAY(instrument_frame); 574 INIT_ARRAY(instrument_frame);
575 INIT_ARRAY(volume_value); 575 INIT_ARRAY(volume_value);
576 INIT_ARRAY(volume_frame); 576 INIT_ARRAY(volume_frame);
577 while (pos < song_len) { 577 while (pos < song_len) {
578 V(int, i); 578 V(int, i);
579 V(int, pattern_rows); 579 V(int, pattern_rows);
580 if (seen[pos] != 0) { 580 if (seen[pos] != 0) {
581 if (seen[pos] != SEEN_THIS_CALL) 581 if (seen[pos] != SEEN_THIS_CALL)
582 module_info _ loops[module_info _ songs] = TRUE; 582 module_info _ loops[module_info _ songs] = TRUE;
583 break; 583 break;
584 } 584 }
585 seen[pos] = SEEN_THIS_CALL; 585 seen[pos] = SEEN_THIS_CALL;
586 global_seen[pos] = TRUE; 586 global_seen[pos] = TRUE;
587 if (UBYTE(module[song_offset + (pos << pos_shift)]) == 0xfe) { 587 if (UBYTE(module[song_offset + (pos << pos_shift)]) == 0xfe) {
588 pos = UBYTE(module[song_offset + (pos << pos_shift) + 1]); 588 pos = UBYTE(module[song_offset + (pos << pos_shift) + 1]);
589 continue; 589 continue;
590 } 590 }
591 for (ch = 0; ch < 1 << pos_shift; ch++) { 591 for (ch = 0; ch < 1 << pos_shift; ch++) {
592 i = UBYTE(module[song_offset + (pos << pos_shift) + ch]); 592 i = UBYTE(module[song_offset + (pos << pos_shift) + ch]);
593 if (i == 0xff) 593 if (i == 0xff)
594 blank_rows[ch] = 256; 594 blank_rows[ch] = 256;
595 else { 595 else {
596 pattern_offset[ch] = pattern_begin[ch] = UBYTE(module[pattern_lo_offset + i]) 596 pattern_offset[ch] = pattern_begin[ch] = UBYTE(module[pattern_lo_offset + i])
597 + (UBYTE(module[pattern_hi_offset + i]) << 8) - addr_to_offset; 597 + (UBYTE(module[pattern_hi_offset + i]) << 8) - addr_to_offset;
598 blank_rows[ch] = 0; 598 blank_rows[ch] = 0;
599 } 599 }
600 } 600 }
601 for (i = 0; i < song_len; i++) 601 for (i = 0; i < song_len; i++)
602 if (seen[i] == SEEN_THIS_CALL) 602 if (seen[i] == SEEN_THIS_CALL)
603 seen[i] = SEEN_BEFORE; 603 seen[i] = SEEN_BEFORE;
604 for (pattern_rows = UBYTE(module[0xa]); --pattern_rows >= 0; ) { 604 for (pattern_rows = UBYTE(module[0xa]); --pattern_rows >= 0; ) {
605 for (ch = 0; ch < 1 << pos_shift; ch++) { 605 for (ch = 0; ch < 1 << pos_shift; ch++) {
606 if (--blank_rows[ch] > 0) 606 if (--blank_rows[ch] > 0)
607 continue; 607 continue;
608 for (;;) { 608 for (;;) {
609 i = UBYTE(module[pattern_offset[ch]++]); 609 i = UBYTE(module[pattern_offset[ch]++]);
610 if ((i & 0x3f) < 62) { 610 if ((i & 0x3f) < 62) {
611 i += UBYTE(module[pattern_offset[ch]++]) << 8; 611 i += UBYTE(module[pattern_offset[ch]++]) << 8;
612 if ((i & 0x3f) != 61) { 612 if ((i & 0x3f) != 61) {
613 instrument_no[ch] = i >> 10; 613 instrument_no[ch] = i >> 10;
614 instrument_frame[ch] = frames; 614 instrument_frame[ch] = frames;
615 } 615 }
616 volume_value[ch] = (i >> 6) & 0xf; 616 volume_value[ch] = (i >> 6) & 0xf;
617 volume_frame[ch] = frames; 617 volume_frame[ch] = frames;
618 break; 618 break;
619 } 619 }
620 if (i == 62) { 620 if (i == 62) {
621 blank_rows[ch] = UBYTE(module[pattern_offset[ch]++]); 621 blank_rows[ch] = UBYTE(module[pattern_offset[ch]++]);
622 break; 622 break;
623 } 623 }
624 if ((i & 0x3f) == 62) { 624 if ((i & 0x3f) == 62) {
625 blank_rows[ch] = i >> 6; 625 blank_rows[ch] = i >> 6;
626 break; 626 break;
627 } 627 }
628 if ((i & 0xbf) == 63) { 628 if ((i & 0xbf) == 63) {
629 tempo = UBYTE(module[pattern_offset[ch]++]); 629 tempo = UBYTE(module[pattern_offset[ch]++]);
630 continue; 630 continue;
631 } 631 }
632 if (i == 0xbf) { 632 if (i == 0xbf) {
633 pattern_offset[ch] = pattern_begin[ch] + UBYTE(module[pattern_offset[ch]]); 633 pattern_offset[ch] = pattern_begin[ch] + UBYTE(module[pattern_offset[ch]]);
634 continue; 634 continue;
635 } 635 }
636 /* assert(i == 0xff); */ 636 /* assert(i == 0xff); */
637 pattern_rows = -1; 637 pattern_rows = -1;
638 break; 638 break;
639 } 639 }
640 if (pattern_rows < 0) 640 if (pattern_rows < 0)
641 break; 641 break;
642 } 642 }
643 if (pattern_rows >= 0) 643 if (pattern_rows >= 0)
644 frames += tempo; 644 frames += tempo;
645 } 645 }
646 pos++; 646 pos++;
647 } 647 }
648 instrument_frames = 0; 648 instrument_frames = 0;
649 for (ch = 0; ch < 1 << pos_shift; ch++) { 649 for (ch = 0; ch < 1 << pos_shift; ch++) {
650 V(int, frame) = instrument_frame[ch]; 650 V(int, frame) = instrument_frame[ch];
651 frame += rmt_instrument_frames(module, instrument_no[ch], volume_value[ch], volume_frame[ch] - frame, ch >= 4); 651 frame += rmt_instrument_frames(module, instrument_no[ch], volume_value[ch], volume_frame[ch] - frame, ch >= 4);
652 if (instrument_frames < frame) 652 if (instrument_frames < frame)
653 instrument_frames = frame; 653 instrument_frames = frame;
654 } 654 }
655 if (frames > instrument_frames) { 655 if (frames > instrument_frames) {
656 if (frames - instrument_frames > 100) 656 if (frames - instrument_frames > 100)
657 module_info _ loops[module_info _ songs] = FALSE; 657 module_info _ loops[module_info _ songs] = FALSE;
658 frames = instrument_frames; 658 frames = instrument_frames;
659 } 659 }
660 if (frames > 0) 660 if (frames > 0)
661 set_song_duration(module_info, frames); 661 set_song_duration(module_info, frames);
662} 662}
663 663
664PRIVATE FUNC(abool, parse_rmt, ( 664PRIVATE FUNC(abool, parse_rmt, (
665 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 665 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
666 P(CONST BYTEARRAY, module), P(int, module_len))) 666 P(CONST BYTEARRAY, module), P(int, module_len)))
667{ 667{
668 V(int, per_frame); 668 V(int, per_frame);
669 V(int, pos_shift); 669 V(int, pos_shift);
670 V(int, song_len); 670 V(int, song_len);
671 V(int, pos); 671 V(int, pos);
672 NEW_ARRAY(abool, global_seen, 256); 672 NEW_ARRAY(abool, global_seen, 256);
673 if (module_len < 0x30 || module[6] != CHARCODE('R') || module[7] != CHARCODE('M') 673 if (module_len < 0x30 || module[6] != CHARCODE('R') || module[7] != CHARCODE('M')
674 || module[8] != CHARCODE('T') || module[0xd] != 1) 674 || module[8] != CHARCODE('T') || module[0xd] != 1)
675 return FALSE; 675 return FALSE;
676 switch (CAST(char) module[9]) { 676 switch (CAST(char) module[9]) {
677 case CHARCODE('4'): 677 case CHARCODE('4'):
678 pos_shift = 2; 678 pos_shift = 2;
679 break; 679 break;
680 case CHARCODE('8'): 680 case CHARCODE('8'):
681 module_info _ channels = 2; 681 module_info _ channels = 2;
682 pos_shift = 3; 682 pos_shift = 3;
683 break; 683 break;
684 default: 684 default:
685 return FALSE; 685 return FALSE;
686 } 686 }
687 per_frame = module[0xc]; 687 per_frame = module[0xc];
688 if (per_frame < 1 || per_frame > 4) 688 if (per_frame < 1 || per_frame > 4)
689 return FALSE; 689 return FALSE;
690 module_info _ type = ASAP_TYPE_RMT; 690 module_info _ type = ASAP_TYPE_RMT;
691 if (!load_native(ast, module_info, module, module_len, 691 if (!load_native(ast, module_info, module, module_len,
692 module_info _ channels == 2 ? GET_RESOURCE(rmt8, obx) : GET_RESOURCE(rmt4, obx))) 692 module_info _ channels == 2 ? GET_RESOURCE(rmt8, obx) : GET_RESOURCE(rmt4, obx)))
693 return FALSE; 693 return FALSE;
694 song_len = UWORD(module, 4) + 1 - UWORD(module, 0x14); 694 song_len = UWORD(module, 4) + 1 - UWORD(module, 0x14);
695 if (pos_shift == 3 && (song_len & 4) != 0 695 if (pos_shift == 3 && (song_len & 4) != 0
696 && UBYTE(module[6 + UWORD(module, 4) - UWORD(module, 2) - 3]) == 0xfe) 696 && UBYTE(module[6 + UWORD(module, 4) - UWORD(module, 2) - 3]) == 0xfe)
697 song_len += 4; 697 song_len += 4;
698 song_len >>= pos_shift; 698 song_len >>= pos_shift;
699 if (song_len >= 0x100) 699 if (song_len >= 0x100)
700 return FALSE; 700 return FALSE;
701 INIT_ARRAY(global_seen); 701 INIT_ARRAY(global_seen);
702 module_info _ songs = 0; 702 module_info _ songs = 0;
703 for (pos = 0; pos < song_len && module_info _ songs < ASAP_SONGS_MAX; pos++) { 703 for (pos = 0; pos < song_len && module_info _ songs < ASAP_SONGS_MAX; pos++) {
704 if (!global_seen[pos]) { 704 if (!global_seen[pos]) {
705 module_info _ song_pos[module_info _ songs] = CAST(byte) pos; 705 module_info _ song_pos[module_info _ songs] = CAST(byte) pos;
706 parse_rmt_song(module_info, module, global_seen, song_len, pos_shift, pos); 706 parse_rmt_song(module_info, module, global_seen, song_len, pos_shift, pos);
707 } 707 }
708 } 708 }
709 /* must set fastplay after song durations calculations, so they assume 312 */ 709 /* must set fastplay after song durations calculations, so they assume 312 */
710 module_info _ fastplay = perframe2fastplay[per_frame - 1]; 710 module_info _ fastplay = perframe2fastplay[per_frame - 1];
711 module_info _ player = 0x600; 711 module_info _ player = 0x600;
712 return module_info _ songs > 0; 712 return module_info _ songs > 0;
713} 713}
714 714
715PRIVATE FUNC(void, parse_tmc_song, ( 715PRIVATE FUNC(void, parse_tmc_song, (
716 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, pos))) 716 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, pos)))
717{ 717{
718 V(int, addr_to_offset) = UWORD(module, 2) - 6; 718 V(int, addr_to_offset) = UWORD(module, 2) - 6;
719 V(int, tempo) = UBYTE(module[0x24]) + 1; 719 V(int, tempo) = UBYTE(module[0x24]) + 1;
720 V(int, frames) = 0; 720 V(int, frames) = 0;
721 NEW_ARRAY(int, pattern_offset, 8); 721 NEW_ARRAY(int, pattern_offset, 8);
722 NEW_ARRAY(int, blank_rows, 8); 722 NEW_ARRAY(int, blank_rows, 8);
723 while (UBYTE(module[0x1a6 + 15 + pos]) < 0x80) { 723 while (UBYTE(module[0x1a6 + 15 + pos]) < 0x80) {
724 V(int, ch); 724 V(int, ch);
725 V(int, pattern_rows); 725 V(int, pattern_rows);
726 for (ch = 7; ch >= 0; ch--) { 726 for (ch = 7; ch >= 0; ch--) {
727 V(int, pat) = UBYTE(module[0x1a6 + 15 + pos - 2 * ch]); 727 V(int, pat) = UBYTE(module[0x1a6 + 15 + pos - 2 * ch]);
728 pattern_offset[ch] = UBYTE(module[0xa6 + pat]) + (UBYTE(module[0x126 + pat]) << 8) - addr_to_offset; 728 pattern_offset[ch] = UBYTE(module[0xa6 + pat]) + (UBYTE(module[0x126 + pat]) << 8) - addr_to_offset;
729 blank_rows[ch] = 0; 729 blank_rows[ch] = 0;
730 } 730 }
731 for (pattern_rows = 64; --pattern_rows >= 0; ) { 731 for (pattern_rows = 64; --pattern_rows >= 0; ) {
732 for (ch = 7; ch >= 0; ch--) { 732 for (ch = 7; ch >= 0; ch--) {
733 if (--blank_rows[ch] >= 0) 733 if (--blank_rows[ch] >= 0)
734 continue; 734 continue;
735 for (;;) { 735 for (;;) {
736 V(int, i) = UBYTE(module[pattern_offset[ch]++]); 736 V(int, i) = UBYTE(module[pattern_offset[ch]++]);
737 if (i < 0x40) { 737 if (i < 0x40) {
738 pattern_offset[ch]++; 738 pattern_offset[ch]++;
739 break; 739 break;
740 } 740 }
741 if (i == 0x40) { 741 if (i == 0x40) {
742 i = UBYTE(module[pattern_offset[ch]++]); 742 i = UBYTE(module[pattern_offset[ch]++]);
743 if ((i & 0x7f) == 0) 743 if ((i & 0x7f) == 0)
744 pattern_rows = 0; 744 pattern_rows = 0;
745 else 745 else
746 tempo = (i & 0x7f) + 1; 746 tempo = (i & 0x7f) + 1;
747 if (i >= 0x80) 747 if (i >= 0x80)
748 pattern_offset[ch]++; 748 pattern_offset[ch]++;
749 break; 749 break;
750 } 750 }
751 if (i < 0x80) { 751 if (i < 0x80) {
752 i = module[pattern_offset[ch]++] & 0x7f; 752 i = module[pattern_offset[ch]++] & 0x7f;
753 if (i == 0) 753 if (i == 0)
754 pattern_rows = 0; 754 pattern_rows = 0;
755 else 755 else
756 tempo = i + 1; 756 tempo = i + 1;
757 pattern_offset[ch]++; 757 pattern_offset[ch]++;
758 break; 758 break;
759 } 759 }
760 if (i < 0xc0) 760 if (i < 0xc0)
761 continue; 761 continue;
762 blank_rows[ch] = i - 0xbf; 762 blank_rows[ch] = i - 0xbf;
763 break; 763 break;
764 } 764 }
765 } 765 }
766 frames += tempo; 766 frames += tempo;
767 } 767 }
768 pos += 16; 768 pos += 16;
769 } 769 }
770 if (UBYTE(module[0x1a6 + 14 + pos]) < 0x80) 770 if (UBYTE(module[0x1a6 + 14 + pos]) < 0x80)
771 module_info _ loops[module_info _ songs] = TRUE; 771 module_info _ loops[module_info _ songs] = TRUE;
772 set_song_duration(module_info, frames); 772 set_song_duration(module_info, frames);
773} 773}
774 774
775PRIVATE FUNC(abool, parse_tmc, ( 775PRIVATE FUNC(abool, parse_tmc, (
776 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 776 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
777 P(CONST BYTEARRAY, module), P(int, module_len))) 777 P(CONST BYTEARRAY, module), P(int, module_len)))
778{ 778{
779 V(int, i); 779 V(int, i);
780 V(int, last_pos); 780 V(int, last_pos);
781 if (module_len < 0x1d0) 781 if (module_len < 0x1d0)
782 return FALSE; 782 return FALSE;
783 module_info _ type = ASAP_TYPE_TMC; 783 module_info _ type = ASAP_TYPE_TMC;
784 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(tmc, obx))) 784 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(tmc, obx)))
785 return FALSE; 785 return FALSE;
786 module_info _ channels = 2; 786 module_info _ channels = 2;
787 i = 0; 787 i = 0;
788 /* find first instrument */ 788 /* find first instrument */
789 while (module[0x66 + i] == 0) { 789 while (module[0x66 + i] == 0) {
790 if (++i >= 64) 790 if (++i >= 64)
791 return FALSE; /* no instrument */ 791 return FALSE; /* no instrument */
792 } 792 }
793 last_pos = (UBYTE(module[0x66 + i]) << 8) + UBYTE(module[0x26 + i]) 793 last_pos = (UBYTE(module[0x66 + i]) << 8) + UBYTE(module[0x26 + i])
794 - UWORD(module, 2) - 0x1b0; 794 - UWORD(module, 2) - 0x1b0;
795 if (0x1b5 + last_pos >= module_len) 795 if (0x1b5 + last_pos >= module_len)
796 return FALSE; 796 return FALSE;
797 /* skip trailing jumps */ 797 /* skip trailing jumps */
798 do { 798 do {
799 if (last_pos <= 0) 799 if (last_pos <= 0)
800 return FALSE; /* no pattern to play */ 800 return FALSE; /* no pattern to play */
801 last_pos -= 16; 801 last_pos -= 16;
802 } while (UBYTE(module[0x1b5 + last_pos]) >= 0x80); 802 } while (UBYTE(module[0x1b5 + last_pos]) >= 0x80);
803 module_info _ songs = 0; 803 module_info _ songs = 0;
804 parse_tmc_song(module_info, module, 0); 804 parse_tmc_song(module_info, module, 0);
805 for (i = 0; i < last_pos && module_info _ songs < ASAP_SONGS_MAX; i += 16) 805 for (i = 0; i < last_pos && module_info _ songs < ASAP_SONGS_MAX; i += 16)
806 if (UBYTE(module[0x1b5 + i]) >= 0x80) 806 if (UBYTE(module[0x1b5 + i]) >= 0x80)
807 parse_tmc_song(module_info, module, i + 16); 807 parse_tmc_song(module_info, module, i + 16);
808 /* must set fastplay after song durations calculations, so they assume 312 */ 808 /* must set fastplay after song durations calculations, so they assume 312 */
809 i = module[0x25]; 809 i = module[0x25];
810 if (i < 1 || i > 4) 810 if (i < 1 || i > 4)
811 return FALSE; 811 return FALSE;
812 if (ast != NULL) 812 if (ast != NULL)
813 ast _ tmc_per_frame = module[0x25]; 813 ast _ tmc_per_frame = module[0x25];
814 module_info _ fastplay = perframe2fastplay[i - 1]; 814 module_info _ fastplay = perframe2fastplay[i - 1];
815 return TRUE; 815 return TRUE;
816} 816}
817 817
818PRIVATE FUNC(void, parse_tm2_song, ( 818PRIVATE FUNC(void, parse_tm2_song, (
819 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, pos))) 819 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, pos)))
820{ 820{
821 V(int, addr_to_offset) = UWORD(module, 2) - 6; 821 V(int, addr_to_offset) = UWORD(module, 2) - 6;
822 V(int, tempo) = UBYTE(module[0x24]) + 1; 822 V(int, tempo) = UBYTE(module[0x24]) + 1;
823 V(int, player_calls) = 0; 823 V(int, player_calls) = 0;
824 NEW_ARRAY(int, pattern_offset, 8); 824 NEW_ARRAY(int, pattern_offset, 8);
825 NEW_ARRAY(int, blank_rows, 8); 825 NEW_ARRAY(int, blank_rows, 8);
826 for (;;) { 826 for (;;) {
827 V(int, ch); 827 V(int, ch);
828 V(int, pattern_rows) = UBYTE(module[0x386 + 16 + pos]); 828 V(int, pattern_rows) = UBYTE(module[0x386 + 16 + pos]);
829 if (pattern_rows == 0) 829 if (pattern_rows == 0)
830 break; 830 break;
831 if (pattern_rows >= 0x80) { 831 if (pattern_rows >= 0x80) {
832 module_info _ loops[module_info _ songs] = TRUE; 832 module_info _ loops[module_info _ songs] = TRUE;
833 break; 833 break;
834 } 834 }
835 for (ch = 7; ch >= 0; ch--) { 835 for (ch = 7; ch >= 0; ch--) {
836 V(int, pat) = UBYTE(module[0x386 + 15 + pos - 2 * ch]); 836 V(int, pat) = UBYTE(module[0x386 + 15 + pos - 2 * ch]);
837 pattern_offset[ch] = UBYTE(module[0x106 + pat]) + (UBYTE(module[0x206 + pat]) << 8) - addr_to_offset; 837 pattern_offset[ch] = UBYTE(module[0x106 + pat]) + (UBYTE(module[0x206 + pat]) << 8) - addr_to_offset;
838 blank_rows[ch] = 0; 838 blank_rows[ch] = 0;
839 } 839 }
840 while (--pattern_rows >= 0) { 840 while (--pattern_rows >= 0) {
841 for (ch = 7; ch >= 0; ch--) { 841 for (ch = 7; ch >= 0; ch--) {
842 if (--blank_rows[ch] >= 0) 842 if (--blank_rows[ch] >= 0)
843 continue; 843 continue;
844 for (;;) { 844 for (;;) {
845 V(int, i) = UBYTE(module[pattern_offset[ch]++]); 845 V(int, i) = UBYTE(module[pattern_offset[ch]++]);
846 if (i == 0) { 846 if (i == 0) {
847 pattern_offset[ch]++; 847 pattern_offset[ch]++;
848 break; 848 break;
849 } 849 }
850 if (i < 0x40) { 850 if (i < 0x40) {
851 if (UBYTE(module[pattern_offset[ch]++]) >= 0x80) 851 if (UBYTE(module[pattern_offset[ch]++]) >= 0x80)
852 pattern_offset[ch]++; 852 pattern_offset[ch]++;
853 break; 853 break;
854 } 854 }
855 if (i < 0x80) { 855 if (i < 0x80) {
856 pattern_offset[ch]++; 856 pattern_offset[ch]++;
857 break; 857 break;
858 } 858 }
859 if (i == 0x80) { 859 if (i == 0x80) {
860 blank_rows[ch] = UBYTE(module[pattern_offset[ch]++]); 860 blank_rows[ch] = UBYTE(module[pattern_offset[ch]++]);
861 break; 861 break;
862 } 862 }
863 if (i < 0xc0) 863 if (i < 0xc0)
864 break; 864 break;
865 if (i < 0xd0) { 865 if (i < 0xd0) {
866 tempo = i - 0xbf; 866 tempo = i - 0xbf;
867 continue; 867 continue;
868 } 868 }
869 if (i < 0xe0) { 869 if (i < 0xe0) {
870 pattern_offset[ch]++; 870 pattern_offset[ch]++;
871 break; 871 break;
872 } 872 }
873 if (i < 0xf0) { 873 if (i < 0xf0) {
874 pattern_offset[ch] += 2; 874 pattern_offset[ch] += 2;
875 break; 875 break;
876 } 876 }
877 if (i < 0xff) { 877 if (i < 0xff) {
878 blank_rows[ch] = i - 0xf0; 878 blank_rows[ch] = i - 0xf0;
879 break; 879 break;
880 } 880 }
881 blank_rows[ch] = 64; 881 blank_rows[ch] = 64;
882 break; 882 break;
883 } 883 }
884 } 884 }
885 player_calls += tempo; 885 player_calls += tempo;
886 } 886 }
887 pos += 17; 887 pos += 17;
888 } 888 }
889 set_song_duration(module_info, player_calls); 889 set_song_duration(module_info, player_calls);
890} 890}
891 891
892PRIVATE FUNC(abool, parse_tm2, ( 892PRIVATE FUNC(abool, parse_tm2, (
893 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 893 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
894 P(CONST BYTEARRAY, module), P(int, module_len))) 894 P(CONST BYTEARRAY, module), P(int, module_len)))
895{ 895{
896 V(int, i); 896 V(int, i);
897 V(int, last_pos); 897 V(int, last_pos);
898 V(int, c); 898 V(int, c);
899 if (module_len < 0x3a4) 899 if (module_len < 0x3a4)
900 return FALSE; 900 return FALSE;
901 module_info _ type = ASAP_TYPE_TM2; 901 module_info _ type = ASAP_TYPE_TM2;
902 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(tm2, obx))) 902 if (!load_native(ast, module_info, module, module_len, GET_RESOURCE(tm2, obx)))
903 return FALSE; 903 return FALSE;
904 i = module[0x25]; 904 i = module[0x25];
905 if (i < 1 || i > 4) 905 if (i < 1 || i > 4)
906 return FALSE; 906 return FALSE;
907 module_info _ fastplay = perframe2fastplay[i - 1]; 907 module_info _ fastplay = perframe2fastplay[i - 1];
908 module_info _ player = 0x500; 908 module_info _ player = 0x500;
909 if (module[0x1f] != 0) 909 if (module[0x1f] != 0)
910 module_info _ channels = 2; 910 module_info _ channels = 2;
911 last_pos = 0xffff; 911 last_pos = 0xffff;
912 for (i = 0; i < 0x80; i++) { 912 for (i = 0; i < 0x80; i++) {
913 V(int, instr_addr) = UBYTE(module[0x86 + i]) + (UBYTE(module[0x306 + i]) << 8); 913 V(int, instr_addr) = UBYTE(module[0x86 + i]) + (UBYTE(module[0x306 + i]) << 8);
914 if (instr_addr != 0 && instr_addr < last_pos) 914 if (instr_addr != 0 && instr_addr < last_pos)
915 last_pos = instr_addr; 915 last_pos = instr_addr;
916 } 916 }
917 for (i = 0; i < 0x100; i++) { 917 for (i = 0; i < 0x100; i++) {
918 V(int, pattern_addr) = UBYTE(module[0x106 + i]) + (UBYTE(module[0x206 + i]) << 8); 918 V(int, pattern_addr) = UBYTE(module[0x106 + i]) + (UBYTE(module[0x206 + i]) << 8);
919 if (pattern_addr != 0 && pattern_addr < last_pos) 919 if (pattern_addr != 0 && pattern_addr < last_pos)
920 last_pos = pattern_addr; 920 last_pos = pattern_addr;
921 } 921 }
922 last_pos -= UWORD(module, 2) + 0x380; 922 last_pos -= UWORD(module, 2) + 0x380;
923 if (0x386 + last_pos >= module_len) 923 if (0x386 + last_pos >= module_len)
924 return FALSE; 924 return FALSE;
925 /* skip trailing stop/jump commands */ 925 /* skip trailing stop/jump commands */
926 do { 926 do {
927 if (last_pos <= 0) 927 if (last_pos <= 0)
928 return FALSE; 928 return FALSE;
929 last_pos -= 17; 929 last_pos -= 17;
930 c = UBYTE(module[0x386 + 16 + last_pos]); 930 c = UBYTE(module[0x386 + 16 + last_pos]);
931 } while (c == 0 || c >= 0x80); 931 } while (c == 0 || c >= 0x80);
932 module_info _ songs = 0; 932 module_info _ songs = 0;
933 parse_tm2_song(module_info, module, 0); 933 parse_tm2_song(module_info, module, 0);
934 for (i = 0; i < last_pos && module_info _ songs < ASAP_SONGS_MAX; i += 17) { 934 for (i = 0; i < last_pos && module_info _ songs < ASAP_SONGS_MAX; i += 17) {
935 c = UBYTE(module[0x386 + 16 + i]); 935 c = UBYTE(module[0x386 + 16 + i]);
936 if (c == 0 || c >= 0x80) 936 if (c == 0 || c >= 0x80)
937 parse_tm2_song(module_info, module, i + 17); 937 parse_tm2_song(module_info, module, i + 17);
938 } 938 }
939 return TRUE; 939 return TRUE;
940} 940}
941 941
942#endif /* ASAP_ONLY_SAP */ 942#endif /* ASAP_ONLY_SAP */
943 943
944PRIVATE FUNC(abool, has_string_at, (P(CONST BYTEARRAY, module), P(int, module_index), P(STRING, s))) 944PRIVATE FUNC(abool, has_string_at, (P(CONST BYTEARRAY, module), P(int, module_index), P(STRING, s)))
945{ 945{
946 V(int, i); 946 V(int, i);
947 V(int, n) = strlen(s); 947 V(int, n) = strlen(s);
948 for (i = 0; i < n; i++) 948 for (i = 0; i < n; i++)
949 if (module[module_index + i] != CHARCODEAT(s, i)) 949 if (module[module_index + i] != CHARCODEAT(s, i))
950 return FALSE; 950 return FALSE;
951 return TRUE; 951 return TRUE;
952} 952}
953 953
954PRIVATE FUNC(STRING, parse_text, (P(OUT_STRING, dest), P(CONST BYTEARRAY, module), P(int, module_index))) 954PRIVATE FUNC(STRING, parse_text, (P(OUT_STRING, dest), P(CONST BYTEARRAY, module), P(int, module_index)))
955{ 955{
956 V(int, i); 956 V(int, i);
957 if (module[module_index] != CHARCODE('"')) 957 if (module[module_index] != CHARCODE('"'))
958 return NULL; 958 return NULL;
959 if (has_string_at(module, module_index + 1, "<?>\"")) 959 if (has_string_at(module, module_index + 1, "<?>\""))
960 return dest; 960 return dest;
961 for (i = 0; ; i++) { 961 for (i = 0; ; i++) {
962 V(int, c) = module[module_index + 1 + i]; 962 V(int, c) = module[module_index + 1 + i];
963 if (c == CHARCODE('"')) 963 if (c == CHARCODE('"'))
964 break; 964 break;
965 if (c < 32 || c >= 127) 965 if (c < 32 || c >= 127)
966 return NULL; 966 return NULL;
967 } 967 }
968 BYTES_TO_STRING(dest, module, module_index + 1, i); 968 BYTES_TO_STRING(dest, module, module_index + 1, i);
969 return dest; 969 return dest;
970} 970}
971 971
972PRIVATE FUNC(int, parse_dec, (P(CONST BYTEARRAY, module), P(int, module_index), P(int, maxval))) 972PRIVATE FUNC(int, parse_dec, (P(CONST BYTEARRAY, module), P(int, module_index), P(int, maxval)))
973{ 973{
974 V(int, r); 974 V(int, r);
975 if (module[module_index] == 0xd) 975 if (module[module_index] == 0xd)
976 return -1; 976 return -1;
977 for (r = 0;;) { 977 for (r = 0;;) {
978 V(int, c) = module[module_index++]; 978 V(int, c) = module[module_index++];
979 if (c == 0xd) 979 if (c == 0xd)
980 break; 980 break;
981 if (c < CHARCODE('0') || c > CHARCODE('9')) 981 if (c < CHARCODE('0') || c > CHARCODE('9'))
982 return -1; 982 return -1;
983 r = 10 * r + c - 48; 983 r = 10 * r + c - 48;
984 if (r > maxval) 984 if (r > maxval)
985 return -1; 985 return -1;
986 } 986 }
987 return r; 987 return r;
988} 988}
989 989
990PRIVATE FUNC(int, parse_hex, (P(CONST BYTEARRAY, module), P(int, module_index))) 990PRIVATE FUNC(int, parse_hex, (P(CONST BYTEARRAY, module), P(int, module_index)))
991{ 991{
992 V(int, r); 992 V(int, r);
993 if (module[module_index] == 0xd) 993 if (module[module_index] == 0xd)
994 return -1; 994 return -1;
995 for (r = 0;;) { 995 for (r = 0;;) {
996 V(int, c) = module[module_index++]; 996 V(int, c) = module[module_index++];
997 if (c == 0xd) 997 if (c == 0xd)
998 break; 998 break;
999 if (r > 0xfff) 999 if (r > 0xfff)
1000 return -1; 1000 return -1;
1001 r <<= 4; 1001 r <<= 4;
1002 if (c >= CHARCODE('0') && c <= CHARCODE('9')) 1002 if (c >= CHARCODE('0') && c <= CHARCODE('9'))
1003 r += c - CHARCODE('0'); 1003 r += c - CHARCODE('0');
1004 else if (c >= CHARCODE('A') && c <= CHARCODE('F')) 1004 else if (c >= CHARCODE('A') && c <= CHARCODE('F'))
1005 r += c - CHARCODE('A') + 10; 1005 r += c - CHARCODE('A') + 10;
1006 else if (c >= CHARCODE('a') && c <= CHARCODE('f')) 1006 else if (c >= CHARCODE('a') && c <= CHARCODE('f'))
1007 r += c - CHARCODE('a') + 10; 1007 r += c - CHARCODE('a') + 10;
1008 else 1008 else
1009 return -1; 1009 return -1;
1010 } 1010 }
1011 return r; 1011 return r;
1012} 1012}
1013 1013
1014FUNC(int, ASAP_ParseDuration, (P(STRING, s))) 1014FUNC(int, ASAP_ParseDuration, (P(STRING, s)))
1015{ 1015{
1016 V(int, i) = 0; 1016 V(int, i) = 0;
1017 V(int, r); 1017 V(int, r);
1018 V(int, d); 1018 V(int, d);
1019 V(int, n) = strlen(s); 1019 V(int, n) = strlen(s);
1020#define PARSE_DIGIT(maxdig, retifnot) \ 1020#define PARSE_DIGIT(maxdig, retifnot) \
1021 if (i >= n) \ 1021 if (i >= n) \
1022 return retifnot; \ 1022 return retifnot; \
1023 d = CHARCODEAT(s, i) - 48; \ 1023 d = CHARCODEAT(s, i) - 48; \
1024 if (d < 0 || d > maxdig) \ 1024 if (d < 0 || d > maxdig) \
1025 return -1; \ 1025 return -1; \
1026 i++; 1026 i++;
1027 1027
1028 PARSE_DIGIT(9, -1); 1028 PARSE_DIGIT(9, -1);
1029 r = d; 1029 r = d;
1030 if (i < n) { 1030 if (i < n) {
1031 d = CHARCODEAT(s, i) - 48; 1031 d = CHARCODEAT(s, i) - 48;
1032 if (d >= 0 && d <= 9) { 1032 if (d >= 0 && d <= 9) {
1033 i++; 1033 i++;
1034 r = 10 * r + d; 1034 r = 10 * r + d;
1035 } 1035 }
1036 if (i < n && CHARAT(s, i) == ':') { 1036 if (i < n && CHARAT(s, i) == ':') {
1037 i++; 1037 i++;
1038 PARSE_DIGIT(5, -1); 1038 PARSE_DIGIT(5, -1);
1039 r = (6 * r + d) * 10; 1039 r = (6 * r + d) * 10;
1040 PARSE_DIGIT(9, -1); 1040 PARSE_DIGIT(9, -1);
1041 r += d; 1041 r += d;
1042 } 1042 }
1043 } 1043 }
1044 r *= 1000; 1044 r *= 1000;
1045 if (i >= n) 1045 if (i >= n)
1046 return r; 1046 return r;
1047 if (CHARAT(s, i) != '.') 1047 if (CHARAT(s, i) != '.')
1048 return -1; 1048 return -1;
1049 i++; 1049 i++;
1050 PARSE_DIGIT(9, -1); 1050 PARSE_DIGIT(9, -1);
1051 r += 100 * d; 1051 r += 100 * d;
1052 PARSE_DIGIT(9, r); 1052 PARSE_DIGIT(9, r);
1053 r += 10 * d; 1053 r += 10 * d;
1054 PARSE_DIGIT(9, r); 1054 PARSE_DIGIT(9, r);
1055 r += d; 1055 r += d;
1056 return r; 1056 return r;
1057} 1057}
1058 1058
1059PRIVATE FUNC(abool, parse_sap_header, ( 1059PRIVATE FUNC(abool, parse_sap_header, (
1060 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, module_len))) 1060 P(ASAP_ModuleInfo PTR, module_info), P(CONST BYTEARRAY, module), P(int, module_len)))
1061{ 1061{
1062 V(int, module_index); 1062 V(int, module_index);
1063 V(int, type) = 0; 1063 V(int, type) = 0;
1064 V(int, duration_index) = 0; 1064 V(int, duration_index) = 0;
1065 if (!has_string_at(module, 0, "SAP\r\n")) 1065 if (!has_string_at(module, 0, "SAP\r\n"))
1066 return FALSE; 1066 return FALSE;
1067 module_index = 5; 1067 module_index = 5;
1068 while (UBYTE(module[module_index]) != 0xff) { 1068 while (UBYTE(module[module_index]) != 0xff) {
1069 if (module_index + 8 >= module_len) 1069 if (module_index + 8 >= module_len)
1070 return FALSE; 1070 return FALSE;
1071#define TAG_IS(s) has_string_at(module, module_index, s) 1071#define TAG_IS(s) has_string_at(module, module_index, s)
1072#ifdef C 1072#ifdef C
1073#define SET_TEXT(v, i) if (parse_text(v, module, module_index + i) == NULL) return FALSE 1073#define SET_TEXT(v, i) if (parse_text(v, module, module_index + i) == NULL) return FALSE
@@ -1076,287 +1076,287 @@ PRIVATE FUNC(abool, parse_sap_header, (
1076#endif 1076#endif
1077#define SET_DEC(v, i, min, max) v = parse_dec(module, module_index + i, max); if (v < min) return FALSE 1077#define SET_DEC(v, i, min, max) v = parse_dec(module, module_index + i, max); if (v < min) return FALSE
1078#define SET_HEX(v, i) v = parse_hex(module, module_index + i) 1078#define SET_HEX(v, i) v = parse_hex(module, module_index + i)
1079 if (TAG_IS("AUTHOR ")) { 1079 if (TAG_IS("AUTHOR ")) {
1080 SET_TEXT(module_info _ author, 7); 1080 SET_TEXT(module_info _ author, 7);
1081 } 1081 }
1082 else if (TAG_IS("NAME ")) { 1082 else if (TAG_IS("NAME ")) {
1083 SET_TEXT(module_info _ name, 5); 1083 SET_TEXT(module_info _ name, 5);
1084 } 1084 }
1085 else if (TAG_IS("DATE ")) { 1085 else if (TAG_IS("DATE ")) {
1086 SET_TEXT(module_info _ date, 5); 1086 SET_TEXT(module_info _ date, 5);
1087 } 1087 }
1088 else if (TAG_IS("SONGS ")) { 1088 else if (TAG_IS("SONGS ")) {
1089 SET_DEC(module_info _ songs, 6, 1, ASAP_SONGS_MAX); 1089 SET_DEC(module_info _ songs, 6, 1, ASAP_SONGS_MAX);
1090 } 1090 }
1091 else if (TAG_IS("DEFSONG ")) { 1091 else if (TAG_IS("DEFSONG ")) {
1092 SET_DEC(module_info _ default_song, 8, 0, ASAP_SONGS_MAX - 1); 1092 SET_DEC(module_info _ default_song, 8, 0, ASAP_SONGS_MAX - 1);
1093 } 1093 }
1094 else if (TAG_IS("STEREO\r")) 1094 else if (TAG_IS("STEREO\r"))
1095 module_info _ channels = 2; 1095 module_info _ channels = 2;
1096 else if (TAG_IS("TIME ")) { 1096 else if (TAG_IS("TIME ")) {
1097 V(int, i); 1097 V(int, i);
1098#ifdef C 1098#ifdef C
1099 char s[ASAP_DURATION_CHARS]; 1099 char s[ASAP_DURATION_CHARS];
1100#else 1100#else
1101 V(STRING, s); 1101 V(STRING, s);
1102#endif 1102#endif
1103 module_index += 5; 1103 module_index += 5;
1104 for (i = 0; module[module_index + i] != 0xd; i++); 1104 for (i = 0; module[module_index + i] != 0xd; i++);
1105 if (i > 5 && has_string_at(module, module_index + i - 5, " LOOP")) { 1105 if (i > 5 && has_string_at(module, module_index + i - 5, " LOOP")) {
1106 module_info _ loops[duration_index] = TRUE; 1106 module_info _ loops[duration_index] = TRUE;
1107 i -= 5; 1107 i -= 5;
1108 } 1108 }
1109#ifdef C 1109#ifdef C
1110 if (i >= ASAP_DURATION_CHARS) 1110 if (i >= ASAP_DURATION_CHARS)
1111 return FALSE; 1111 return FALSE;
1112#endif 1112#endif
1113 BYTES_TO_STRING(s, module, module_index, i); 1113 BYTES_TO_STRING(s, module, module_index, i);
1114 i = ASAP_ParseDuration(s); 1114 i = ASAP_ParseDuration(s);
1115 if (i < 0 || duration_index >= ASAP_SONGS_MAX) 1115 if (i < 0 || duration_index >= ASAP_SONGS_MAX)
1116 return FALSE; 1116 return FALSE;
1117 module_info _ durations[duration_index++] = i; 1117 module_info _ durations[duration_index++] = i;
1118 } 1118 }
1119 else if (TAG_IS("TYPE ")) 1119 else if (TAG_IS("TYPE "))
1120 type = module[module_index + 5]; 1120 type = module[module_index + 5];
1121 else if (TAG_IS("FASTPLAY ")) { 1121 else if (TAG_IS("FASTPLAY ")) {
1122 SET_DEC(module_info _ fastplay, 9, 1, 312); 1122 SET_DEC(module_info _ fastplay, 9, 1, 312);
1123 } 1123 }
1124 else if (TAG_IS("MUSIC ")) { 1124 else if (TAG_IS("MUSIC ")) {
1125 SET_HEX(module_info _ music, 6); 1125 SET_HEX(module_info _ music, 6);
1126 } 1126 }
1127 else if (TAG_IS("INIT ")) { 1127 else if (TAG_IS("INIT ")) {
1128 SET_HEX(module_info _ init, 5); 1128 SET_HEX(module_info _ init, 5);
1129 } 1129 }
1130 else if (TAG_IS("PLAYER ")) { 1130 else if (TAG_IS("PLAYER ")) {
1131 SET_HEX(module_info _ player, 7); 1131 SET_HEX(module_info _ player, 7);
1132 } 1132 }
1133 else if (TAG_IS("COVOX ")) { 1133 else if (TAG_IS("COVOX ")) {
1134 SET_HEX(module_info _ covox_addr, 6); 1134 SET_HEX(module_info _ covox_addr, 6);
1135 if (module_info _ covox_addr != 0xd600) 1135 if (module_info _ covox_addr != 0xd600)
1136 return FALSE; 1136 return FALSE;
1137 module_info _ channels = 2; 1137 module_info _ channels = 2;
1138 } 1138 }
1139 1139
1140 while (module[module_index++] != 0x0d) { 1140 while (module[module_index++] != 0x0d) {
1141 if (module_index >= module_len) 1141 if (module_index >= module_len)
1142 return FALSE; 1142 return FALSE;
1143 } 1143 }
1144 if (module[module_index++] != 0x0a) 1144 if (module[module_index++] != 0x0a)
1145 return FALSE; 1145 return FALSE;
1146 } 1146 }
1147 if (module_info _ default_song >= module_info _ songs) 1147 if (module_info _ default_song >= module_info _ songs)
1148 return FALSE; 1148 return FALSE;
1149 switch (type) { 1149 switch (type) {
1150 case CHARCODE('B'): 1150 case CHARCODE('B'):
1151 if (module_info _ player < 0 || module_info _ init < 0) 1151 if (module_info _ player < 0 || module_info _ init < 0)
1152 return FALSE; 1152 return FALSE;
1153 module_info _ type = ASAP_TYPE_SAP_B; 1153 module_info _ type = ASAP_TYPE_SAP_B;
1154 break; 1154 break;
1155 case CHARCODE('C'): 1155 case CHARCODE('C'):
1156 if (module_info _ player < 0 || module_info _ music < 0) 1156 if (module_info _ player < 0 || module_info _ music < 0)
1157 return FALSE; 1157 return FALSE;
1158 module_info _ type = ASAP_TYPE_SAP_C; 1158 module_info _ type = ASAP_TYPE_SAP_C;
1159 break; 1159 break;
1160 case CHARCODE('D'): 1160 case CHARCODE('D'):
1161 if (module_info _ init < 0) 1161 if (module_info _ init < 0)
1162 return FALSE; 1162 return FALSE;
1163 module_info _ type = ASAP_TYPE_SAP_D; 1163 module_info _ type = ASAP_TYPE_SAP_D;
1164 break; 1164 break;
1165 case CHARCODE('S'): 1165 case CHARCODE('S'):
1166 if (module_info _ init < 0) 1166 if (module_info _ init < 0)
1167 return FALSE; 1167 return FALSE;
1168 module_info _ type = ASAP_TYPE_SAP_S; 1168 module_info _ type = ASAP_TYPE_SAP_S;
1169 module_info _ fastplay = 78; 1169 module_info _ fastplay = 78;
1170 break; 1170 break;
1171 default: 1171 default:
1172 return FALSE; 1172 return FALSE;
1173 } 1173 }
1174 if (UBYTE(module[module_index + 1]) != 0xff) 1174 if (UBYTE(module[module_index + 1]) != 0xff)
1175 return FALSE; 1175 return FALSE;
1176 module_info _ header_len = module_index; 1176 module_info _ header_len = module_index;
1177 return TRUE; 1177 return TRUE;
1178} 1178}
1179 1179
1180PRIVATE FUNC(abool, parse_sap, ( 1180PRIVATE FUNC(abool, parse_sap, (
1181 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 1181 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
1182 P(CONST BYTEARRAY, module), P(int, module_len))) 1182 P(CONST BYTEARRAY, module), P(int, module_len)))
1183{ 1183{
1184 V(int, module_index); 1184 V(int, module_index);
1185 if (!parse_sap_header(module_info, module, module_len)) 1185 if (!parse_sap_header(module_info, module, module_len))
1186 return FALSE; 1186 return FALSE;
1187 if (ast == NULL) 1187 if (ast == NULL)
1188 return TRUE; 1188 return TRUE;
1189 ZERO_ARRAY(ast _ memory); 1189 ZERO_ARRAY(ast _ memory);
1190 module_index = module_info _ header_len + 2; 1190 module_index = module_info _ header_len + 2;
1191 while (module_index + 5 <= module_len) { 1191 while (module_index + 5 <= module_len) {
1192 V(int, start_addr) = UWORD(module, module_index); 1192 V(int, start_addr) = UWORD(module, module_index);
1193 V(int, block_len) = UWORD(module, module_index + 2) + 1 - start_addr; 1193 V(int, block_len) = UWORD(module, module_index + 2) + 1 - start_addr;
1194 if (block_len <= 0 || module_index + block_len > module_len) 1194 if (block_len <= 0 || module_index + block_len > module_len)
1195 return FALSE; 1195 return FALSE;
1196 module_index += 4; 1196 module_index += 4;
1197 COPY_ARRAY(ast _ memory, start_addr, module, module_index, block_len); 1197 COPY_ARRAY(ast _ memory, start_addr, module, module_index, block_len);
1198 module_index += block_len; 1198 module_index += block_len;
1199 if (module_index == module_len) 1199 if (module_index == module_len)
1200 return TRUE; 1200 return TRUE;
1201 if (module_index + 7 <= module_len 1201 if (module_index + 7 <= module_len
1202 && UBYTE(module[module_index]) == 0xff && UBYTE(module[module_index + 1]) == 0xff) 1202 && UBYTE(module[module_index]) == 0xff && UBYTE(module[module_index + 1]) == 0xff)
1203 module_index += 2; 1203 module_index += 2;
1204 } 1204 }
1205 return FALSE; 1205 return FALSE;
1206} 1206}
1207 1207
1208#define ASAP_EXT(c1, c2, c3) ((CHARCODE(c1) + (CHARCODE(c2) << 8) + (CHARCODE(c3) << 16)) | 0x202020) 1208#define ASAP_EXT(c1, c2, c3) ((CHARCODE(c1) + (CHARCODE(c2) << 8) + (CHARCODE(c3) << 16)) | 0x202020)
1209 1209
1210PRIVATE FUNC(int, get_packed_ext, (P(STRING, filename))) 1210PRIVATE FUNC(int, get_packed_ext, (P(STRING, filename)))
1211{ 1211{
1212 V(int, i) = strlen(filename); 1212 V(int, i) = strlen(filename);
1213 V(int, ext) = 0; 1213 V(int, ext) = 0;
1214 while (--i > 0) { 1214 while (--i > 0) {
1215 V(char, c) = CHARAT(filename, i); 1215 V(char, c) = CHARAT(filename, i);
1216 if (c <= ' ' || c > 'z') 1216 if (c <= ' ' || c > 'z')
1217 return 0; 1217 return 0;
1218 if (c == '.') 1218 if (c == '.')
1219 return ext | 0x202020; 1219 return ext | 0x202020;
1220 ext = (ext << 8) + CHARCODE(c); 1220 ext = (ext << 8) + CHARCODE(c);
1221 } 1221 }
1222 return 0; 1222 return 0;
1223} 1223}
1224 1224
1225PRIVATE FUNC(abool, is_our_ext, (P(int, ext))) 1225PRIVATE FUNC(abool, is_our_ext, (P(int, ext)))
1226{ 1226{
1227 switch (ext) { 1227 switch (ext) {
1228 case ASAP_EXT('S', 'A', 'P'): 1228 case ASAP_EXT('S', 'A', 'P'):
1229#ifndef ASAP_ONLY_SAP 1229#ifndef ASAP_ONLY_SAP
1230 case ASAP_EXT('C', 'M', 'C'): 1230 case ASAP_EXT('C', 'M', 'C'):
1231 case ASAP_EXT('C', 'M', '3'): 1231 case ASAP_EXT('C', 'M', '3'):
1232 case ASAP_EXT('C', 'M', 'R'): 1232 case ASAP_EXT('C', 'M', 'R'):
1233 case ASAP_EXT('C', 'M', 'S'): 1233 case ASAP_EXT('C', 'M', 'S'):
1234 case ASAP_EXT('D', 'M', 'C'): 1234 case ASAP_EXT('D', 'M', 'C'):
1235 case ASAP_EXT('D', 'L', 'T'): 1235 case ASAP_EXT('D', 'L', 'T'):
1236 case ASAP_EXT('M', 'P', 'T'): 1236 case ASAP_EXT('M', 'P', 'T'):
1237 case ASAP_EXT('M', 'P', 'D'): 1237 case ASAP_EXT('M', 'P', 'D'):
1238 case ASAP_EXT('R', 'M', 'T'): 1238 case ASAP_EXT('R', 'M', 'T'):
1239 case ASAP_EXT('T', 'M', 'C'): 1239 case ASAP_EXT('T', 'M', 'C'):
1240 case ASAP_EXT('T', 'M', '8'): 1240 case ASAP_EXT('T', 'M', '8'):
1241 case ASAP_EXT('T', 'M', '2'): 1241 case ASAP_EXT('T', 'M', '2'):
1242#endif 1242#endif
1243 return TRUE; 1243 return TRUE;
1244 default: 1244 default:
1245 return FALSE; 1245 return FALSE;
1246 } 1246 }
1247} 1247}
1248 1248
1249FUNC(abool, ASAP_IsOurFile, (P(STRING, filename))) 1249FUNC(abool, ASAP_IsOurFile, (P(STRING, filename)))
1250{ 1250{
1251 V(int, ext) = get_packed_ext(filename); 1251 V(int, ext) = get_packed_ext(filename);
1252 return is_our_ext(ext); 1252 return is_our_ext(ext);
1253} 1253}
1254 1254
1255FUNC(abool, ASAP_IsOurExt, (P(STRING, ext))) 1255FUNC(abool, ASAP_IsOurExt, (P(STRING, ext)))
1256{ 1256{
1257 return strlen(ext) == 3 1257 return strlen(ext) == 3
1258 && is_our_ext(ASAP_EXT(CHARAT(ext, 0), CHARAT(ext, 1), CHARAT(ext, 2))); 1258 && is_our_ext(ASAP_EXT(CHARAT(ext, 0), CHARAT(ext, 1), CHARAT(ext, 2)));
1259} 1259}
1260 1260
1261PRIVATE FUNC(abool, parse_file, ( 1261PRIVATE FUNC(abool, parse_file, (
1262 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info), 1262 P(ASAP_State PTR, ast), P(ASAP_ModuleInfo PTR, module_info),
1263 P(STRING, filename), P(CONST BYTEARRAY, module), P(int, module_len))) 1263 P(STRING, filename), P(CONST BYTEARRAY, module), P(int, module_len)))
1264{ 1264{
1265 V(int, i); 1265 V(int, i);
1266 V(int, len) = strlen(filename); 1266 V(int, len) = strlen(filename);
1267 V(int, basename) = 0; 1267 V(int, basename) = 0;
1268 V(int, ext) = -1; 1268 V(int, ext) = -1;
1269 for (i = 0; i < len; i++) { 1269 for (i = 0; i < len; i++) {
1270 V(char, c) = CHARAT(filename, i); 1270 V(char, c) = CHARAT(filename, i);
1271 if (c == '/' || c == '\\') { 1271 if (c == '/' || c == '\\') {
1272 basename = i + 1; 1272 basename = i + 1;
1273 ext = -1; 1273 ext = -1;
1274 } 1274 }
1275 else if (c == '.') 1275 else if (c == '.')
1276 ext = i; 1276 ext = i;
1277 } 1277 }
1278 if (ext < 0) 1278 if (ext < 0)
1279 return FALSE; 1279 return FALSE;
1280 EMPTY_STRING(module_info _ author); 1280 EMPTY_STRING(module_info _ author);
1281 SUBSTRING(module_info _ name, filename, basename, ext - basename); 1281 SUBSTRING(module_info _ name, filename, basename, ext - basename);
1282 EMPTY_STRING(module_info _ date); 1282 EMPTY_STRING(module_info _ date);
1283 module_info _ channels = 1; 1283 module_info _ channels = 1;
1284 module_info _ songs = 1; 1284 module_info _ songs = 1;
1285 module_info _ default_song = 0; 1285 module_info _ default_song = 0;
1286 for (i = 0; i < ASAP_SONGS_MAX; i++) { 1286 for (i = 0; i < ASAP_SONGS_MAX; i++) {
1287 module_info _ durations[i] = -1; 1287 module_info _ durations[i] = -1;
1288 module_info _ loops[i] = FALSE; 1288 module_info _ loops[i] = FALSE;
1289 } 1289 }
1290 module_info _ fastplay = 312; 1290 module_info _ fastplay = 312;
1291 module_info _ music = -1; 1291 module_info _ music = -1;
1292 module_info _ init = -1; 1292 module_info _ init = -1;
1293 module_info _ player = -1; 1293 module_info _ player = -1;
1294 module_info _ covox_addr = -1; 1294 module_info _ covox_addr = -1;
1295 switch (get_packed_ext(filename)) { 1295 switch (get_packed_ext(filename)) {
1296 case ASAP_EXT('S', 'A', 'P'): 1296 case ASAP_EXT('S', 'A', 'P'):
1297 return parse_sap(ast, module_info, module, module_len); 1297 return parse_sap(ast, module_info, module, module_len);
1298#ifndef ASAP_ONLY_SAP 1298#ifndef ASAP_ONLY_SAP
1299 case ASAP_EXT('C', 'M', 'C'): 1299 case ASAP_EXT('C', 'M', 'C'):
1300 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMC, GET_RESOURCE(cmc, obx)); 1300 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMC, GET_RESOURCE(cmc, obx));
1301 case ASAP_EXT('C', 'M', '3'): 1301 case ASAP_EXT('C', 'M', '3'):
1302 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CM3, GET_RESOURCE(cm3, obx)); 1302 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CM3, GET_RESOURCE(cm3, obx));
1303 case ASAP_EXT('C', 'M', 'R'): 1303 case ASAP_EXT('C', 'M', 'R'):
1304 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMR, GET_RESOURCE(cmc, obx)); 1304 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMR, GET_RESOURCE(cmc, obx));
1305 case ASAP_EXT('C', 'M', 'S'): 1305 case ASAP_EXT('C', 'M', 'S'):
1306 module_info _ channels = 2; 1306 module_info _ channels = 2;
1307 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMS, GET_RESOURCE(cms, obx)); 1307 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMS, GET_RESOURCE(cms, obx));
1308 case ASAP_EXT('D', 'M', 'C'): 1308 case ASAP_EXT('D', 'M', 'C'):
1309 module_info _ fastplay = 156; 1309 module_info _ fastplay = 156;
1310 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMC, GET_RESOURCE(cmc, obx)); 1310 return parse_cmc(ast, module_info, module, module_len, ASAP_TYPE_CMC, GET_RESOURCE(cmc, obx));
1311 case ASAP_EXT('D', 'L', 'T'): 1311 case ASAP_EXT('D', 'L', 'T'):
1312 return parse_dlt(ast, module_info, module, module_len); 1312 return parse_dlt(ast, module_info, module, module_len);
1313 case ASAP_EXT('M', 'P', 'T'): 1313 case ASAP_EXT('M', 'P', 'T'):
1314 return parse_mpt(ast, module_info, module, module_len); 1314 return parse_mpt(ast, module_info, module, module_len);
1315 case ASAP_EXT('M', 'P', 'D'): 1315 case ASAP_EXT('M', 'P', 'D'):
1316 module_info _ fastplay = 156; 1316 module_info _ fastplay = 156;
1317 return parse_mpt(ast, module_info, module, module_len); 1317 return parse_mpt(ast, module_info, module, module_len);
1318 case ASAP_EXT('R', 'M', 'T'): 1318 case ASAP_EXT('R', 'M', 'T'):
1319 return parse_rmt(ast, module_info, module, module_len); 1319 return parse_rmt(ast, module_info, module, module_len);
1320 case ASAP_EXT('T', 'M', 'C'): 1320 case ASAP_EXT('T', 'M', 'C'):
1321 case ASAP_EXT('T', 'M', '8'): 1321 case ASAP_EXT('T', 'M', '8'):
1322 return parse_tmc(ast, module_info, module, module_len); 1322 return parse_tmc(ast, module_info, module, module_len);
1323 case ASAP_EXT('T', 'M', '2'): 1323 case ASAP_EXT('T', 'M', '2'):
1324 return parse_tm2(ast, module_info, module, module_len); 1324 return parse_tm2(ast, module_info, module, module_len);
1325#endif 1325#endif
1326 default: 1326 default:
1327 return FALSE; 1327 return FALSE;
1328 } 1328 }
1329} 1329}
1330 1330
1331FUNC(abool, ASAP_GetModuleInfo, ( 1331FUNC(abool, ASAP_GetModuleInfo, (
1332 P(ASAP_ModuleInfo PTR, module_info), P(STRING, filename), 1332 P(ASAP_ModuleInfo PTR, module_info), P(STRING, filename),
1333 P(CONST BYTEARRAY, module), P(int, module_len))) 1333 P(CONST BYTEARRAY, module), P(int, module_len)))
1334{ 1334{
1335 return parse_file(NULL, module_info, filename, module, module_len); 1335 return parse_file(NULL, module_info, filename, module, module_len);
1336} 1336}
1337 1337
1338FUNC(abool, ASAP_Load, ( 1338FUNC(abool, ASAP_Load, (
1339 P(ASAP_State PTR, ast), P(STRING, filename), 1339 P(ASAP_State PTR, ast), P(STRING, filename),
1340 P(CONST BYTEARRAY, module), P(int, module_len))) 1340 P(CONST BYTEARRAY, module), P(int, module_len)))
1341{ 1341{
1342 ast _ silence_cycles = 0; 1342 ast _ silence_cycles = 0;
1343 return parse_file(ast, ADDRESSOF ast _ module_info, filename, module, module_len); 1343 return parse_file(ast, ADDRESSOF ast _ module_info, filename, module, module_len);
1344} 1344}
1345 1345
1346FUNC(void, ASAP_DetectSilence, (P(ASAP_State PTR, ast), P(int, seconds))) 1346FUNC(void, ASAP_DetectSilence, (P(ASAP_State PTR, ast), P(int, seconds)))
1347{ 1347{
1348 ast _ silence_cycles = seconds * ASAP_MAIN_CLOCK; 1348 ast _ silence_cycles = seconds * ASAP_MAIN_CLOCK;
1349} 1349}
1350 1350
1351PRIVATE FUNC(void, call_6502, (P(ASAP_State PTR, ast), P(int, addr), P(int, max_scanlines))) 1351PRIVATE FUNC(void, call_6502, (P(ASAP_State PTR, ast), P(int, addr), P(int, max_scanlines)))
1352{ 1352{
1353 ast _ cpu_pc = addr; 1353 ast _ cpu_pc = addr;
1354 /* put a CIM at 0xd20a and a return address on stack */ 1354 /* put a CIM at 0xd20a and a return address on stack */
1355 dPutByte(0xd20a, 0xd2); 1355 dPutByte(0xd20a, 0xd2);
1356 dPutByte(0x01fe, 0x09); 1356 dPutByte(0x01fe, 0x09);
1357 dPutByte(0x01ff, 0xd2); 1357 dPutByte(0x01ff, 0xd2);
1358 ast _ cpu_s = 0xfd; 1358 ast _ cpu_s = 0xfd;
1359 Cpu_RunScanlines(ast, max_scanlines); 1359 Cpu_RunScanlines(ast, max_scanlines);
1360} 1360}
1361 1361
1362/* 50 Atari frames for the initialization routine - some SAPs are self-extracting. */ 1362/* 50 Atari frames for the initialization routine - some SAPs are self-extracting. */
@@ -1364,843 +1364,843 @@ PRIVATE FUNC(void, call_6502, (P(ASAP_State PTR, ast), P(int, addr), P(int, max_
1364 1364
1365PRIVATE FUNC(void, call_6502_init, (P(ASAP_State PTR, ast), P(int, addr), P(int, a), P(int, x), P(int, y))) 1365PRIVATE FUNC(void, call_6502_init, (P(ASAP_State PTR, ast), P(int, addr), P(int, a), P(int, x), P(int, y)))
1366{ 1366{
1367 ast _ cpu_a = a & 0xff; 1367 ast _ cpu_a = a & 0xff;
1368 ast _ cpu_x = x & 0xff; 1368 ast _ cpu_x = x & 0xff;
1369 ast _ cpu_y = y & 0xff; 1369 ast _ cpu_y = y & 0xff;
1370 call_6502(ast, addr, SCANLINES_FOR_INIT); 1370 call_6502(ast, addr, SCANLINES_FOR_INIT);
1371} 1371}
1372 1372
1373FUNC(void, ASAP_PlaySong, (P(ASAP_State PTR, ast), P(int, song), P(int, duration))) 1373FUNC(void, ASAP_PlaySong, (P(ASAP_State PTR, ast), P(int, song), P(int, duration)))
1374{ 1374{
1375 ast _ current_song = song; 1375 ast _ current_song = song;
1376 ast _ current_duration = duration; 1376 ast _ current_duration = duration;
1377 ast _ blocks_played = 0; 1377 ast _ blocks_played = 0;
1378 ast _ silence_cycles_counter = ast _ silence_cycles; 1378 ast _ silence_cycles_counter = ast _ silence_cycles;
1379 ast _ extra_pokey_mask = ast _ module_info.channels > 1 ? 0x10 : 0; 1379 ast _ extra_pokey_mask = ast _ module_info.channels > 1 ? 0x10 : 0;
1380 ast _ consol = 8; 1380 ast _ consol = 8;
1381 ast _ covox[0] = CAST(byte) 0x80; 1381 ast _ covox[0] = CAST(byte) 0x80;
1382 ast _ covox[1] = CAST(byte) 0x80; 1382 ast _ covox[1] = CAST(byte) 0x80;
1383 ast _ covox[2] = CAST(byte) 0x80; 1383 ast _ covox[2] = CAST(byte) 0x80;
1384 ast _ covox[3] = CAST(byte) 0x80; 1384 ast _ covox[3] = CAST(byte) 0x80;
1385 PokeySound_Initialize(ast); 1385 PokeySound_Initialize(ast);
1386 ast _ cycle = 0; 1386 ast _ cycle = 0;
1387 ast _ cpu_nz = 0; 1387 ast _ cpu_nz = 0;
1388 ast _ cpu_c = 0; 1388 ast _ cpu_c = 0;
1389 ast _ cpu_vdi = 0; 1389 ast _ cpu_vdi = 0;
1390 ast _ scanline_number = 0; 1390 ast _ scanline_number = 0;
1391 ast _ next_scanline_cycle = 0; 1391 ast _ next_scanline_cycle = 0;
1392 ast _ timer1_cycle = NEVER; 1392 ast _ timer1_cycle = NEVER;
1393 ast _ timer2_cycle = NEVER; 1393 ast _ timer2_cycle = NEVER;
1394 ast _ timer4_cycle = NEVER; 1394 ast _ timer4_cycle = NEVER;
1395 ast _ irqst = 0xff; 1395 ast _ irqst = 0xff;
1396 switch (ast _ module_info.type) { 1396 switch (ast _ module_info.type) {
1397 case ASAP_TYPE_SAP_B: 1397 case ASAP_TYPE_SAP_B:
1398 call_6502_init(ast, ast _ module_info.init, song, 0, 0); 1398 call_6502_init(ast, ast _ module_info.init, song, 0, 0);
1399 break; 1399 break;
1400 case ASAP_TYPE_SAP_C: 1400 case ASAP_TYPE_SAP_C:
1401#ifndef ASAP_ONLY_SAP 1401#ifndef ASAP_ONLY_SAP
1402 case ASAP_TYPE_CMC: 1402 case ASAP_TYPE_CMC:
1403 case ASAP_TYPE_CM3: 1403 case ASAP_TYPE_CM3:
1404 case ASAP_TYPE_CMR: 1404 case ASAP_TYPE_CMR:
1405 case ASAP_TYPE_CMS: 1405 case ASAP_TYPE_CMS:
1406#endif 1406#endif
1407 call_6502_init(ast, ast _ module_info.player + 3, 0x70, ast _ module_info.music, ast _ module_info.music >> 8); 1407 call_6502_init(ast, ast _ module_info.player + 3, 0x70, ast _ module_info.music, ast _ module_info.music >> 8);
1408 call_6502_init(ast, ast _ module_info.player + 3, 0x00, song, 0); 1408 call_6502_init(ast, ast _ module_info.player + 3, 0x00, song, 0);
1409 break; 1409 break;
1410 case ASAP_TYPE_SAP_D: 1410 case ASAP_TYPE_SAP_D:
1411 case ASAP_TYPE_SAP_S: 1411 case ASAP_TYPE_SAP_S:
1412 ast _ cpu_a = song; 1412 ast _ cpu_a = song;
1413 ast _ cpu_x = 0x00; 1413 ast _ cpu_x = 0x00;
1414 ast _ cpu_y = 0x00; 1414 ast _ cpu_y = 0x00;
1415 ast _ cpu_s = 0xff; 1415 ast _ cpu_s = 0xff;
1416 ast _ cpu_pc = ast _ module_info.init; 1416 ast _ cpu_pc = ast _ module_info.init;
1417 break; 1417 break;
1418#ifndef ASAP_ONLY_SAP 1418#ifndef ASAP_ONLY_SAP
1419 case ASAP_TYPE_DLT: 1419 case ASAP_TYPE_DLT:
1420 call_6502_init(ast, ast _ module_info.player + 0x100, 0x00, 0x00, ast _ module_info.song_pos[song]); 1420 call_6502_init(ast, ast _ module_info.player + 0x100, 0x00, 0x00, ast _ module_info.song_pos[song]);
1421 break; 1421 break;
1422 case ASAP_TYPE_MPT: 1422 case ASAP_TYPE_MPT:
1423 call_6502_init(ast, ast _ module_info.player, 0x00, ast _ module_info.music >> 8, ast _ module_info.music); 1423 call_6502_init(ast, ast _ module_info.player, 0x00, ast _ module_info.music >> 8, ast _ module_info.music);
1424 call_6502_init(ast, ast _ module_info.player, 0x02, ast _ module_info.song_pos[song], 0); 1424 call_6502_init(ast, ast _ module_info.player, 0x02, ast _ module_info.song_pos[song], 0);
1425 break; 1425 break;
1426 case ASAP_TYPE_RMT: 1426 case ASAP_TYPE_RMT:
1427 call_6502_init(ast, ast _ module_info.player, ast _ module_info.song_pos[song], ast _ module_info.music, ast _ module_info.music >> 8); 1427 call_6502_init(ast, ast _ module_info.player, ast _ module_info.song_pos[song], ast _ module_info.music, ast _ module_info.music >> 8);
1428 break; 1428 break;
1429 case ASAP_TYPE_TMC: 1429 case ASAP_TYPE_TMC:
1430 case ASAP_TYPE_TM2: 1430 case ASAP_TYPE_TM2:
1431 call_6502_init(ast, ast _ module_info.player, 0x70, ast _ module_info.music >> 8, ast _ module_info.music); 1431 call_6502_init(ast, ast _ module_info.player, 0x70, ast _ module_info.music >> 8, ast _ module_info.music);
1432 call_6502_init(ast, ast _ module_info.player, 0x00, song, 0); 1432 call_6502_init(ast, ast _ module_info.player, 0x00, song, 0);
1433 ast _ tmc_per_frame_counter = 1; 1433 ast _ tmc_per_frame_counter = 1;
1434 break; 1434 break;
1435#endif 1435#endif
1436 } 1436 }
1437 ASAP_MutePokeyChannels(ast, 0); 1437 ASAP_MutePokeyChannels(ast, 0);
1438} 1438}
1439 1439
1440FUNC(void, ASAP_MutePokeyChannels, (P(ASAP_State PTR, ast), P(int, mask))) 1440FUNC(void, ASAP_MutePokeyChannels, (P(ASAP_State PTR, ast), P(int, mask)))
1441{ 1441{
1442 PokeySound_Mute(ast, ADDRESSOF ast _ base_pokey, mask); 1442 PokeySound_Mute(ast, ADDRESSOF ast _ base_pokey, mask);
1443 PokeySound_Mute(ast, ADDRESSOF ast _ extra_pokey, mask >> 4); 1443 PokeySound_Mute(ast, ADDRESSOF ast _ extra_pokey, mask >> 4);
1444} 1444}
1445 1445
1446FUNC(abool, call_6502_player, (P(ASAP_State PTR, ast))) 1446FUNC(abool, call_6502_player, (P(ASAP_State PTR, ast)))
1447{ 1447{
1448 V(int, player) = ast _ module_info.player; 1448 V(int, player) = ast _ module_info.player;
1449 PokeySound_StartFrame(ast); 1449 PokeySound_StartFrame(ast);
1450 switch (ast _ module_info.type) { 1450 switch (ast _ module_info.type) {
1451 case ASAP_TYPE_SAP_B: 1451 case ASAP_TYPE_SAP_B:
1452 call_6502(ast, player, ast _ module_info.fastplay); 1452 call_6502(ast, player, ast _ module_info.fastplay);
1453 break; 1453 break;
1454 case ASAP_TYPE_SAP_C: 1454 case ASAP_TYPE_SAP_C:
1455#ifndef ASAP_ONLY_SAP 1455#ifndef ASAP_ONLY_SAP
1456 case ASAP_TYPE_CMC: 1456 case ASAP_TYPE_CMC:
1457 case ASAP_TYPE_CM3: 1457 case ASAP_TYPE_CM3:
1458 case ASAP_TYPE_CMR: 1458 case ASAP_TYPE_CMR:
1459 case ASAP_TYPE_CMS: 1459 case ASAP_TYPE_CMS:
1460#endif 1460#endif
1461 call_6502(ast, player + 6, ast _ module_info.fastplay); 1461 call_6502(ast, player + 6, ast _ module_info.fastplay);
1462 break; 1462 break;
1463 case ASAP_TYPE_SAP_D: 1463 case ASAP_TYPE_SAP_D:
1464 if (player >= 0) { 1464 if (player >= 0) {
1465 V(int, s)= ast _ cpu_s; 1465 V(int, s)= ast _ cpu_s;
1466#define PUSH_ON_6502_STACK(x) dPutByte(0x100 + s, x); s = (s - 1) & 0xff 1466#define PUSH_ON_6502_STACK(x) dPutByte(0x100 + s, x); s = (s - 1) & 0xff
1467#define RETURN_FROM_PLAYER_ADDR 0xd200 1467#define RETURN_FROM_PLAYER_ADDR 0xd200
1468 /* save 6502 state on 6502 stack */ 1468 /* save 6502 state on 6502 stack */
1469 PUSH_ON_6502_STACK(ast _ cpu_pc >> 8); 1469 PUSH_ON_6502_STACK(ast _ cpu_pc >> 8);
1470 PUSH_ON_6502_STACK(ast _ cpu_pc & 0xff); 1470 PUSH_ON_6502_STACK(ast _ cpu_pc & 0xff);
1471 PUSH_ON_6502_STACK(((ast _ cpu_nz | (ast _ cpu_nz >> 1)) & 0x80) + ast _ cpu_vdi + \ 1471 PUSH_ON_6502_STACK(((ast _ cpu_nz | (ast _ cpu_nz >> 1)) & 0x80) + ast _ cpu_vdi + \
1472 ((ast _ cpu_nz & 0xff) == 0 ? Z_FLAG : 0) + ast _ cpu_c + 0x20); 1472 ((ast _ cpu_nz & 0xff) == 0 ? Z_FLAG : 0) + ast _ cpu_c + 0x20);
1473 PUSH_ON_6502_STACK(ast _ cpu_a); 1473 PUSH_ON_6502_STACK(ast _ cpu_a);
1474 PUSH_ON_6502_STACK(ast _ cpu_x); 1474 PUSH_ON_6502_STACK(ast _ cpu_x);
1475 PUSH_ON_6502_STACK(ast _ cpu_y); 1475 PUSH_ON_6502_STACK(ast _ cpu_y);
1476 /* RTS will jump to 6502 code that restores the state */ 1476 /* RTS will jump to 6502 code that restores the state */
1477 PUSH_ON_6502_STACK((RETURN_FROM_PLAYER_ADDR - 1) >> 8); 1477 PUSH_ON_6502_STACK((RETURN_FROM_PLAYER_ADDR - 1) >> 8);
1478 PUSH_ON_6502_STACK((RETURN_FROM_PLAYER_ADDR - 1) & 0xff); 1478 PUSH_ON_6502_STACK((RETURN_FROM_PLAYER_ADDR - 1) & 0xff);
1479 ast _ cpu_s = s; 1479 ast _ cpu_s = s;
1480 dPutByte(RETURN_FROM_PLAYER_ADDR, 0x68); /* PLA */ 1480 dPutByte(RETURN_FROM_PLAYER_ADDR, 0x68); /* PLA */
1481 dPutByte(RETURN_FROM_PLAYER_ADDR + 1, 0xa8); /* TAY */ 1481 dPutByte(RETURN_FROM_PLAYER_ADDR + 1, 0xa8); /* TAY */
1482 dPutByte(RETURN_FROM_PLAYER_ADDR + 2, 0x68); /* PLA */ 1482 dPutByte(RETURN_FROM_PLAYER_ADDR + 2, 0x68); /* PLA */
1483 dPutByte(RETURN_FROM_PLAYER_ADDR + 3, 0xaa); /* TAX */ 1483 dPutByte(RETURN_FROM_PLAYER_ADDR + 3, 0xaa); /* TAX */
1484 dPutByte(RETURN_FROM_PLAYER_ADDR + 4, 0x68); /* PLA */ 1484 dPutByte(RETURN_FROM_PLAYER_ADDR + 4, 0x68); /* PLA */
1485 dPutByte(RETURN_FROM_PLAYER_ADDR + 5, 0x40); /* RTI */ 1485 dPutByte(RETURN_FROM_PLAYER_ADDR + 5, 0x40); /* RTI */
1486 ast _ cpu_pc = player; 1486 ast _ cpu_pc = player;
1487 } 1487 }
1488 Cpu_RunScanlines(ast, ast _ module_info.fastplay); 1488 Cpu_RunScanlines(ast, ast _ module_info.fastplay);
1489 break; 1489 break;
1490 case ASAP_TYPE_SAP_S: 1490 case ASAP_TYPE_SAP_S:
1491 Cpu_RunScanlines(ast, ast _ module_info.fastplay); 1491 Cpu_RunScanlines(ast, ast _ module_info.fastplay);
1492 { 1492 {
1493 V(int, i) = dGetByte(0x45) - 1; 1493 V(int, i) = dGetByte(0x45) - 1;
1494 dPutByte(0x45, i); 1494 dPutByte(0x45, i);
1495 if (i == 0) 1495 if (i == 0)
1496 dPutByte(0xb07b, dGetByte(0xb07b) + 1); 1496 dPutByte(0xb07b, dGetByte(0xb07b) + 1);
1497 } 1497 }
1498 break; 1498 break;
1499#ifndef ASAP_ONLY_SAP 1499#ifndef ASAP_ONLY_SAP
1500 case ASAP_TYPE_DLT: 1500 case ASAP_TYPE_DLT:
1501 call_6502(ast, player + 0x103, ast _ module_info.fastplay); 1501 call_6502(ast, player + 0x103, ast _ module_info.fastplay);
1502 break; 1502 break;
1503 case ASAP_TYPE_MPT: 1503 case ASAP_TYPE_MPT:
1504 case ASAP_TYPE_RMT: 1504 case ASAP_TYPE_RMT:
1505 case ASAP_TYPE_TM2: 1505 case ASAP_TYPE_TM2:
1506 call_6502(ast, player + 3, ast _ module_info.fastplay); 1506 call_6502(ast, player + 3, ast _ module_info.fastplay);
1507 break; 1507 break;
1508 case ASAP_TYPE_TMC: 1508 case ASAP_TYPE_TMC:
1509 if (--ast _ tmc_per_frame_counter <= 0) { 1509 if (--ast _ tmc_per_frame_counter <= 0) {
1510 ast _ tmc_per_frame_counter = ast _ tmc_per_frame; 1510 ast _ tmc_per_frame_counter = ast _ tmc_per_frame;
1511 call_6502(ast, player + 3, ast _ module_info.fastplay); 1511 call_6502(ast, player + 3, ast _ module_info.fastplay);
1512 } 1512 }
1513 else 1513 else
1514 call_6502(ast, player + 6, ast _ module_info.fastplay); 1514 call_6502(ast, player + 6, ast _ module_info.fastplay);
1515 break; 1515 break;
1516#endif 1516#endif
1517 } 1517 }
1518 PokeySound_EndFrame(ast, ast _ module_info.fastplay * 114); 1518 PokeySound_EndFrame(ast, ast _ module_info.fastplay * 114);
1519 if (ast _ silence_cycles > 0) { 1519 if (ast _ silence_cycles > 0) {
1520 if (PokeySound_IsSilent(ADDRESSOF ast _ base_pokey) 1520 if (PokeySound_IsSilent(ADDRESSOF ast _ base_pokey)
1521 && PokeySound_IsSilent(ADDRESSOF ast _ extra_pokey)) { 1521 && PokeySound_IsSilent(ADDRESSOF ast _ extra_pokey)) {
1522 ast _ silence_cycles_counter -= ast _ module_info.fastplay * 114; 1522 ast _ silence_cycles_counter -= ast _ module_info.fastplay * 114;
1523 if (ast _ silence_cycles_counter <= 0) 1523 if (ast _ silence_cycles_counter <= 0)
1524 return FALSE; 1524 return FALSE;
1525 } 1525 }
1526 else 1526 else
1527 ast _ silence_cycles_counter = ast _ silence_cycles; 1527 ast _ silence_cycles_counter = ast _ silence_cycles;
1528 } 1528 }
1529 return TRUE; 1529 return TRUE;
1530} 1530}
1531 1531
1532FUNC(int, ASAP_GetPosition, (P(CONST ASAP_State PTR, ast))) 1532FUNC(int, ASAP_GetPosition, (P(CONST ASAP_State PTR, ast)))
1533{ 1533{
1534 return ast _ blocks_played * 10 / (ASAP_SAMPLE_RATE / 100); 1534 return ast _ blocks_played * 10 / (ASAP_SAMPLE_RATE / 100);
1535} 1535}
1536 1536
1537FUNC(int, milliseconds_to_blocks, (P(int, milliseconds))) 1537FUNC(int, milliseconds_to_blocks, (P(int, milliseconds)))
1538{ 1538{
1539 return milliseconds * (ASAP_SAMPLE_RATE / 100) / 10; 1539 return milliseconds * (ASAP_SAMPLE_RATE / 100) / 10;
1540} 1540}
1541 1541
1542#ifndef ACTIONSCRIPT 1542#ifndef ACTIONSCRIPT
1543 1543
1544FUNC(void, ASAP_Seek, (P(ASAP_State PTR, ast), P(int, position))) 1544FUNC(void, ASAP_Seek, (P(ASAP_State PTR, ast), P(int, position)))
1545{ 1545{
1546 V(int, block) = milliseconds_to_blocks(position); 1546 V(int, block) = milliseconds_to_blocks(position);
1547 if (block < ast _ blocks_played) 1547 if (block < ast _ blocks_played)
1548 ASAP_PlaySong(ast, ast _ current_song, ast _ current_duration); 1548 ASAP_PlaySong(ast, ast _ current_song, ast _ current_duration);
1549 while (ast _ blocks_played + ast _ samples - ast _ sample_index < block) { 1549 while (ast _ blocks_played + ast _ samples - ast _ sample_index < block) {
1550 ast _ blocks_played += ast _ samples - ast _ sample_index; 1550 ast _ blocks_played += ast _ samples - ast _ sample_index;
1551 call_6502_player(ast); 1551 call_6502_player(ast);
1552 } 1552 }
1553 ast _ sample_index += block - ast _ blocks_played; 1553 ast _ sample_index += block - ast _ blocks_played;
1554 ast _ blocks_played = block; 1554 ast _ blocks_played = block;
1555} 1555}
1556 1556
1557PRIVATE FUNC(void, serialize_int, (P(BYTEARRAY, buffer), P(int, offset), P(int, value))) 1557PRIVATE FUNC(void, serialize_int, (P(BYTEARRAY, buffer), P(int, offset), P(int, value)))
1558{ 1558{
1559 buffer[offset] = TO_BYTE(value); 1559 buffer[offset] = TO_BYTE(value);
1560 buffer[offset + 1] = TO_BYTE(value >> 8); 1560 buffer[offset + 1] = TO_BYTE(value >> 8);
1561 buffer[offset + 2] = TO_BYTE(value >> 16); 1561 buffer[offset + 2] = TO_BYTE(value >> 16);
1562 buffer[offset + 3] = TO_BYTE(value >> 24); 1562 buffer[offset + 3] = TO_BYTE(value >> 24);
1563} 1563}
1564 1564
1565FUNC(void, ASAP_GetWavHeaderForPart, ( 1565FUNC(void, ASAP_GetWavHeaderForPart, (
1566 P(CONST ASAP_State PTR, ast), P(BYTEARRAY, buffer), 1566 P(CONST ASAP_State PTR, ast), P(BYTEARRAY, buffer),
1567 P(ASAP_SampleFormat, format), P(int, blocks))) 1567 P(ASAP_SampleFormat, format), P(int, blocks)))
1568{ 1568{
1569 V(int, use_16bit) = format != ASAP_FORMAT_U8 ? 1 : 0; 1569 V(int, use_16bit) = format != ASAP_FORMAT_U8 ? 1 : 0;
1570 V(int, block_size) = ast _ module_info.channels << use_16bit; 1570 V(int, block_size) = ast _ module_info.channels << use_16bit;
1571 V(int, bytes_per_second) = ASAP_SAMPLE_RATE * block_size; 1571 V(int, bytes_per_second) = ASAP_SAMPLE_RATE * block_size;
1572 V(int, remaining_blocks) = milliseconds_to_blocks(ast _ current_duration) - ast _ blocks_played; 1572 V(int, remaining_blocks) = milliseconds_to_blocks(ast _ current_duration) - ast _ blocks_played;
1573 V(int, n_bytes); 1573 V(int, n_bytes);
1574 if (blocks > remaining_blocks) 1574 if (blocks > remaining_blocks)
1575 blocks = remaining_blocks; 1575 blocks = remaining_blocks;
1576 n_bytes = blocks * block_size; 1576 n_bytes = blocks * block_size;
1577 buffer[0] = CAST(byte) CHARCODE('R'); 1577 buffer[0] = CAST(byte) CHARCODE('R');
1578 buffer[1] = CAST(byte) CHARCODE('I'); 1578 buffer[1] = CAST(byte) CHARCODE('I');
1579 buffer[2] = CAST(byte) CHARCODE('F'); 1579 buffer[2] = CAST(byte) CHARCODE('F');
1580 buffer[3] = CAST(byte) CHARCODE('F'); 1580 buffer[3] = CAST(byte) CHARCODE('F');
1581 serialize_int(buffer, 4, n_bytes + 36); 1581 serialize_int(buffer, 4, n_bytes + 36);
1582 buffer[8] = CAST(byte) CHARCODE('W'); 1582 buffer[8] = CAST(byte) CHARCODE('W');
1583 buffer[9] = CAST(byte) CHARCODE('A'); 1583 buffer[9] = CAST(byte) CHARCODE('A');
1584 buffer[10] = CAST(byte) CHARCODE('V'); 1584 buffer[10] = CAST(byte) CHARCODE('V');
1585 buffer[11] = CAST(byte) CHARCODE('E'); 1585 buffer[11] = CAST(byte) CHARCODE('E');
1586 buffer[12] = CAST(byte) CHARCODE('f'); 1586 buffer[12] = CAST(byte) CHARCODE('f');
1587 buffer[13] = CAST(byte) CHARCODE('m'); 1587 buffer[13] = CAST(byte) CHARCODE('m');
1588 buffer[14] = CAST(byte) CHARCODE('t'); 1588 buffer[14] = CAST(byte) CHARCODE('t');
1589 buffer[15] = CAST(byte) CHARCODE(' '); 1589 buffer[15] = CAST(byte) CHARCODE(' ');
1590 buffer[16] = 16; 1590 buffer[16] = 16;
1591 buffer[17] = 0; 1591 buffer[17] = 0;
1592 buffer[18] = 0; 1592 buffer[18] = 0;
1593 buffer[19] = 0; 1593 buffer[19] = 0;
1594 buffer[20] = 1; 1594 buffer[20] = 1;
1595 buffer[21] = 0; 1595 buffer[21] = 0;
1596 buffer[22] = CAST(byte) ast _ module_info.channels; 1596 buffer[22] = CAST(byte) ast _ module_info.channels;
1597 buffer[23] = 0; 1597 buffer[23] = 0;
1598 serialize_int(buffer, 24, ASAP_SAMPLE_RATE); 1598 serialize_int(buffer, 24, ASAP_SAMPLE_RATE);
1599 serialize_int(buffer, 28, bytes_per_second); 1599 serialize_int(buffer, 28, bytes_per_second);
1600 buffer[32] = CAST(byte) block_size; 1600 buffer[32] = CAST(byte) block_size;
1601 buffer[33] = 0; 1601 buffer[33] = 0;
1602 buffer[34] = CAST(byte) (8 << use_16bit); 1602 buffer[34] = CAST(byte) (8 << use_16bit);
1603 buffer[35] = 0; 1603 buffer[35] = 0;
1604 buffer[36] = CAST(byte) CHARCODE('d'); 1604 buffer[36] = CAST(byte) CHARCODE('d');
1605 buffer[37] = CAST(byte) CHARCODE('a'); 1605 buffer[37] = CAST(byte) CHARCODE('a');
1606 buffer[38] = CAST(byte) CHARCODE('t'); 1606 buffer[38] = CAST(byte) CHARCODE('t');
1607 buffer[39] = CAST(byte) CHARCODE('a'); 1607 buffer[39] = CAST(byte) CHARCODE('a');
1608 serialize_int(buffer, 40, n_bytes); 1608 serialize_int(buffer, 40, n_bytes);
1609} 1609}
1610 1610
1611FUNC(void, ASAP_GetWavHeader, ( 1611FUNC(void, ASAP_GetWavHeader, (
1612 P(CONST ASAP_State PTR, ast), P(BYTEARRAY, buffer), P(ASAP_SampleFormat, format))) 1612 P(CONST ASAP_State PTR, ast), P(BYTEARRAY, buffer), P(ASAP_SampleFormat, format)))
1613{ 1613{
1614 V(int, remaining_blocks) = milliseconds_to_blocks(ast _ current_duration) - ast _ blocks_played; 1614 V(int, remaining_blocks) = milliseconds_to_blocks(ast _ current_duration) - ast _ blocks_played;
1615 ASAP_GetWavHeaderForPart(ast, buffer, format, remaining_blocks); 1615 ASAP_GetWavHeaderForPart(ast, buffer, format, remaining_blocks);
1616} 1616}
1617 1617
1618#endif /* ACTIONSCRIPT */ 1618#endif /* ACTIONSCRIPT */
1619 1619
1620PRIVATE FUNC(int, ASAP_GenerateAt, (P(ASAP_State PTR, ast), P(VOIDPTR, buffer), P(int, buffer_offset), P(int, buffer_len), P(ASAP_SampleFormat, format))) 1620PRIVATE FUNC(int, ASAP_GenerateAt, (P(ASAP_State PTR, ast), P(VOIDPTR, buffer), P(int, buffer_offset), P(int, buffer_len), P(ASAP_SampleFormat, format)))
1621{ 1621{
1622 V(int, block_shift); 1622 V(int, block_shift);
1623 V(int, buffer_blocks); 1623 V(int, buffer_blocks);
1624 V(int, block); 1624 V(int, block);
1625 if (ast _ silence_cycles > 0 && ast _ silence_cycles_counter <= 0) 1625 if (ast _ silence_cycles > 0 && ast _ silence_cycles_counter <= 0)
1626 return 0; 1626 return 0;
1627#ifdef ACTIONSCRIPT 1627#ifdef ACTIONSCRIPT
1628 block_shift = 0; 1628 block_shift = 0;
1629#else 1629#else
1630 block_shift = (ast _ module_info.channels - 1) + (format != ASAP_FORMAT_U8 ? 1 : 0); 1630 block_shift = (ast _ module_info.channels - 1) + (format != ASAP_FORMAT_U8 ? 1 : 0);
1631#endif 1631#endif
1632 buffer_blocks = buffer_len >> block_shift; 1632 buffer_blocks = buffer_len >> block_shift;
1633 if (ast _ current_duration > 0) { 1633 if (ast _ current_duration > 0) {
1634 V(int, total_blocks) = milliseconds_to_blocks(ast _ current_duration); 1634 V(int, total_blocks) = milliseconds_to_blocks(ast _ current_duration);
1635 if (buffer_blocks > total_blocks - ast _ blocks_played) 1635 if (buffer_blocks > total_blocks - ast _ blocks_played)
1636 buffer_blocks = total_blocks - ast _ blocks_played; 1636 buffer_blocks = total_blocks - ast _ blocks_played;
1637 } 1637 }
1638 block = 0; 1638 block = 0;
1639 do { 1639 do {
1640 V(int, blocks) = PokeySound_Generate(ast, CAST(BYTEARRAY) buffer, 1640 V(int, blocks) = PokeySound_Generate(ast, CAST(BYTEARRAY) buffer,
1641 buffer_offset + (block << block_shift), buffer_blocks - block, format); 1641 buffer_offset + (block << block_shift), buffer_blocks - block, format);
1642 ast _ blocks_played += blocks; 1642 ast _ blocks_played += blocks;
1643 block += blocks; 1643 block += blocks;
1644 } while (block < buffer_blocks && call_6502_player(ast)); 1644 } while (block < buffer_blocks && call_6502_player(ast));
1645 return block << block_shift; 1645 return block << block_shift;
1646} 1646}
1647 1647
1648FUNC(int, ASAP_Generate, (P(ASAP_State PTR, ast), P(VOIDPTR, buffer), P(int, buffer_len), P(ASAP_SampleFormat, format))) 1648FUNC(int, ASAP_Generate, (P(ASAP_State PTR, ast), P(VOIDPTR, buffer), P(int, buffer_len), P(ASAP_SampleFormat, format)))
1649{ 1649{
1650 return ASAP_GenerateAt(ast, buffer, 0, buffer_len, format); 1650 return ASAP_GenerateAt(ast, buffer, 0, buffer_len, format);
1651} 1651}
1652 1652
1653#if defined(C) && !defined(ASAP_ONLY_SAP) 1653#if defined(C) && !defined(ASAP_ONLY_SAP)
1654 1654
1655abool ASAP_ChangeExt(char *filename, const char *ext) 1655abool ASAP_ChangeExt(char *filename, const char *ext)
1656{ 1656{
1657 char *dest = NULL; 1657 char *dest = NULL;
1658 while (*filename != '\0') { 1658 while (*filename != '\0') {
1659 if (*filename == '/' || *filename == '\\') 1659 if (*filename == '/' || *filename == '\\')
1660 dest = NULL; 1660 dest = NULL;
1661 else if (*filename == '.') 1661 else if (*filename == '.')
1662 dest = filename + 1; 1662 dest = filename + 1;
1663 filename++; 1663 filename++;
1664 } 1664 }
1665 if (dest == NULL) 1665 if (dest == NULL)
1666 return FALSE; 1666 return FALSE;
1667 strcpy(dest, ext); 1667 strcpy(dest, ext);
1668 return TRUE; 1668 return TRUE;
1669} 1669}
1670 1670
1671abool ASAP_CanSetModuleInfo(const char *filename) 1671abool ASAP_CanSetModuleInfo(const char *filename)
1672{ 1672{
1673 int ext = get_packed_ext(filename); 1673 int ext = get_packed_ext(filename);
1674 return ext == ASAP_EXT('S', 'A', 'P'); 1674 return ext == ASAP_EXT('S', 'A', 'P');
1675} 1675}
1676 1676
1677static byte *put_string(byte *dest, const char *str) 1677static byte *put_string(byte *dest, const char *str)
1678{ 1678{
1679 while (*str != '\0') 1679 while (*str != '\0')
1680 *dest++ = *str++; 1680 *dest++ = *str++;
1681 return dest; 1681 return dest;
1682} 1682}
1683 1683
1684static byte *put_dec(byte *dest, int value) 1684static byte *put_dec(byte *dest, int value)
1685{ 1685{
1686 if (value >= 10) { 1686 if (value >= 10) {
1687 dest = put_dec(dest, value / 10); 1687 dest = put_dec(dest, value / 10);
1688 value %= 10; 1688 value %= 10;
1689 } 1689 }
1690 *dest++ = '0' + value; 1690 *dest++ = '0' + value;
1691 return dest; 1691 return dest;
1692} 1692}
1693 1693
1694static byte *put_text_tag(byte *dest, const char *tag, const char *value) 1694static byte *put_text_tag(byte *dest, const char *tag, const char *value)
1695{ 1695{
1696 dest = put_string(dest, tag); 1696 dest = put_string(dest, tag);
1697 *dest++ = '"'; 1697 *dest++ = '"';
1698 if (*value == '\0') 1698 if (*value == '\0')
1699 value = "<?>"; 1699 value = "<?>";
1700 while (*value != '\0') { 1700 while (*value != '\0') {
1701 if (*value < ' ' || *value > 'z' || *value == '"' || *value == '`') 1701 if (*value < ' ' || *value > 'z' || *value == '"' || *value == '`')
1702 return NULL; 1702 return NULL;
1703 *dest++ = *value++; 1703 *dest++ = *value++;
1704 } 1704 }
1705 *dest++ = '"'; 1705 *dest++ = '"';
1706 *dest++ = '\r'; 1706 *dest++ = '\r';
1707 *dest++ = '\n'; 1707 *dest++ = '\n';
1708 return dest; 1708 return dest;
1709} 1709}
1710 1710
1711static byte *put_dec_tag(byte *dest, const char *tag, int value) 1711static byte *put_dec_tag(byte *dest, const char *tag, int value)
1712{ 1712{
1713 dest = put_string(dest, tag); 1713 dest = put_string(dest, tag);
1714 dest = put_dec(dest, value); 1714 dest = put_dec(dest, value);
1715 *dest++ = '\r'; 1715 *dest++ = '\r';
1716 *dest++ = '\n'; 1716 *dest++ = '\n';
1717 return dest; 1717 return dest;
1718} 1718}
1719 1719
1720static byte *put_hex_tag(byte *dest, const char *tag, int value) 1720static byte *put_hex_tag(byte *dest, const char *tag, int value)
1721{ 1721{
1722 int i; 1722 int i;
1723 if (value < 0) 1723 if (value < 0)
1724 return dest; 1724 return dest;
1725 dest = put_string(dest, tag); 1725 dest = put_string(dest, tag);
1726 for (i = 12; i >= 0; i -= 4) { 1726 for (i = 12; i >= 0; i -= 4) {
1727 int digit = (value >> i) & 0xf; 1727 int digit = (value >> i) & 0xf;
1728 *dest++ = (byte) (digit + (digit < 10 ? '0' : 'A' - 10)); 1728 *dest++ = (byte) (digit + (digit < 10 ? '0' : 'A' - 10));
1729 } 1729 }
1730 *dest++ = '\r'; 1730 *dest++ = '\r';
1731 *dest++ = '\n'; 1731 *dest++ = '\n';
1732 return dest; 1732 return dest;
1733} 1733}
1734 1734
1735static byte *start_sap_header(byte *dest, const ASAP_ModuleInfo *module_info) 1735static byte *start_sap_header(byte *dest, const ASAP_ModuleInfo *module_info)
1736{ 1736{
1737 dest = put_string(dest, "SAP\r\n"); 1737 dest = put_string(dest, "SAP\r\n");
1738 dest = put_text_tag(dest, "AUTHOR ", module_info->author); 1738 dest = put_text_tag(dest, "AUTHOR ", module_info->author);
1739 if (dest == NULL) 1739 if (dest == NULL)
1740 return NULL; 1740 return NULL;
1741 dest = put_text_tag(dest, "NAME ", module_info->name); 1741 dest = put_text_tag(dest, "NAME ", module_info->name);
1742 if (dest == NULL) 1742 if (dest == NULL)
1743 return NULL; 1743 return NULL;
1744 dest = put_text_tag(dest, "DATE ", module_info->date); 1744 dest = put_text_tag(dest, "DATE ", module_info->date);
1745 if (dest == NULL) 1745 if (dest == NULL)
1746 return NULL; 1746 return NULL;
1747 if (module_info->songs > 1) { 1747 if (module_info->songs > 1) {
1748 dest = put_dec_tag(dest, "SONGS ", module_info->songs); 1748 dest = put_dec_tag(dest, "SONGS ", module_info->songs);
1749 if (module_info->default_song > 0) 1749 if (module_info->default_song > 0)
1750 dest = put_dec_tag(dest, "DEFSONG ", module_info->default_song); 1750 dest = put_dec_tag(dest, "DEFSONG ", module_info->default_song);
1751 } 1751 }
1752 if (module_info->channels > 1) 1752 if (module_info->channels > 1)
1753 dest = put_string(dest, "STEREO\r\n"); 1753 dest = put_string(dest, "STEREO\r\n");
1754 return dest; 1754 return dest;
1755} 1755}
1756 1756
1757static char *two_digits(char *s, int x) 1757static char *two_digits(char *s, int x)
1758{ 1758{
1759 s[0] = '0' + x / 10; 1759 s[0] = '0' + x / 10;
1760 s[1] = '0' + x % 10; 1760 s[1] = '0' + x % 10;
1761 return s + 2; 1761 return s + 2;
1762} 1762}
1763 1763
1764void ASAP_DurationToString(char *s, int duration) 1764void ASAP_DurationToString(char *s, int duration)
1765{ 1765{
1766 if (duration >= 0 && duration < 100 * 60 * 1000) { 1766 if (duration >= 0 && duration < 100 * 60 * 1000) {
1767 int seconds = duration / 1000; 1767 int seconds = duration / 1000;
1768 s = two_digits(s, seconds / 60); 1768 s = two_digits(s, seconds / 60);
1769 *s++ = ':'; 1769 *s++ = ':';
1770 s = two_digits(s, seconds % 60); 1770 s = two_digits(s, seconds % 60);
1771 duration %= 1000; 1771 duration %= 1000;
1772 if (duration != 0) { 1772 if (duration != 0) {
1773 *s++ = '.'; 1773 *s++ = '.';
1774 s = two_digits(s, duration / 10); 1774 s = two_digits(s, duration / 10);
1775 duration %= 10; 1775 duration %= 10;
1776 if (duration != 0) 1776 if (duration != 0)
1777 *s++ = '0' + duration; 1777 *s++ = '0' + duration;
1778 } 1778 }
1779 } 1779 }
1780 *s = '\0'; 1780 *s = '\0';
1781} 1781}
1782 1782
1783static byte *put_durations(byte *dest, const ASAP_ModuleInfo *module_info) 1783static byte *put_durations(byte *dest, const ASAP_ModuleInfo *module_info)
1784{ 1784{
1785 int song; 1785 int song;
1786 for (song = 0; song < module_info->songs; song++) { 1786 for (song = 0; song < module_info->songs; song++) {
1787 if (module_info->durations[song] < 0) 1787 if (module_info->durations[song] < 0)
1788 break; 1788 break;
1789 dest = put_string(dest, "TIME "); 1789 dest = put_string(dest, "TIME ");
1790 ASAP_DurationToString((char *) dest, module_info->durations[song]); 1790 ASAP_DurationToString((char *) dest, module_info->durations[song]);
1791 while (*dest != '\0') 1791 while (*dest != '\0')
1792 dest++; 1792 dest++;
1793 if (module_info->loops[song]) 1793 if (module_info->loops[song])
1794 dest = put_string(dest, " LOOP"); 1794 dest = put_string(dest, " LOOP");
1795 *dest++ = '\r'; 1795 *dest++ = '\r';
1796 *dest++ = '\n'; 1796 *dest++ = '\n';
1797 } 1797 }
1798 return dest; 1798 return dest;
1799} 1799}
1800 1800
1801static byte *put_sap_header(byte *dest, const ASAP_ModuleInfo *module_info, char type, int music, int init, int player) 1801static byte *put_sap_header(byte *dest, const ASAP_ModuleInfo *module_info, char type, int music, int init, int player)
1802{ 1802{
1803 dest = start_sap_header(dest, module_info); 1803 dest = start_sap_header(dest, module_info);
1804 if (dest == NULL) 1804 if (dest == NULL)
1805 return NULL; 1805 return NULL;
1806 dest = put_string(dest, "TYPE "); 1806 dest = put_string(dest, "TYPE ");
1807 *dest++ = type; 1807 *dest++ = type;
1808 *dest++ = '\r'; 1808 *dest++ = '\r';
1809 *dest++ = '\n'; 1809 *dest++ = '\n';
1810 if (module_info->fastplay != 312) 1810 if (module_info->fastplay != 312)
1811 dest = put_dec_tag(dest, "FASTPLAY ", module_info->fastplay); 1811 dest = put_dec_tag(dest, "FASTPLAY ", module_info->fastplay);
1812 dest = put_hex_tag(dest, "MUSIC ", music); 1812 dest = put_hex_tag(dest, "MUSIC ", music);
1813 dest = put_hex_tag(dest, "INIT ", init); 1813 dest = put_hex_tag(dest, "INIT ", init);
1814 dest = put_hex_tag(dest, "PLAYER ", player); 1814 dest = put_hex_tag(dest, "PLAYER ", player);
1815 dest = put_durations(dest, module_info); 1815 dest = put_durations(dest, module_info);
1816 return dest; 1816 return dest;
1817} 1817}
1818 1818
1819int ASAP_SetModuleInfo(const ASAP_ModuleInfo *module_info, const BYTEARRAY module, int module_len, BYTEARRAY out_module) 1819int ASAP_SetModuleInfo(const ASAP_ModuleInfo *module_info, const BYTEARRAY module, int module_len, BYTEARRAY out_module)
1820{ 1820{
1821 byte *dest; 1821 byte *dest;
1822 int i; 1822 int i;
1823 if (memcmp(module, "SAP\r\n", 5) != 0) 1823 if (memcmp(module, "SAP\r\n", 5) != 0)
1824 return -1; 1824 return -1;
1825 dest = start_sap_header(out_module, module_info); 1825 dest = start_sap_header(out_module, module_info);
1826 if (dest == NULL) 1826 if (dest == NULL)
1827 return -1; 1827 return -1;
1828 i = 5; 1828 i = 5;
1829 while (i < module_len && module[i] != 0xff) { 1829 while (i < module_len && module[i] != 0xff) {
1830 if (memcmp(module + i, "AUTHOR ", 7) == 0 1830 if (memcmp(module + i, "AUTHOR ", 7) == 0
1831 || memcmp(module + i, "NAME ", 5) == 0 1831 || memcmp(module + i, "NAME ", 5) == 0
1832 || memcmp(module + i, "DATE ", 5) == 0 1832 || memcmp(module + i, "DATE ", 5) == 0
1833 || memcmp(module + i, "SONGS ", 6) == 0 1833 || memcmp(module + i, "SONGS ", 6) == 0
1834 || memcmp(module + i, "DEFSONG ", 8) == 0 1834 || memcmp(module + i, "DEFSONG ", 8) == 0
1835 || memcmp(module + i, "STEREO\r", 7) == 0 1835 || memcmp(module + i, "STEREO\r", 7) == 0
1836 || memcmp(module + i, "TIME ", 5) == 0) { 1836 || memcmp(module + i, "TIME ", 5) == 0) {
1837 while (i < module_len && module[i++] != 0x0a); 1837 while (i < module_len && module[i++] != 0x0a);
1838 } 1838 }
1839 else { 1839 else {
1840 int b; 1840 int b;
1841 do { 1841 do {
1842 b = module[i++]; 1842 b = module[i++];
1843 *dest++ = b; 1843 *dest++ = b;
1844 } while (i < module_len && b != 0x0a); 1844 } while (i < module_len && b != 0x0a);
1845 } 1845 }
1846 } 1846 }
1847 dest = put_durations(dest, module_info); 1847 dest = put_durations(dest, module_info);
1848 module_len -= i; 1848 module_len -= i;
1849 memcpy(dest, module + i, module_len); 1849 memcpy(dest, module + i, module_len);
1850 dest += module_len; 1850 dest += module_len;
1851 return dest - out_module; 1851 return dest - out_module;
1852} 1852}
1853 1853
1854#define RMT_INIT 0x0c80 1854#define RMT_INIT 0x0c80
1855#define TM2_INIT 0x1080 1855#define TM2_INIT 0x1080
1856 1856
1857const char *ASAP_CanConvert( 1857const char *ASAP_CanConvert(
1858 const char *filename, const ASAP_ModuleInfo *module_info, 1858 const char *filename, const ASAP_ModuleInfo *module_info,
1859 const BYTEARRAY module, int module_len) 1859 const BYTEARRAY module, int module_len)
1860{ 1860{
1861 (void) filename; 1861 (void) filename;
1862 switch (module_info->type) { 1862 switch (module_info->type) {
1863 case ASAP_TYPE_SAP_B: 1863 case ASAP_TYPE_SAP_B:
1864 if ((module_info->init == 0x3fb || module_info->init == 0x3f9) && module_info->player == 0x503) 1864 if ((module_info->init == 0x3fb || module_info->init == 0x3f9) && module_info->player == 0x503)
1865 return "dlt"; 1865 return "dlt";
1866 if (module_info->init == 0x4f3 || module_info->init == 0xf4f3 || module_info->init == 0x4ef) 1866 if (module_info->init == 0x4f3 || module_info->init == 0xf4f3 || module_info->init == 0x4ef)
1867 return module_info->fastplay == 156 ? "mpd" : "mpt"; 1867 return module_info->fastplay == 156 ? "mpd" : "mpt";
1868 if (module_info->init == RMT_INIT) 1868 if (module_info->init == RMT_INIT)
1869 return "rmt"; 1869 return "rmt";
1870 if ((module_info->init == 0x4f5 || module_info->init == 0xf4f5 || module_info->init == 0x4f2) 1870 if ((module_info->init == 0x4f5 || module_info->init == 0xf4f5 || module_info->init == 0x4f2)
1871 || ((module_info->init == 0x4e7 || module_info->init == 0xf4e7 || module_info->init == 0x4e4) && module_info->fastplay == 156) 1871 || ((module_info->init == 0x4e7 || module_info->init == 0xf4e7 || module_info->init == 0x4e4) && module_info->fastplay == 156)
1872 || ((module_info->init == 0x4e5 || module_info->init == 0xf4e5 || module_info->init == 0x4e2) && (module_info->fastplay == 104 || module_info->fastplay == 78))) 1872 || ((module_info->init == 0x4e5 || module_info->init == 0xf4e5 || module_info->init == 0x4e2) && (module_info->fastplay == 104 || module_info->fastplay == 78)))
1873 return "tmc"; 1873 return "tmc";
1874 if (module_info->init == TM2_INIT) 1874 if (module_info->init == TM2_INIT)
1875 return "tm2"; 1875 return "tm2";
1876 break; 1876 break;
1877 case ASAP_TYPE_SAP_C: 1877 case ASAP_TYPE_SAP_C:
1878 if (module_info->player == 0x500 || module_info->player == 0xf500) { 1878 if (module_info->player == 0x500 || module_info->player == 0xf500) {
1879 if (module_info->fastplay == 156) 1879 if (module_info->fastplay == 156)
1880 return "dmc"; 1880 return "dmc";
1881 if (module_info->channels > 1) 1881 if (module_info->channels > 1)
1882 return "cms"; 1882 return "cms";
1883 if (module[module_len - 170] == 0x1e) 1883 if (module[module_len - 170] == 0x1e)
1884 return "cmr"; 1884 return "cmr";
1885 if (module[module_len - 909] == 0x30) 1885 if (module[module_len - 909] == 0x30)
1886 return "cm3"; 1886 return "cm3";
1887 return "cmc"; 1887 return "cmc";
1888 } 1888 }
1889 break; 1889 break;
1890 case ASAP_TYPE_CMC: 1890 case ASAP_TYPE_CMC:
1891 case ASAP_TYPE_CM3: 1891 case ASAP_TYPE_CM3:
1892 case ASAP_TYPE_CMR: 1892 case ASAP_TYPE_CMR:
1893 case ASAP_TYPE_CMS: 1893 case ASAP_TYPE_CMS:
1894 case ASAP_TYPE_DLT: 1894 case ASAP_TYPE_DLT:
1895 case ASAP_TYPE_MPT: 1895 case ASAP_TYPE_MPT:
1896 case ASAP_TYPE_RMT: 1896 case ASAP_TYPE_RMT:
1897 case ASAP_TYPE_TMC: 1897 case ASAP_TYPE_TMC:
1898 case ASAP_TYPE_TM2: 1898 case ASAP_TYPE_TM2:
1899 return "sap"; 1899 return "sap";
1900 default: 1900 default:
1901 break; 1901 break;
1902 } 1902 }
1903 return NULL; 1903 return NULL;
1904} 1904}
1905 1905
1906int ASAP_Convert( 1906int ASAP_Convert(
1907 const char *filename, const ASAP_ModuleInfo *module_info, 1907 const char *filename, const ASAP_ModuleInfo *module_info,
1908 const BYTEARRAY module, int module_len, BYTEARRAY out_module) 1908 const BYTEARRAY module, int module_len, BYTEARRAY out_module)
1909{ 1909{
1910 (void) filename; 1910 (void) filename;
1911 int out_len; 1911 int out_len;
1912 byte *dest; 1912 byte *dest;
1913 int addr; 1913 int addr;
1914 int player; 1914 int player;
1915 static const int tmc_player[4] = { 3, -9, -10, -10 }; 1915 static const int tmc_player[4] = { 3, -9, -10, -10 };
1916 static const int tmc_init[4] = { -14, -16, -17, -17 }; 1916 static const int tmc_init[4] = { -14, -16, -17, -17 };
1917 switch (module_info->type) { 1917 switch (module_info->type) {
1918 case ASAP_TYPE_SAP_B: 1918 case ASAP_TYPE_SAP_B:
1919 case ASAP_TYPE_SAP_C: 1919 case ASAP_TYPE_SAP_C:
1920 out_len = UWORD(module, module_info->header_len + 4) - UWORD(module, module_info->header_len + 2) + 7; 1920 out_len = UWORD(module, module_info->header_len + 4) - UWORD(module, module_info->header_len + 2) + 7;
1921 if (out_len < 7 || module_info->header_len + out_len >= module_len) 1921 if (out_len < 7 || module_info->header_len + out_len >= module_len)
1922 return -1; 1922 return -1;
1923 memcpy(out_module, module + module_info->header_len, out_len); 1923 memcpy(out_module, module + module_info->header_len, out_len);
1924 return out_len; 1924 return out_len;
1925 case ASAP_TYPE_CMC: 1925 case ASAP_TYPE_CMC:
1926 case ASAP_TYPE_CM3: 1926 case ASAP_TYPE_CM3:
1927 case ASAP_TYPE_CMR: 1927 case ASAP_TYPE_CMR:
1928 case ASAP_TYPE_CMS: 1928 case ASAP_TYPE_CMS:
1929 dest = put_sap_header(out_module, module_info, 'C', module_info->music, -1, module_info->player); 1929 dest = put_sap_header(out_module, module_info, 'C', module_info->music, -1, module_info->player);
1930 if (dest == NULL) 1930 if (dest == NULL)
1931 return -1; 1931 return -1;
1932 memcpy(dest, module, module_len); 1932 memcpy(dest, module, module_len);
1933 dest[0] = 0xff; /* some modules start with zeros */ 1933 dest[0] = 0xff; /* some modules start with zeros */
1934 dest[1] = 0xff; 1934 dest[1] = 0xff;
1935 dest += module_len; 1935 dest += module_len;
1936 if (module_info->type == ASAP_TYPE_CM3) { 1936 if (module_info->type == ASAP_TYPE_CM3) {
1937 memcpy(dest, cm3_obx + 2, sizeof(cm3_obx) - 2); 1937 memcpy(dest, cm3_obx + 2, sizeof(cm3_obx) - 2);
1938 dest += sizeof(cm3_obx) - 2; 1938 dest += sizeof(cm3_obx) - 2;
1939 } 1939 }
1940 else if (module_info->type == ASAP_TYPE_CMS) { 1940 else if (module_info->type == ASAP_TYPE_CMS) {
1941 memcpy(dest, cms_obx + 2, sizeof(cms_obx) - 2); 1941 memcpy(dest, cms_obx + 2, sizeof(cms_obx) - 2);
1942 dest += sizeof(cms_obx) - 2; 1942 dest += sizeof(cms_obx) - 2;
1943 } 1943 }
1944 else { 1944 else {
1945 memcpy(dest, cmc_obx + 2, sizeof(cmc_obx) - 2); 1945 memcpy(dest, cmc_obx + 2, sizeof(cmc_obx) - 2);
1946 if (module_info->type == ASAP_TYPE_CMR) 1946 if (module_info->type == ASAP_TYPE_CMR)
1947 memcpy(dest + 4 + CMR_BASS_TABLE_OFFSET, cmr_bass_table, sizeof(cmr_bass_table)); 1947 memcpy(dest + 4 + CMR_BASS_TABLE_OFFSET, cmr_bass_table, sizeof(cmr_bass_table));
1948 dest += sizeof(cmc_obx) - 2; 1948 dest += sizeof(cmc_obx) - 2;
1949 } 1949 }
1950 return dest - out_module; 1950 return dest - out_module;
1951 case ASAP_TYPE_DLT: 1951 case ASAP_TYPE_DLT:
1952 if (module_info->songs != 1) { 1952 if (module_info->songs != 1) {
1953 addr = module_info->player - 7 - module_info->songs; 1953 addr = module_info->player - 7 - module_info->songs;
1954 dest = put_sap_header(out_module, module_info, 'B', -1, module_info->player - 7, module_info->player + 0x103); 1954 dest = put_sap_header(out_module, module_info, 'B', -1, module_info->player - 7, module_info->player + 0x103);
1955 } 1955 }
1956 else { 1956 else {
1957 addr = module_info->player - 5; 1957 addr = module_info->player - 5;
1958 dest = put_sap_header(out_module, module_info, 'B', -1, addr, module_info->player + 0x103); 1958 dest = put_sap_header(out_module, module_info, 'B', -1, addr, module_info->player + 0x103);
1959 } 1959 }
1960 if (dest == NULL) 1960 if (dest == NULL)
1961 return -1; 1961 return -1;
1962 memcpy(dest, module, module_len); 1962 memcpy(dest, module, module_len);
1963 if (module_len == 0x2c06) { 1963 if (module_len == 0x2c06) {
1964 dest[4] = 0; 1964 dest[4] = 0;
1965 dest[5] = 0x4c; 1965 dest[5] = 0x4c;
1966 dest[0x2c06] = 0; 1966 dest[0x2c06] = 0;
1967 } 1967 }
1968 dest += 0x2c07; 1968 dest += 0x2c07;
1969 *dest++ = (byte) addr; 1969 *dest++ = (byte) addr;
1970 *dest++ = (byte) (addr >> 8); 1970 *dest++ = (byte) (addr >> 8);
1971 *dest++ = dlt_obx[4]; 1971 *dest++ = dlt_obx[4];
1972 *dest++ = dlt_obx[5]; 1972 *dest++ = dlt_obx[5];
1973 if (module_info->songs != 1) { 1973 if (module_info->songs != 1) {
1974 memcpy(dest, module_info->song_pos, module_info->songs); 1974 memcpy(dest, module_info->song_pos, module_info->songs);
1975 dest += module_info->songs; 1975 dest += module_info->songs;
1976 *dest++ = 0xaa; /* tax */ 1976 *dest++ = 0xaa; /* tax */
1977 *dest++ = 0xbc; /* ldy song2pos,x */ 1977 *dest++ = 0xbc; /* ldy song2pos,x */
1978 *dest++ = (byte) addr; 1978 *dest++ = (byte) addr;
1979 *dest++ = (byte) (addr >> 8); 1979 *dest++ = (byte) (addr >> 8);
1980 } 1980 }
1981 else { 1981 else {
1982 *dest++ = 0xa0; /* ldy #0 */ 1982 *dest++ = 0xa0; /* ldy #0 */
1983 *dest++ = 0; 1983 *dest++ = 0;
1984 } 1984 }
1985 *dest++ = 0x4c; /* jmp init */ 1985 *dest++ = 0x4c; /* jmp init */
1986 *dest++ = (byte) module_info->player; 1986 *dest++ = (byte) module_info->player;
1987 *dest++ = (byte) ((module_info->player >> 8) + 1); 1987 *dest++ = (byte) ((module_info->player >> 8) + 1);
1988 memcpy(dest, dlt_obx + 6, sizeof(dlt_obx) - 6); 1988 memcpy(dest, dlt_obx + 6, sizeof(dlt_obx) - 6);
1989 dest += sizeof(dlt_obx) - 6; 1989 dest += sizeof(dlt_obx) - 6;
1990 return dest - out_module; 1990 return dest - out_module;
1991 case ASAP_TYPE_MPT: 1991 case ASAP_TYPE_MPT:
1992 if (module_info->songs != 1) { 1992 if (module_info->songs != 1) {
1993 addr = module_info->player - 17 - module_info->songs; 1993 addr = module_info->player - 17 - module_info->songs;
1994 dest = put_sap_header(out_module, module_info, 'B', -1, module_info->player - 17, module_info->player + 3); 1994 dest = put_sap_header(out_module, module_info, 'B', -1, module_info->player - 17, module_info->player + 3);
1995 } 1995 }
1996 else { 1996 else {
1997 addr = module_info->player - 13; 1997 addr = module_info->player - 13;
1998 dest = put_sap_header(out_module, module_info, 'B', -1, addr, module_info->player + 3); 1998 dest = put_sap_header(out_module, module_info, 'B', -1, addr, module_info->player + 3);
1999 } 1999 }
2000 if (dest == NULL) 2000 if (dest == NULL)
2001 return -1; 2001 return -1;
2002 memcpy(dest, module, module_len); 2002 memcpy(dest, module, module_len);
2003 dest += module_len; 2003 dest += module_len;
2004 *dest++ = (byte) addr; 2004 *dest++ = (byte) addr;
2005 *dest++ = (byte) (addr >> 8); 2005 *dest++ = (byte) (addr >> 8);
2006 *dest++ = mpt_obx[4]; 2006 *dest++ = mpt_obx[4];
2007 *dest++ = mpt_obx[5]; 2007 *dest++ = mpt_obx[5];
2008 if (module_info->songs != 1) { 2008 if (module_info->songs != 1) {
2009 memcpy(dest, module_info->song_pos, module_info->songs); 2009 memcpy(dest, module_info->song_pos, module_info->songs);
2010 dest += module_info->songs; 2010 dest += module_info->songs;
2011 *dest++ = 0x48; /* pha */ 2011 *dest++ = 0x48; /* pha */
2012 } 2012 }
2013 *dest++ = 0xa0; /* ldy #<music */ 2013 *dest++ = 0xa0; /* ldy #<music */
2014 *dest++ = (byte) module_info->music; 2014 *dest++ = (byte) module_info->music;
2015 *dest++ = 0xa2; /* ldx #>music */ 2015 *dest++ = 0xa2; /* ldx #>music */
2016 *dest++ = (byte) (module_info->music >> 8); 2016 *dest++ = (byte) (module_info->music >> 8);
2017 *dest++ = 0xa9; /* lda #0 */ 2017 *dest++ = 0xa9; /* lda #0 */
2018 *dest++ = 0; 2018 *dest++ = 0;
2019 *dest++ = 0x20; /* jsr player */ 2019 *dest++ = 0x20; /* jsr player */
2020 *dest++ = (byte) module_info->player; 2020 *dest++ = (byte) module_info->player;
2021 *dest++ = (byte) (module_info->player >> 8); 2021 *dest++ = (byte) (module_info->player >> 8);
2022 if (module_info->songs != 1) { 2022 if (module_info->songs != 1) {
2023 *dest++ = 0x68; /* pla */ 2023 *dest++ = 0x68; /* pla */
2024 *dest++ = 0xa8; /* tay */ 2024 *dest++ = 0xa8; /* tay */
2025 *dest++ = 0xbe; /* ldx song2pos,y */ 2025 *dest++ = 0xbe; /* ldx song2pos,y */
2026 *dest++ = (byte) addr; 2026 *dest++ = (byte) addr;
2027 *dest++ = (byte) (addr >> 8); 2027 *dest++ = (byte) (addr >> 8);
2028 } 2028 }
2029 else { 2029 else {
2030 *dest++ = 0xa2; /* ldx #0 */ 2030 *dest++ = 0xa2; /* ldx #0 */
2031 *dest++ = 0; 2031 *dest++ = 0;
2032 } 2032 }
2033 *dest++ = 0xa9; /* lda #2 */ 2033 *dest++ = 0xa9; /* lda #2 */
2034 *dest++ = 2; 2034 *dest++ = 2;
2035 memcpy(dest, mpt_obx + 6, sizeof(mpt_obx) - 6); 2035 memcpy(dest, mpt_obx + 6, sizeof(mpt_obx) - 6);
2036 dest += sizeof(mpt_obx) - 6; 2036 dest += sizeof(mpt_obx) - 6;
2037 return dest - out_module; 2037 return dest - out_module;
2038 case ASAP_TYPE_RMT: 2038 case ASAP_TYPE_RMT:
2039 dest = put_sap_header(out_module, module_info, 'B', -1, RMT_INIT, module_info->player + 3); 2039 dest = put_sap_header(out_module, module_info, 'B', -1, RMT_INIT, module_info->player + 3);
2040 if (dest == NULL) 2040 if (dest == NULL)
2041 return -1; 2041 return -1;
2042 memcpy(dest, module, module_len); 2042 memcpy(dest, module, module_len);
2043 dest += module_len; 2043 dest += module_len;
2044 *dest++ = (byte) RMT_INIT; 2044 *dest++ = (byte) RMT_INIT;
2045 *dest++ = (byte) (RMT_INIT >> 8); 2045 *dest++ = (byte) (RMT_INIT >> 8);
2046 if (module_info->songs != 1) { 2046 if (module_info->songs != 1) {
2047 addr = RMT_INIT + 10 + module_info->songs; 2047 addr = RMT_INIT + 10 + module_info->songs;
2048 *dest++ = (byte) addr; 2048 *dest++ = (byte) addr;
2049 *dest++ = (byte) (addr >> 8); 2049 *dest++ = (byte) (addr >> 8);
2050 *dest++ = 0xa8; /* tay */ 2050 *dest++ = 0xa8; /* tay */
2051 *dest++ = 0xb9; /* lda song2pos,y */ 2051 *dest++ = 0xb9; /* lda song2pos,y */
2052 *dest++ = (byte) (RMT_INIT + 11); 2052 *dest++ = (byte) (RMT_INIT + 11);
2053 *dest++ = (byte) ((RMT_INIT + 11) >> 8); 2053 *dest++ = (byte) ((RMT_INIT + 11) >> 8);
2054 } 2054 }
2055 else { 2055 else {
2056 *dest++ = (byte) (RMT_INIT + 8); 2056 *dest++ = (byte) (RMT_INIT + 8);
2057 *dest++ = (byte) ((RMT_INIT + 8) >> 8); 2057 *dest++ = (byte) ((RMT_INIT + 8) >> 8);
2058 *dest++ = 0xa9; /* lda #0 */ 2058 *dest++ = 0xa9; /* lda #0 */
2059 *dest++ = 0; 2059 *dest++ = 0;
2060 } 2060 }
2061 *dest++ = 0xa2; /* ldx #<music */ 2061 *dest++ = 0xa2; /* ldx #<music */
2062 *dest++ = (byte) module_info->music; 2062 *dest++ = (byte) module_info->music;
2063 *dest++ = 0xa0; /* ldy #>music */ 2063 *dest++ = 0xa0; /* ldy #>music */
2064 *dest++ = (byte) (module_info->music >> 8); 2064 *dest++ = (byte) (module_info->music >> 8);
2065 *dest++ = 0x4c; /* jmp player */ 2065 *dest++ = 0x4c; /* jmp player */
2066 *dest++ = (byte) module_info->player; 2066 *dest++ = (byte) module_info->player;
2067 *dest++ = (byte) (module_info->player >> 8); 2067 *dest++ = (byte) (module_info->player >> 8);
2068 if (module_info->songs != 1) { 2068 if (module_info->songs != 1) {
2069 memcpy(dest, module_info->song_pos, module_info->songs); 2069 memcpy(dest, module_info->song_pos, module_info->songs);
2070 dest += module_info->songs; 2070 dest += module_info->songs;
2071 } 2071 }
2072 if (module_info->channels == 1) { 2072 if (module_info->channels == 1) {
2073 memcpy(dest, rmt4_obx + 2, sizeof(rmt4_obx) - 2); 2073 memcpy(dest, rmt4_obx + 2, sizeof(rmt4_obx) - 2);
2074 dest += sizeof(rmt4_obx) - 2; 2074 dest += sizeof(rmt4_obx) - 2;
2075 } 2075 }
2076 else { 2076 else {
2077 memcpy(dest, rmt8_obx + 2, sizeof(rmt8_obx) - 2); 2077 memcpy(dest, rmt8_obx + 2, sizeof(rmt8_obx) - 2);
2078 dest += sizeof(rmt8_obx) - 2; 2078 dest += sizeof(rmt8_obx) - 2;
2079 } 2079 }
2080 return dest - out_module; 2080 return dest - out_module;
2081 case ASAP_TYPE_TMC: 2081 case ASAP_TYPE_TMC:
2082 player = module_info->player + tmc_player[module[0x25] - 1]; 2082 player = module_info->player + tmc_player[module[0x25] - 1];
2083 addr = player + tmc_init[module[0x25] - 1]; 2083 addr = player + tmc_init[module[0x25] - 1];
2084 if (module_info->songs != 1) 2084 if (module_info->songs != 1)
2085 addr -= 3; 2085 addr -= 3;
2086 dest = put_sap_header(out_module, module_info, 'B', -1, addr, player); 2086 dest = put_sap_header(out_module, module_info, 'B', -1, addr, player);
2087 if (dest == NULL) 2087 if (dest == NULL)
2088 return -1; 2088 return -1;
2089 memcpy(dest, module, module_len); 2089 memcpy(dest, module, module_len);
2090 dest += module_len; 2090 dest += module_len;
2091 *dest++ = (byte) addr; 2091 *dest++ = (byte) addr;
2092 *dest++ = (byte) (addr >> 8); 2092 *dest++ = (byte) (addr >> 8);
2093 *dest++ = tmc_obx[4]; 2093 *dest++ = tmc_obx[4];
2094 *dest++ = tmc_obx[5]; 2094 *dest++ = tmc_obx[5];
2095 if (module_info->songs != 1) 2095 if (module_info->songs != 1)
2096 *dest++ = 0x48; /* pha */ 2096 *dest++ = 0x48; /* pha */
2097 *dest++ = 0xa0; /* ldy #<music */ 2097 *dest++ = 0xa0; /* ldy #<music */
2098 *dest++ = (byte) module_info->music; 2098 *dest++ = (byte) module_info->music;
2099 *dest++ = 0xa2; /* ldx #>music */ 2099 *dest++ = 0xa2; /* ldx #>music */
2100 *dest++ = (byte) (module_info->music >> 8); 2100 *dest++ = (byte) (module_info->music >> 8);
2101 *dest++ = 0xa9; /* lda #$70 */ 2101 *dest++ = 0xa9; /* lda #$70 */
2102 *dest++ = 0x70; 2102 *dest++ = 0x70;
2103 *dest++ = 0x20; /* jsr player */ 2103 *dest++ = 0x20; /* jsr player */
2104 *dest++ = (byte) module_info->player; 2104 *dest++ = (byte) module_info->player;
2105 *dest++ = (byte) (module_info->player >> 8); 2105 *dest++ = (byte) (module_info->player >> 8);
2106 if (module_info->songs != 1) { 2106 if (module_info->songs != 1) {
2107 *dest++ = 0x68; /* pla */ 2107 *dest++ = 0x68; /* pla */
2108 *dest++ = 0xaa; /* tax */ 2108 *dest++ = 0xaa; /* tax */
2109 *dest++ = 0xa9; /* lda #0 */ 2109 *dest++ = 0xa9; /* lda #0 */
2110 *dest++ = 0; 2110 *dest++ = 0;
2111 } 2111 }
2112 else { 2112 else {
2113 *dest++ = 0xa9; /* lda #$60 */ 2113 *dest++ = 0xa9; /* lda #$60 */
2114 *dest++ = 0x60; 2114 *dest++ = 0x60;
2115 } 2115 }
2116 switch (module[0x25]) { 2116 switch (module[0x25]) {
2117 case 2: 2117 case 2:
2118 *dest++ = 0x06; /* asl 0 */ 2118 *dest++ = 0x06; /* asl 0 */
2119 *dest++ = 0; 2119 *dest++ = 0;
2120 *dest++ = 0x4c; /* jmp player */ 2120 *dest++ = 0x4c; /* jmp player */
2121 *dest++ = (byte) module_info->player; 2121 *dest++ = (byte) module_info->player;
2122 *dest++ = (byte) (module_info->player >> 8); 2122 *dest++ = (byte) (module_info->player >> 8);
2123 *dest++ = 0xa5; /* lda 0 */ 2123 *dest++ = 0xa5; /* lda 0 */
2124 *dest++ = 0; 2124 *dest++ = 0;
2125 *dest++ = 0xe6; /* inc 0 */ 2125 *dest++ = 0xe6; /* inc 0 */
2126 *dest++ = 0; 2126 *dest++ = 0;
2127 *dest++ = 0x4a; /* lsr @ */ 2127 *dest++ = 0x4a; /* lsr @ */
2128 *dest++ = 0x90; /* bcc player+3 */ 2128 *dest++ = 0x90; /* bcc player+3 */
2129 *dest++ = 5; 2129 *dest++ = 5;
2130 *dest++ = 0xb0; /* bcs player+6 */ 2130 *dest++ = 0xb0; /* bcs player+6 */
2131 *dest++ = 6; 2131 *dest++ = 6;
2132 break; 2132 break;
2133 case 3: 2133 case 3:
2134 case 4: 2134 case 4:
2135 *dest++ = 0xa0; /* ldy #1 */ 2135 *dest++ = 0xa0; /* ldy #1 */
2136 *dest++ = 1; 2136 *dest++ = 1;
2137 *dest++ = 0x84; /* sty 0 */ 2137 *dest++ = 0x84; /* sty 0 */
2138 *dest++ = 0; 2138 *dest++ = 0;
2139 *dest++ = 0xd0; /* bne player */ 2139 *dest++ = 0xd0; /* bne player */
2140 *dest++ = 10; 2140 *dest++ = 10;
2141 *dest++ = 0xc6; /* dec 0 */ 2141 *dest++ = 0xc6; /* dec 0 */
2142 *dest++ = 0; 2142 *dest++ = 0;
2143 *dest++ = 0xd0; /* bne player+6 */ 2143 *dest++ = 0xd0; /* bne player+6 */
2144 *dest++ = 12; 2144 *dest++ = 12;
2145 *dest++ = 0xa0; /* ldy #3 */ 2145 *dest++ = 0xa0; /* ldy #3 */
2146 *dest++ = module[0x25]; 2146 *dest++ = module[0x25];
2147 *dest++ = 0x84; /* sty 0 */ 2147 *dest++ = 0x84; /* sty 0 */
2148 *dest++ = 0; 2148 *dest++ = 0;
2149 *dest++ = 0xd0; /* bne player+3 */ 2149 *dest++ = 0xd0; /* bne player+3 */
2150 *dest++ = 3; 2150 *dest++ = 3;
2151 break; 2151 break;
2152 default: 2152 default:
2153 break; 2153 break;
2154 } 2154 }
2155 memcpy(dest, tmc_obx + 6, sizeof(tmc_obx) - 6); 2155 memcpy(dest, tmc_obx + 6, sizeof(tmc_obx) - 6);
2156 dest += sizeof(tmc_obx) - 6; 2156 dest += sizeof(tmc_obx) - 6;
2157 return dest - out_module; 2157 return dest - out_module;
2158 case ASAP_TYPE_TM2: 2158 case ASAP_TYPE_TM2:
2159 dest = put_sap_header(out_module, module_info, 'B', -1, TM2_INIT, module_info->player + 3); 2159 dest = put_sap_header(out_module, module_info, 'B', -1, TM2_INIT, module_info->player + 3);
2160 if (dest == NULL) 2160 if (dest == NULL)
2161 return -1; 2161 return -1;
2162 memcpy(dest, module, module_len); 2162 memcpy(dest, module, module_len);
2163 dest += module_len; 2163 dest += module_len;
2164 *dest++ = (byte) TM2_INIT; 2164 *dest++ = (byte) TM2_INIT;
2165 *dest++ = (byte) (TM2_INIT >> 8); 2165 *dest++ = (byte) (TM2_INIT >> 8);
2166 if (module_info->songs != 1) { 2166 if (module_info->songs != 1) {
2167 *dest++ = (byte) (TM2_INIT + 16); 2167 *dest++ = (byte) (TM2_INIT + 16);
2168 *dest++ = (byte) ((TM2_INIT + 16) >> 8); 2168 *dest++ = (byte) ((TM2_INIT + 16) >> 8);
2169 *dest++ = 0x48; /* pha */ 2169 *dest++ = 0x48; /* pha */
2170 } 2170 }
2171 else { 2171 else {
2172 *dest++ = (byte) (TM2_INIT + 14); 2172 *dest++ = (byte) (TM2_INIT + 14);
2173 *dest++ = (byte) ((TM2_INIT + 14) >> 8); 2173 *dest++ = (byte) ((TM2_INIT + 14) >> 8);
2174 } 2174 }
2175 *dest++ = 0xa0; /* ldy #<music */ 2175 *dest++ = 0xa0; /* ldy #<music */
2176 *dest++ = (byte) module_info->music; 2176 *dest++ = (byte) module_info->music;
2177 *dest++ = 0xa2; /* ldx #>music */ 2177 *dest++ = 0xa2; /* ldx #>music */
2178 *dest++ = (byte) (module_info->music >> 8); 2178 *dest++ = (byte) (module_info->music >> 8);
2179 *dest++ = 0xa9; /* lda #$70 */ 2179 *dest++ = 0xa9; /* lda #$70 */
2180 *dest++ = 0x70; 2180 *dest++ = 0x70;
2181 *dest++ = 0x20; /* jsr player */ 2181 *dest++ = 0x20; /* jsr player */
2182 *dest++ = (byte) module_info->player; 2182 *dest++ = (byte) module_info->player;
2183 *dest++ = (byte) (module_info->player >> 8); 2183 *dest++ = (byte) (module_info->player >> 8);
2184 if (module_info->songs != 1) { 2184 if (module_info->songs != 1) {
2185 *dest++ = 0x68; /* pla */ 2185 *dest++ = 0x68; /* pla */
2186 *dest++ = 0xaa; /* tax */ 2186 *dest++ = 0xaa; /* tax */
2187 *dest++ = 0xa9; /* lda #0 */ 2187 *dest++ = 0xa9; /* lda #0 */
2188 *dest++ = 0; 2188 *dest++ = 0;
2189 } 2189 }
2190 else { 2190 else {
2191 *dest++ = 0xa9; /* lda #0 */ 2191 *dest++ = 0xa9; /* lda #0 */
2192 *dest++ = 0; 2192 *dest++ = 0;
2193 *dest++ = 0xaa; /* tax */ 2193 *dest++ = 0xaa; /* tax */
2194 } 2194 }
2195 *dest++ = 0x4c; /* jmp player */ 2195 *dest++ = 0x4c; /* jmp player */
2196 *dest++ = (byte) module_info->player; 2196 *dest++ = (byte) module_info->player;
2197 *dest++ = (byte) (module_info->player >> 8); 2197 *dest++ = (byte) (module_info->player >> 8);
2198 memcpy(dest, tm2_obx + 2, sizeof(tm2_obx) - 2); 2198 memcpy(dest, tm2_obx + 2, sizeof(tm2_obx) - 2);
2199 dest += sizeof(tm2_obx) - 2; 2199 dest += sizeof(tm2_obx) - 2;
2200 return dest - out_module; 2200 return dest - out_module;
2201 default: 2201 default:
2202 return -1; 2202 return -1;
2203 } 2203 }
2204} 2204}
2205 2205
2206#endif /* defined(C) && !defined(ASAP_ONLY_SAP) */ 2206#endif /* defined(C) && !defined(ASAP_ONLY_SAP) */