7b68892cce63f8b293091b76190896d83be07820
[retrocrawl] / src / sprite.c
1 #include <string.h>
2 #include "sprite.h"
3 #include "hwregs.h"
4 #include "copper.h"
5
6 #define MAX_SPRITES     32
7
8 static int scount;
9 static struct sprite *spr[MAX_SPRITES];
10 static struct sprite *hwspr[4]; /* 4 channels because we support only attached sprites */
11
12 static uint16_t nullspr[] = {
13         0x2000, 0x2100,
14         0x0000, 0x0000,
15         0x0000, 0x0000
16 };
17 static uint32_t nullspr_addr = (intptr_t)nullspr;
18
19 static uint32_t *coplist;
20
21
22 void begin_sprites(void)
23 {
24         scount = 0;
25         memset(hwspr, 0, sizeof hwspr);
26
27         coplist = copperlist_end;
28 }
29
30 void end_sprites(void)
31 {
32         int i, j, reg;
33
34         copperlist_end = coplist;
35
36         /* initially point all sprites to the null sprite */
37         reg = REGN_SPR0PTH;
38         for(i=0; i<8; i++) {
39                 add_copper(COPPER_MOVE(reg, nullspr_addr >> 16));
40                 add_copper(COPPER_MOVE(reg + 2, nullspr_addr));
41                 reg += 4;
42         }
43
44         /* sort sprites by increasing start position */
45         for(i=0; i<scount; i++) {
46                 for(j=i+1; j<scount; j++) {
47                         if(spr[j]->y < spr[i]->y) {
48                                 struct sprite *tmp = spr[i];
49                                 spr[i] = spr[j];
50                                 spr[j] = tmp;
51                         }
52                 }
53         }
54
55         /* set sprite positions and populate copperlist to draw
56          * hardware sprites
57          */
58         for(i=0; i<scount; i++) {
59                 struct sprite *s = spr[i];
60                 uint16_t sx = 0x80 + s->x;
61                 uint16_t sy = 0x2c + s->y;
62                 uint16_t vstop = sy + s->height;
63                 uint32_t addr;
64                 int reuse = 0;
65
66                 int chan[4];
67                 int nchan_found = 0;
68                 for(j=0; j<4; j++) {
69                         if(!hwspr[j] || hwspr[j]->y + hwspr[j]->height < s->y) {
70                                 if(hwspr[j]) {
71                                         reuse = 1;
72                                 }
73                                 chan[nchan_found++] = j;
74                                 hwspr[j] = s;
75                                 if(nchan_found >= s->hwslices) {
76                                         break;
77                                 }
78                         }
79                 }
80                 if(nchan_found < s->hwslices) continue;
81
82                 if(reuse) {
83                         add_copper(COPPER_VWAIT(sy));
84                 }
85
86                 for(j=0; j<s->hwslices; j++) {
87                         int idx = chan[j] * 2;
88                         reg = REGN_SPR0PTH + idx * 4;
89
90                         s->hwspr[idx][0] = s->hwspr[idx + 1][0] = (sx >> 1) | (sy << 8);
91                         s->hwspr[idx][1] = s->hwspr[idx + 1][1] = (vstop << 8) |
92                                 ((vstop >> 7) & 2) | (sx & 1) | 0x80;
93
94                         addr = (intptr_t)s->hwspr[idx];
95                         add_copper(COPPER_MOVE(reg, addr >> 16));
96                         add_copper(COPPER_MOVE(reg + 2, addr));
97                         reg += 4;
98                         addr = (intptr_t)s->hwspr[idx + 1];
99                         add_copper(COPPER_MOVE(reg, addr >> 16));
100                         add_copper(COPPER_MOVE(reg + 2, addr));
101
102                         sx += 16;
103                 }
104         }
105
106         *copperlist_end = COPPER_END;
107         copperlist_end = coplist;
108 }
109
110 void draw_sprite(struct sprite *s, int x, int y)
111 {
112         if(s->img) {
113                 /* blitter sprite */
114         } else {
115                 /* hw sprites */
116                 spr[scount++] = s;
117                 s->x = x - s->origx;
118                 s->y = y - s->origy;
119         }
120 }