source: buchla-68k/ram/uslice.c

Last change on this file was e68b406, checked in by Thomas Lopatic <thomas@…>, 6 years ago

Postpone pointer increment for proper sequencing.

  • Property mode set to 100644
File size: 15.8 KB
Line 
1/*
2 =============================================================================
3 uslice.c -- update score display slice
4 Version 32 -- 1988-09-28 -- D.N. Lynx Crowe
5 =============================================================================
6*/
7
8#undef DEBUGGER
9
10#define DEBUGIT 0
11
12#include "ram.h"
13
14#define BARCOLOR 0x3333
15
16/* initialized data */
17
18int16_t lintab1[] = { /* note top line table */
19
20 205, 205, 201, 197, 197, 193, 193, 189, 185, 185, 181, 181,
21 177, 177, 173, 169, 169, 165, 165, 161, 157, 157, 153, 153,
22 149, 149, 145, 141, 141, 137, 137, 133, 129, 129, 125, 125,
23 121, 121, 117, 113, 113, 109, 109, 105, 101, 101, 97, 97,
24 93, 93, 89, 85, 85, 81, 81, 77, 73, 73, 69, 69,
25 65, 65, 61, 57, 57, 53, 53, 49, 45, 45, 41, 41,
26 37, 37, 33, 29, 29, 25, 25, 21, 17, 17, 13, 13,
27 9, 9, 5, 1
28};
29
30int16_t lintab2[] = { /* note top line table - N_FLAT */
31
32 205, 201, 201, 197, 193, 193, 189, 189, 185, 181, 181, 177,
33 177, 173, 173, 169, 165, 165, 161, 161, 157, 153, 153, 149,
34 149, 145, 145, 141, 137, 137, 133, 133, 129, 125, 125, 121,
35 121, 117, 117, 113, 109, 109, 105, 105, 101, 97, 97, 93,
36 93, 89, 89, 85, 81, 81, 77, 77, 73, 69, 69, 65,
37 65, 61, 61, 57, 53, 53, 49, 49, 45, 41, 41, 37,
38 37, 33, 33, 29, 25, 25, 21, 21, 17, 13, 13, 9,
39 9, 5, 5, 1
40};
41
42int16_t nttab1[] = { /* forward code transition table */
43
44 0, /* 0 */
45 2, /* 1 */
46 3, /* 2 */
47 3, /* 3 */
48 5, /* 4 */
49 3, /* 5 */
50 0 /* 6 */
51};
52
53int16_t nttab2[] = { /* backward code transition table */
54
55 0, /* 0 */
56 0, /* 1 */
57 1, /* 2 */
58 3, /* 3 */
59 0, /* 4 */
60 4, /* 5 */
61 0 /* 6 */
62};
63
64uint16_t pxtbl[][4] = { /* pixel mask table for notes */
65
66 { 0x0000, 0x0000, 0x0000, 0 }, /* 0 */
67 { 0x0000, 0x0000, 0xFFFF, 0 }, /* 1 */
68 { 0x0000, 0xFFFF, 0xFFFF, 0 }, /* 2 */
69 { 0xFFFF, 0xFFFF, 0xFFFF, 0 }, /* 3 */
70 { 0xFFFF, 0x0000, 0x0000, 0 }, /* 4 */
71 { 0xFFFF, 0xFFFF, 0x0000, 0 }, /* 5 */
72 { 0xFFFF, 0xFFFF, 0xFFFF, 0 } /* 6 */
73};
74
75uint16_t epxtbl[][16] = { /* pixel mask table for events */
76
77 { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 0 */
78 0xFFFF, 0x0000, 0x0000, 0x0000,
79 0x0000, 0x0000, 0x0000, 0x0000,
80 0, 0, 0, 0 },
81
82 { 0x0000, 0x0000, 0x0000, 0x0000, /* 1 */
83 0x0000, 0xFFFF, 0xFFFF, 0x0000,
84 0x0000, 0x0000, 0x0000, 0x0000,
85 0, 0, 0, 0 },
86
87 { 0x0000, 0x0000, 0x0000, 0x0000, /* 2 */
88 0x0000, 0x0000, 0x0000, 0xFFFF,
89 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
90 0, 0, 0, 0 },
91
92 { 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, /* 3 */
93 0x0000, 0x0000, 0x0000, 0x0000,
94 0x0000, 0x0000, 0x0000, 0x0000,
95 0, 0, 0, 0 },
96
97 { 0x0000, 0x0000, 0x0000, 0xFFFF, /* 4 */
98 0xFFFF, 0xFFFF, 0x0000, 0x0000,
99 0x0000, 0x0000, 0x0000, 0x0000,
100 0, 0, 0, 0 },
101
102 { 0x0000, 0x0000, 0x0000, 0x0000, /* 5 */
103 0x0000, 0x0000, 0xFFFF, 0xFFFF,
104 0xFFFF, 0x0000, 0x0000, 0x0000,
105 0, 0, 0, 0 },
106
107 { 0x0000, 0x0000, 0x0000, 0x0000, /* 6 */
108 0x0000, 0x0000, 0x0000, 0x0000,
109 0x0000, 0xFFFF, 0xFFFF, 0xFFFF,
110 0, 0, 0, 0 }
111};
112
113/*
114 =============================================================================
115 uslice(slice, mask1, mask2, gdstb)
116
117 Updates 'slice[]' using 'mask1' and 'mask2' for the pixel mask
118 and the slice mask, respectively, and 'gdstb[]' for the group table.
119
120 Note transitions are based on the value of global variable 'sd',
121 which is zero for forward, and non-zero for backward scrolling.
122
123 Returns count of active groups and event priority levels.
124
125 Note colors come from 'gtctab[]'.
126
127 This code must be very fast or the display bogs down the system.
128 =============================================================================
129*/
130
131int16_t uslice(volatile uint16_t *slice, uint16_t mask1, uint16_t mask2, struct gdsel *gdstb[])
132{
133 uint16_t *pxptr;
134 volatile uint16_t *slptr;
135 struct gdsel *gdsep;
136 uint16_t i, ncolor, w;
137 uint16_t *ncptr;
138 int16_t *nctabp;
139 struct gdsel **gdstp, *gdprv, *gdnxt;
140 int16_t wrote;
141 int16_t *lintab;
142
143 DB_ENTR("uslice()");
144
145 /* initialize note color, note control, and group control pointers */
146
147 gdstp = gdstb; /* group control table */
148 nctabp = sd ? nttab2 : nttab1; /* note transition table */
149 ncptr = gtctab; /* group to color table */
150 wrote = 0; /* reset count of active groups */
151
152 lintab = (ac_code EQ N_SHARP) ? lintab1 : lintab2; /* line table */
153
154 if (gdstb[NGDSEL - 1]) { /* check for a bar marker */
155
156 slptr = slice; /* point at the slice */
157 ncolor = mask1 & BARCOLOR; /* setup bar write variable */
158
159 for (i = 211; i--; ) { /* draw the bar */
160 *slptr = (*slptr & mask2) | ncolor;
161 ++slptr;
162 }
163
164 gdstb[NGDSEL - 1] = (struct gdsel *)NULL; /* clear flag */
165 }
166
167 for (i = 0; i < 12; i++) { /* scan the group control table ... */
168
169 ncolor = mask1 & *ncptr++; /* get note color mask */
170 gdprv = (struct gdsel *)gdstp; /* setup previous pointer */
171 gdsep = *gdstp++; /* setup current pointer */
172
173 if (gdsep) { /* ... process each active group ... */
174
175 ++wrote; /* indicate slice was updated */
176
177 do { /* ... for each note played by the group ... */
178
179 /* setup slice and pixel pointers */
180
181 slptr = slice + lintab[gdsep->note];
182 pxptr = &pxtbl[gdsep->code][0];
183
184 /* update the slice */
185
186 *slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
187 ++slptr;
188 *slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
189 ++slptr;
190 *slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
191
192 gdnxt = gdsep->next; /* set next pointer */
193
194 /* update and check update note status code */
195
196 if (0 EQ (gdsep->code = nctabp[gdsep->code])) {
197
198 /* if it's zero, delete the element */
199
200 gdprv->next = gdnxt;
201 gdsep->next = gdfsep;
202 gdfsep = gdsep;
203
204 } else
205 gdprv = gdsep;
206
207 gdsep = gdnxt; /* set pointer for next pass */
208
209 } while (gdsep);
210 }
211 }
212
213
214 for (; i < (NGDSEL - 1); i++) {
215
216 gdprv = (struct gdsel *)gdstp; /* setup previous pointer */
217 gdsep = *gdstp++; /* setup current pointer */
218
219 if (gdsep) { /* ... process each active event priority ... */
220
221 ++wrote; /* indicate slice was updated */
222
223 do { /* ... for each event of this priority ... */
224
225 /* setup slice and pixel pointers */
226
227 slptr = slice + 212;
228 pxptr = &epxtbl[gdsep->code][0];
229
230 /* get event color */
231
232 ncolor = mask1 & (uint16_t)gdsep->note;
233
234 /* update the slice */
235
236 if ((w = *pxptr++)) /* 212 */
237 *slptr = (*slptr & mask2) | (w & ncolor);
238
239 ++slptr;
240
241 if ((w = *pxptr++)) /* 213 */
242 *slptr = (*slptr & mask2) | (w & ncolor);
243
244 ++slptr;
245
246 if ((w = *pxptr++)) /* 214 */
247 *slptr = (*slptr & mask2) | (w & ncolor);
248
249 ++slptr;
250
251 if ((w = *pxptr++)) /* 215 */
252 *slptr = (*slptr & mask2) | (w & ncolor);
253
254 ++slptr;
255
256 if ((w = *pxptr++)) /* 216 */
257 *slptr = (*slptr & mask2) | (w & ncolor);
258
259 ++slptr;
260
261 if ((w = *pxptr++)) /* 217 */
262 *slptr = (*slptr & mask2) | (w & ncolor);
263
264 ++slptr;
265
266 if ((w = *pxptr++)) /* 218 */
267 *slptr = (*slptr & mask2) | (w & ncolor);
268
269 ++slptr;
270
271 if ((w = *pxptr++)) /* 219 */
272 *slptr = (*slptr & mask2) | (w & ncolor);
273
274 ++slptr;
275
276 if ((w = *pxptr++)) /* 220 */
277 *slptr = (*slptr & mask2) | (w & ncolor);
278
279 ++slptr;
280
281 if ((w = *pxptr++)) /* 221 */
282 *slptr = (*slptr & mask2) | (w & ncolor);
283
284 ++slptr;
285
286 if ((w = *pxptr++)) /* 222 */
287 *slptr = (*slptr & mask2) | (w & ncolor);
288
289 ++slptr;
290
291 if ((w = *pxptr)) /* 223 */
292 *slptr = (*slptr & mask2) | (w & ncolor);
293
294 gdnxt = gdsep->next; /* set next pointer */
295 gdprv->next = gdnxt; /* delete the element */
296 gdsep->next = gdfsep;
297 gdfsep = gdsep;
298 gdsep = gdnxt; /* set pointer for next pass */
299
300 } while (gdsep);
301 }
302 }
303
304 DB_EXIT(wrote ? "uslice - slice written" : "uslice - no write");
305
306 return(wrote);
307}
308
309/*
310 =============================================================================
311 rslice(gdstb)
312
313 Reverses the slice codes in 'gdstb' based the value of sd,
314 which is zero for forward, and non-zero for backward scrolling.
315 =============================================================================
316*/
317
318void rslice(struct gdsel *gdstb[])
319{
320 struct gdsel *gdsep;
321 struct gdsel **gdstp;
322 int16_t *nctabp;
323 uint16_t i;
324 struct gdsel *gdprv, *gdnxt;
325
326 DB_ENTR("rslice");
327
328#if DEBUGIT
329 if (debugsw)
330 printf("\nrslice($%lX): sd = %s\n", gdstb, sd ? "BAK" : "FWD");
331#endif
332
333 /* initialize note control and group control pointers */
334
335 nctabp = sd ? nttab2 : nttab1; /* note control table pointer */
336 gdstp = gdstb; /* group control table pointer */
337
338
339 /* reverse note codes */
340
341 for (i = 0; i < 12; i++) { /* scan the group control table ... */
342
343 gdprv = (struct gdsel *)gdstp; /* setup previous pointer */
344 gdsep = *gdstp++; /* setup current pointer */
345
346 if (gdsep) { /* ... process each active group ... */
347
348 do { /* ... for each note played by the group ... */
349
350 gdnxt = gdsep->next; /* set next pointer */
351
352 /* update and check update note status code */
353
354 if (0 EQ (gdsep->code = nctabp[gdsep->code])) {
355
356#if DEBUGIT
357 if (debugsw)
358 printf("rslice: note %d - %d -> %d\n",
359 gdsep->note, nc, gdsep->code);
360#endif
361
362 /* if it's zero, delete the element */
363
364 gdprv->next = gdnxt;
365 gdsep->next = gdfsep;
366 gdfsep = gdsep;
367
368 } else {
369
370#if DEBUGIT
371 if (debugsw)
372 printf("rslice: note %d - %d -> %d\n",
373 gdsep->note, nc, gdsep->code);
374#endif
375
376 gdprv = gdsep;
377 }
378
379 gdsep = gdnxt; /* set pointer for next pass */
380
381 } while (gdsep);
382 }
383 }
384
385
386 /* delete event codes */
387
388 for (; i < NGDSEL - 1; i++) {
389
390 gdprv = (struct gdsel *)gdstp; /* setup previous pointer */
391 gdsep = *gdstp++; /* setup current pointer */
392
393 if (gdsep) { /* ... process each active event priority ... */
394
395 do { /* ... for each event of this priority ... */
396
397 gdnxt = gdsep->next; /* set next pointer */
398 gdprv->next = gdnxt; /* delete the element */
399 gdsep->next = gdfsep;
400 gdfsep = gdsep;
401 gdsep = gdnxt; /* set pointer for next pass */
402
403 } while (gdsep);
404 }
405 }
406
407 gdstb[NGDSEL - 1] = (struct gdsel *)NULL; /* clear bar flag */
408
409 DB_EXIT("rslice");
410}
411
412/*
413 =============================================================================
414 cslice(slice, mask1, mask2, gdstb)
415
416 Updates 'slice[]' using 'mask1' and 'mask2' for the pixel mask
417 and the slice mask, respectively, using 'gdstb[]' as the group table.
418
419 Differs from uslice() in that no note gdstb events are deleted.
420 Used for center slice updates.
421
422 Note transitions are based on the value of global variable 'sd',
423 which is zero for forward, and non-zero for backward scrolling.
424
425 Returns count of active groups and event priority levels.
426
427 Note colors come from 'gtctab[]'.
428
429 This code has to be very fast.
430 =============================================================================
431*/
432
433int16_t cslice(volatile uint16_t *slice, uint16_t mask1, uint16_t mask2, struct gdsel *gdstb[])
434{
435 uint16_t *pxptr;
436 volatile uint16_t *slptr;
437 struct gdsel *gdsep;
438 uint16_t i, ncolor, w;
439 uint16_t *ncptr;
440 struct gdsel **gdstp, *gdprv, *gdnxt;
441 int16_t wrote;
442 int16_t *lintab;
443
444 DB_ENTR("cslice()");
445
446 /* initialize note color, note control, and group control pointers */
447
448 gdstp = gdstb; /* group control table */
449 ncptr = gtctab; /* group to color table */
450 wrote = 0; /* reset count of active groups */
451
452 lintab = (ac_code EQ N_SHARP) ? lintab1 : lintab2; /* line table */
453
454 if (gdstb[NGDSEL - 1]) { /* check for a bar marker */
455
456 slptr = slice; /* point at the slice */
457 ncolor = mask1 & BARCOLOR; /* setup bar write variable */
458
459 for (i = 211; i--; ) { /* draw the bar */
460 *slptr = (*slptr & mask2) | ncolor;
461 ++slptr;
462 }
463
464 gdstb[NGDSEL - 1] = (struct gdsel *)NULL; /* clear flag */
465 }
466
467 for (i = 0; i < 12; i++) { /* scan the group control table ... */
468
469 ncolor = *ncptr++; /* get note color */
470 gdprv = (struct gdsel *)gdstp; /* setup previous pointer */
471 gdsep = *gdstp++; /* setup current pointer */
472
473 if (gdsep) { /* ... process each active group ... */
474
475#ifdef DEBUGGER
476 sprintf(DBvar, "cslice - g=%d gdsep=$%lX", i, gdsep); DB_CMNT(DBvar);
477#endif
478 ++wrote; /* indicate slice was updated */
479
480 do { /* ... for each note played by the group ... */
481
482 /* setup slice and pixel pointers */
483
484 slptr = slice + lintab[gdsep->note];
485 pxptr = &pxtbl[gdsep->code][0];
486
487 /* update the slice */
488
489 *slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
490 ++slptr;
491 *slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
492 ++slptr;
493 *slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
494
495 gdnxt = gdsep->next; /* set nxt pointer */
496 gdprv = gdsep; /* set prv pointer */
497 gdsep = gdnxt; /* set pointer for next pass */
498
499 } while (gdsep);
500 }
501 }
502
503
504 for (; i < (NGDSEL - 1); i++) { /* scan the event priorities ... */
505
506 gdprv = (struct gdsel *)gdstp; /* setup previous pointer */
507 gdsep = *gdstp++; /* setup current pointer */
508
509 if (gdsep) { /* ... process each active event priority ... */
510
511 ++wrote; /* indicate slice was updated */
512
513 do { /* ... for each event of this priority ... */
514
515 /* setup slice and pixel pointers */
516
517 slptr = slice + 212;
518 pxptr = &epxtbl[gdsep->code][0];
519
520 ncolor = (uint16_t)gdsep->note; /* get event color */
521
522 /* update the slice */
523
524 if ((w = *pxptr++)) /* 212 */
525 *slptr = (*slptr & mask2) | (w & ncolor);
526
527 ++slptr;
528
529 if ((w = *pxptr++)) /* 213 */
530 *slptr = (*slptr & mask2) | (w & ncolor);
531
532 ++slptr;
533
534 if ((w = *pxptr++)) /* 214 */
535 *slptr = (*slptr & mask2) | (w & ncolor);
536
537 ++slptr;
538
539 if ((w = *pxptr++)) /* 215 */
540 *slptr = (*slptr & mask2) | (w & ncolor);
541
542 ++slptr;
543
544 if ((w = *pxptr++)) /* 216 */
545 *slptr = (*slptr & mask2) | (w & ncolor);
546
547 ++slptr;
548
549 if ((w = *pxptr++)) /* 217 */
550 *slptr = (*slptr & mask2) | (w & ncolor);
551
552 ++slptr;
553
554 if ((w = *pxptr++)) /* 218 */
555 *slptr = (*slptr & mask2) | (w & ncolor);
556
557 ++slptr;
558
559 if ((w = *pxptr++)) /* 219 */
560 *slptr = (*slptr & mask2) | (w & ncolor);
561
562 ++slptr;
563
564 if ((w = *pxptr++)) /* 220 */
565 *slptr = (*slptr & mask2) | (w & ncolor);
566
567 ++slptr;
568
569 if ((w = *pxptr++)) /* 221 */
570 *slptr = (*slptr & mask2) | (w & ncolor);
571
572 ++slptr;
573
574 if ((w = *pxptr++)) /* 222 */
575 *slptr = (*slptr & mask2) | (w & ncolor);
576
577 ++slptr;
578
579 if ((w = *pxptr)) /* 223 */
580 *slptr = (*slptr & mask2) | (w & ncolor);
581
582 gdnxt = gdsep->next; /* set next pointer */
583 gdprv->next = gdnxt; /* delete the element */
584 gdsep->next = gdfsep;
585 gdfsep = gdsep;
586 gdsep = gdnxt; /* set pointer for next pass */
587
588 } while (gdsep);
589 }
590 }
591
592 DB_EXIT(wrote ? "cslice - slice written" : "cslice - no write");
593
594 return(wrote);
595}
596
597/*
598 =============================================================================
599 clrsctl() -- clear slice control list and pointers
600 =============================================================================
601*/
602
603void clrsctl(void)
604{
605 register struct gdsel *gdsp, *gnxt, **gp;
606 register int16_t i;
607
608 gdfsep = gdsp = &gdfsl[0]; /* initialize slice control pool */
609 gnxt = &gdfsl[1];
610
611 for (i = MAXFSL - 1; i--; ) {
612
613 gdsp->code = 0;
614 gdsp->note = 0;
615 gdsp->next = gnxt;
616
617 gdsp++;
618 gnxt++;
619 }
620
621 gdsp->code = 0;
622 gdsp->note = 0;
623 gdsp->next = (struct gdsel *)0L;
624
625 gp = gdstbc; /* clear gdstbc */
626
627 for (i = NGDSEL; i--; )
628 *gp++ = (struct gdsel *)0L;
629
630 gp = gdstbn; /* clear gdstbn */
631
632 for (i = NGDSEL; i--; )
633 *gp++ = (struct gdsel *)0L;
634
635 gp = gdstbp; /* clear gdstbp */
636
637 for (i = NGDSEL; i--; )
638 *gp++ = (struct gdsel *)0L;
639
640 sbase = I_SBASE; /* initialize score video RAM offset */
641 soffset = I_OFFSET; /* initialize scroll register offset */
642 saddr = &v_score[sbase]; /* initialize score area base address */
643
644 consl = &slices[672]; /* initialize constant slice pointer */
645 prvsl = &slices[448]; /* initialize previous slice pointer */
646 cursl = &slices[224]; /* initialize current slice pointer */
647 nxtsl = &slices[0]; /* initialize next slice pointer */
648
649 {
650 volatile uint16_t *p1, *p2, *p3, *p4;
651 uint16_t sword;
652
653 p1 = consl; /* clear slices */
654 p2 = nxtsl;
655 p3 = cursl;
656 p4 = prvsl;
657
658 for (i = 224; i--; ) {
659
660 sword = *p1++;
661 *p2++ = sword;
662 *p3++ = sword;
663 *p4++ = sword;
664 }
665 }
666}
667
Note: See TracBrowser for help on using the repository browser.