new sprite system first successfull test
[retrocrawl] / src / sprite.c
index 3a00881..7b68892 100644 (file)
@@ -1,21 +1,45 @@
 #include <string.h>
 #include "sprite.h"
+#include "hwregs.h"
+#include "copper.h"
 
 #define MAX_SPRITES    32
 
 static int scount;
-static sprite *spr[MAX_SPRITES];
-static sprite *hwspr[4];       /* 4 channels because we support only attached sprites */
+static struct sprite *spr[MAX_SPRITES];
+static struct sprite *hwspr[4];        /* 4 channels because we support only attached sprites */
+
+static uint16_t nullspr[] = {
+       0x2000, 0x2100,
+       0x0000, 0x0000,
+       0x0000, 0x0000
+};
+static uint32_t nullspr_addr = (intptr_t)nullspr;
+
+static uint32_t *coplist;
+
 
 void begin_sprites(void)
 {
        scount = 0;
-       memset(hwspr_used, 0, sizeof hwspr_used);
+       memset(hwspr, 0, sizeof hwspr);
+
+       coplist = copperlist_end;
 }
 
 void end_sprites(void)
 {
-       int i, j;
+       int i, j, reg;
+
+       copperlist_end = coplist;
+
+       /* initially point all sprites to the null sprite */
+       reg = REGN_SPR0PTH;
+       for(i=0; i<8; i++) {
+               add_copper(COPPER_MOVE(reg, nullspr_addr >> 16));
+               add_copper(COPPER_MOVE(reg + 2, nullspr_addr));
+               reg += 4;
+       }
 
        /* sort sprites by increasing start position */
        for(i=0; i<scount; i++) {
@@ -36,22 +60,51 @@ void end_sprites(void)
                uint16_t sx = 0x80 + s->x;
                uint16_t sy = 0x2c + s->y;
                uint16_t vstop = sy + s->height;
+               uint32_t addr;
+               int reuse = 0;
 
-               int chan = -1;
+               int chan[4];
+               int nchan_found = 0;
                for(j=0; j<4; j++) {
                        if(!hwspr[j] || hwspr[j]->y + hwspr[j]->height < s->y) {
-                               chan = j;
+                               if(hwspr[j]) {
+                                       reuse = 1;
+                               }
+                               chan[nchan_found++] = j;
                                hwspr[j] = s;
+                               if(nchan_found >= s->hwslices) {
+                                       break;
+                               }
                        }
                }
-               if(chan == -1) continue;
+               if(nchan_found < s->hwslices) continue;
+
+               if(reuse) {
+                       add_copper(COPPER_VWAIT(sy));
+               }
 
                for(j=0; j<s->hwslices; j++) {
+                       int idx = chan[j] * 2;
+                       reg = REGN_SPR0PTH + idx * 4;
+
                        s->hwspr[idx][0] = s->hwspr[idx + 1][0] = (sx >> 1) | (sy << 8);
                        s->hwspr[idx][1] = s->hwspr[idx + 1][1] = (vstop << 8) |
                                ((vstop >> 7) & 2) | (sx & 1) | 0x80;
+
+                       addr = (intptr_t)s->hwspr[idx];
+                       add_copper(COPPER_MOVE(reg, addr >> 16));
+                       add_copper(COPPER_MOVE(reg + 2, addr));
+                       reg += 4;
+                       addr = (intptr_t)s->hwspr[idx + 1];
+                       add_copper(COPPER_MOVE(reg, addr >> 16));
+                       add_copper(COPPER_MOVE(reg + 2, addr));
+
+                       sx += 16;
                }
        }
+
+       *copperlist_end = COPPER_END;
+       copperlist_end = coplist;
 }
 
 void draw_sprite(struct sprite *s, int x, int y)
@@ -61,7 +114,7 @@ void draw_sprite(struct sprite *s, int x, int y)
        } else {
                /* hw sprites */
                spr[scount++] = s;
-               s->x = x - origx;
-               s->y = y - origy;
+               s->x = x - s->origx;
+               s->y = y - s->origy;
        }
 }