1 /* OpenCP Module Player
2 * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3 *
4 * XMPlay time routines for IMS
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * revision history: (please note changes here)
21 * -nb980510 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
22 * -first release
23 * -th980717 Tammo Hinrichs <opencp@gmx.net>
24 * -removed all references to gmd structures to make this more flexible
25 */
26
27 #include "config.h"
28 #include "types.h"
29 #include "xmplay.h"
30 #include "err.h"
31
32 static uint8_t chPatLoopCount[256];
33 static uint8_t chPatLoopStart[256];
34
35 static uint8_t curtick;
36 static uint8_t curtempo;
37
38 static int looped;
39 static int currow;
40 static uint8_t (*patptr)[5];
41 static int patlen;
42 static int curord;
43
44 static int nord;
45 static int nchan;
46 static int loopord;
47 static uint8_t (**patterns)[5];
48 static uint16_t *orders;
49 static uint16_t *patlens;
50
51 static int jumptoord;
52 static int jumptorow;
53 static int patdelay;
54
55 static int timerval;
56 static int timerfrac;
57 static int speed;
58
59 static int (*calctimer)[2];
60 static int calcn;
61 static int sync;
62
xmpFindTick(void)63 static int xmpFindTick(void)
64 {
65 int i;
66 int p;
67
68 curtick++;
69 if (curtick>=curtempo)
70 curtick=0;
71
72 if (!curtick&&patdelay)
73 {
74 if (jumptoord!=-1)
75 {
76 if (jumptoord!=curord)
77 for (i=0; i<nchan; i++)
78 {
79 chPatLoopCount[i]=0;
80 chPatLoopStart[i]=0;
81 }
82
83 if (jumptoord>=nord)
84 jumptoord=loopord;
85
86 curord=jumptoord;
87 currow=jumptorow;
88 jumptoord=-1;
89 patlen=patlens[orders[curord]];
90 patptr=patterns[orders[curord]];
91 }
92 }
93
94 if (!curtick&&patdelay)
95 {
96 patdelay--;
97 } else if (!curtick)
98 {
99 currow++;
100 if ((jumptoord==-1)&&(currow>=patlen))
101 {
102 jumptoord=curord+1;
103 jumptorow=0;
104 }
105 if (jumptoord!=-1)
106 {
107 if (jumptoord!=curord)
108 for (i=0; i<nchan; i++)
109 {
110 chPatLoopCount[i]=0;
111 chPatLoopStart[i]=0;
112 }
113
114 if (jumptoord>=nord)
115 jumptoord=loopord;
116 if (jumptoord<curord)
117 looped=1;
118
119 curord=jumptoord;
120 currow=jumptorow;
121 jumptoord=-1;
122 patlen=patlens[orders[curord]];
123 patptr=patterns[orders[curord]];
124 }
125
126 for (i=0; i<nchan; i++)
127 {
128 int procdat=patptr[nchan*currow+i][4];
129
130 switch (patptr[nchan*currow+i][3])
131 {
132 case xmpCmdSync1: case xmpCmdSync2: case xmpCmdSync3:
133 sync=procdat;
134 break;
135 case xmpCmdJump:
136 jumptoord=procdat;
137 jumptorow=0;
138 break;
139 case xmpCmdBreak:
140 if (jumptoord==-1)
141 jumptoord=curord+1;
142 jumptorow=(procdat&0xF)+(procdat>>4)*10;
143 break;
144 case xmpCmdSpeed:
145 if (!procdat)
146 {
147 jumptoord=procdat;
148 jumptorow=0;
149 break;
150 }
151 if (procdat>=0x20)
152 speed=procdat;
153 else
154 curtempo=procdat;
155 break;
156 case xmpCmdPatLoop:
157 if (!procdat)
158 chPatLoopStart[i]=currow;
159 else {
160 chPatLoopCount[i]++;
161 if (chPatLoopCount[i]<=procdat)
162 {
163 jumptorow=chPatLoopStart[i];
164 jumptoord=curord;
165 } else {
166 chPatLoopCount[i]=0;
167 chPatLoopStart[i]=currow+1;
168 }
169 }
170 break;
171 case xmpCmdPatDelay:
172 patdelay=procdat;
173 break;
174 }
175 }
176 }
177
178 p=(curord<<16)|(currow<<8)|curtick;
179 for (i=0; i<calcn; i++)
180 if ((p==calctimer[i][0])&&(calctimer[i][1]<0))
181 if (!++calctimer[i][1])
182 calctimer[i][1]=timerval;
183
184 if (sync!=-1)
185 for (i=0; i<calcn; i++)
186 if ((calctimer[i][0]==(-256-sync))&&(calctimer[i][1]<0))
187 if (!++calctimer[i][1])
188 calctimer[i][1]=timerval;
189
190 sync=-1;
191
192 if (looped)
193 for (i=0; i<calcn; i++)
194 if ((calctimer[i][0]==-1)&&(calctimer[i][1]<0))
195 if (!++calctimer[i][1])
196 calctimer[i][1]=timerval;
197
198 looped=0;
199
200 timerfrac+=4096*163840/speed;
201 timerval+=timerfrac>>12;
202 timerfrac&=4095;
203
204 for (i=0; i<calcn; i++)
205 if (calctimer[i][1]<0)
206 return 0;
207
208 return 1;
209 }
210
xmpPrecalcTime(struct xmodule * m,int startpos,int (* calc)[2],int n,int ite)211 int __attribute__ ((visibility ("internal"))) xmpPrecalcTime(struct xmodule *m, int startpos, int (*calc)[2], int n, int ite)
212 {
213 int i;
214
215 patdelay=0;
216 sync=-1;
217 looped=0;
218 calcn=n;
219 calctimer=calc;
220 jumptorow=(startpos>>8)&0xFF;
221 jumptoord=startpos&0xFF;
222 curord=-1;
223 currow=-1;
224 nord=m->nord;
225 patterns=m->patterns;
226 orders=m->orders;
227 patlens=m->patlens;
228 nchan=m->nchan;
229 loopord=m->loopord;
230
231 curtempo=m->initempo;
232 curtick=m->initempo-1;
233
234 speed=m->inibpm;
235 timerval=0;
236 timerfrac=0;
237
238 for (i=0; i<ite; i++)
239 if (xmpFindTick())
240 break;
241
242 return 1;
243 }
244