sprites 256c, shadow oam, sprite transforms, sinlut
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 19 Apr 2021 14:10:27 +0000 (17:10 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 19 Apr 2021 14:10:27 +0000 (17:10 +0300)
13 files changed:
.gitignore
Makefile
src/data.h
src/data.s
src/dma.c
src/game.h
src/gamescr.c
src/main.c
src/sprite.c [new file with mode: 0644]
src/sprite.h [new file with mode: 0644]
src/util.h
tools/lutgen.c [new file with mode: 0644]
tools/tungen.c

index 226cf4e..929ef66 100644 (file)
@@ -7,6 +7,7 @@ cfg.mk
 *.a
 pngdump
 mmutil
+lutgen
 tungen
 *.ppm
 *.png
index 301519d..f89cedd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 src = $(wildcard src/*.c)
-ssrc = $(wildcard src/*.s)
+ssrc = $(wildcard src/*.s) data/lut.s
 obj = $(src:.c=.o) $(ssrc:.s=.o)
 dep = $(src:.c=.d)
 name = gbajam21
@@ -7,6 +7,7 @@ elf = $(name).elf
 bin = $(name).gba
 
 data = data/tuncross.raw data/tuncross.pal \
+          data/spr_game.raw data/spr_game.pal \
           data/tun.map
 
 audata = data/audio/popcorn.mod
@@ -50,6 +51,9 @@ src/data.o: src/data.s $(data)
 tools/pngdump/pngdump:
        $(MAKE) -C tools/pngdump
 
+tools/lutgen: tools/lutgen.c
+       cc -o $@ $< -lm
+
 tools/tungen: tools/tungen.c
        cc -o $@ $< -lm
 
@@ -65,6 +69,9 @@ tools/mmutil/mmutil:
 %.pal: %.png tools/pngdump/pngdump
        tools/pngdump/pngdump -o $@ -c $<
 
+data/lut.s: tools/lutgen
+       tools/lutgen >$@
+
 data/tun.map: tools/tungen
        tools/tungen -s 240x160 >$@
 
index 7d927c0..92a43cb 100644 (file)
@@ -12,6 +12,9 @@ extern unsigned char tuncross_cmap[];
 
 extern uint32_t tunmap[];
 
+extern unsigned char spr_game_pixels[];
+extern unsigned char spr_game_cmap[];
+
 extern unsigned char sound_data[];
 
 #endif /* DATA_H_ */
index 94949e7..d99f695 100644 (file)
@@ -3,6 +3,8 @@
        .globl tuncross_pixels
        .globl tuncross_cmap
        .globl tunmap
+       .globl spr_game_pixels
+       .globl spr_game_cmap
        .globl sound_data
 
        .align 1
@@ -15,5 +17,12 @@ tuncross_cmap:
        .align 2
 tunmap: .incbin "data/tun.map"
 
+       .align 1
+spr_game_pixels:
+       .incbin "data/spr_game.raw"
+       .align 1
+spr_game_cmap:
+       .incbin "data/spr_game.pal"
+
        .align 2
 sound_data: .incbin "data/snd.bin"
index 5de4faf..ba23ab7 100644 (file)
--- a/src/dma.c
+++ b/src/dma.c
 
 static volatile uint32_t *reg_dma[4] = {(void*)0x040000b0, (void*)0x040000bc, (void*)0x040000c8, (void*)0x040000d4 };
 
-void AAS_DoDMA3(void*, void*, uint32_t);
-
 /* --- perform a copy of words or halfwords using DMA --- */
 
 void dma_copy32(int channel, void *dst, void *src, int words, unsigned int flags)
 {
-#ifndef NOSOUND
-       if(channel == 3) {
-               AAS_DoDMA3(src, dst, words | flags | DMA_32 | DMA_ENABLE);
-               return;
-       }
-#endif
        reg_dma[channel][DMA_SRC] = (uint32_t)src;
        reg_dma[channel][DMA_DST] = (uint32_t)dst;
        reg_dma[channel][DMA_CTRL] = words | flags | DMA_32 | DMA_ENABLE;
@@ -44,12 +36,6 @@ void dma_copy32(int channel, void *dst, void *src, int words, unsigned int flags
 
 void dma_copy16(int channel, void *dst, void *src, int halfwords, unsigned int flags)
 {
-#ifndef NOSOUND
-       if(channel == 3) {
-               AAS_DoDMA3(src, dst, halfwords | flags | DMA_16 | DMA_ENABLE);
-               return;
-       }
-#endif
        reg_dma[channel][DMA_SRC] = (uint32_t)src;
        reg_dma[channel][DMA_DST] = (uint32_t)dst;
        reg_dma[channel][DMA_CTRL] = halfwords | flags | DMA_16 | DMA_ENABLE;
@@ -62,12 +48,6 @@ static uint32_t fill[4];
 void dma_fill32(int channel, void *dst, uint32_t val, int words)
 {
        fill[channel] = val;
-#ifndef NOSOUND
-       if(channel == 3) {
-               AAS_DoDMA3(fill + channel, dst, words | DMA_SRC_FIX | DMA_TIMING_IMMED | DMA_32 | DMA_ENABLE);
-               return;
-       }
-#endif
        reg_dma[channel][DMA_SRC] = (uint32_t)(fill + channel);
        reg_dma[channel][DMA_DST] = (uint32_t)dst;
        reg_dma[channel][DMA_CTRL] = words | DMA_SRC_FIX | DMA_TIMING_IMMED | DMA_32 | DMA_ENABLE;
@@ -76,12 +56,6 @@ void dma_fill32(int channel, void *dst, uint32_t val, int words)
 void dma_fill16(int channel, void *dst, uint16_t val, int halfwords)
 {
        fill[channel] = val;
-#ifndef NOSOUND
-       if(channel == 3) {
-               AAS_DoDMA3(fill + channel, dst, halfwords | DMA_SRC_FIX | DMA_TIMING_IMMED | DMA_16 | DMA_ENABLE);
-               return;
-       }
-#endif
        reg_dma[channel][DMA_SRC] = (uint32_t)(fill + channel);
        reg_dma[channel][DMA_DST] = (uint32_t)dst;
        reg_dma[channel][DMA_CTRL] = halfwords | DMA_SRC_FIX | DMA_TIMING_IMMED | DMA_16 | DMA_ENABLE;
index 376b26d..b290634 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef GAME_H_
 #define GAME_H_
 
+void (*screen_vblank)(void);
+
 void menuscr(void);
 void gamescr(void);
 
index f927cee..51df533 100644 (file)
@@ -1,30 +1,49 @@
 #include <stdlib.h>
 #include <string.h>
 #include "gbaregs.h"
+#include "game.h"
 #include "dma.h"
 #include "data.h"
 #include "util.h"
 #include "intr.h"
 #include "input.h"
+#include "sprite.h"
 #include "debug.h"
 
 static void draw_tunnel(void);
+static void vblank(void);
 
 static int nframes, backbuf;
 static uint16_t *vram[] = { (uint16_t*)VRAM_LFB_FB0_ADDR, (uint16_t*)VRAM_LFB_FB1_ADDR };
 static unsigned char *tex;
 static uint16_t bnstate;
 
+#define MAX_SPR                4
+static uint16_t oam[4 * MAX_SPR];
+
+static short x = 120, y = 80;
+static unsigned char rot;
+
 void gamescr(void)
 {
        int i;
        uint16_t *cdst;
        unsigned char *csrc;
 
-       REG_DISPCNT = 4 | DISPCNT_BG2 | DISPCNT_FB1;
+       REG_DISPCNT = 4 | DISPCNT_BG2 | DISPCNT_OBJ | DISPCNT_FB1;
 
        vblperf_setcolor(0xff);
 
+       /* sprite setup */
+       spr_setup(16, 16, spr_game_pixels, spr_game_cmap);
+
+       wait_vblank();
+       spr_clear();
+       spr_oam_clear(oam, 0);
+       spr_oam_clear(oam, 1);
+       spr_oam_clear(oam, 2);
+       spr_oam_clear(oam, 3);
+
        cdst = (uint16_t*)CRAM_BG_ADDR;
        csrc = tuncross_cmap;
        for(i=0; i<256; i++) {
@@ -38,13 +57,17 @@ void gamescr(void)
        tex = iwram_sbrk(32 * 32);
        memcpy(tex, tuncross_pixels, 32 * 32);
 
-       select_input(BN_DPAD);
+       /*select_input(BN_DPAD);*/
+
+       mask(INTR_VBLANK);
+       screen_vblank = vblank;
+       unmask(INTR_VBLANK);
 
        nframes = 0;
        for(;;) {
                backbuf = ++nframes & 1;
 
-               bnstate = get_input();
+               bnstate = ~REG_KEYINPUT;
 
                draw_tunnel();
 
@@ -66,8 +89,8 @@ static void draw_tunnel(void)
 
        zoffs = nframes;
 
-       if(bnstate & BN_LEFT) uoffs++;
-       if(bnstate & BN_RIGHT) uoffs--;
+       if(bnstate & BN_LT) uoffs++;
+       if(bnstate & BN_RT) uoffs--;
 
        top = vram[backbuf];
        bot = vram[backbuf] + 159 * 240 / 2;
@@ -106,3 +129,45 @@ static void draw_tunnel(void)
                bot -= 240;
        }
 }
+
+__attribute__((noinline, target("arm"), section(".iwram")))
+static void vblank(void)
+{
+       uint16_t bnstate;
+       int16_t mat[4];
+       static short gate_speed;
+
+       bnstate = ~REG_KEYINPUT;
+       if(bnstate & BN_DPAD) {
+               if(gate_speed < 5) {
+                       gate_speed++;
+               }
+
+               if(bnstate & BN_LEFT) x -= gate_speed;
+               if(bnstate & BN_RIGHT) x += gate_speed;
+               if(bnstate & BN_UP) y -= gate_speed;
+               if(bnstate & BN_DOWN) y += gate_speed;
+
+               if(x < 0) x = 0;
+               if(x > 239) x = 239;
+               if(y < 0) y = 0;
+               if(y > 159) y = 159;
+       } else {
+               gate_speed = 0;
+       }
+
+       if(bnstate & BN_A) rot--;
+       if(bnstate & BN_B) rot++;
+
+       spr_oam(oam, 0, 512 + 256, x - 64, y - 64, SPR_256COL | SPR_SZ64 | SPR_DBLSZ |
+                       SPR_ROTSCL | SPR_ROTSCL_SEL(0));
+
+       mat[0] = COS(rot) << 1;
+       mat[1] = -SIN(rot) << 1;
+       mat[2] = SIN(rot) << 1;
+       mat[3] = COS(rot) << 1;
+       spr_transform(oam, 0, mat);
+
+
+       dma_copy16(3, (void*)OAM_ADDR, oam, sizeof oam / 2, 0);
+}
index 9b3b0e8..e1c3af0 100644 (file)
@@ -7,6 +7,7 @@
 #include "maxmod.h"
 
 static void vblank(void);
+static void nopfunc(void);
 
 int main(void)
 {
@@ -19,6 +20,8 @@ int main(void)
        mmStart(MOD_POPCORN, MM_PLAY_LOOP);
 #endif
 
+       screen_vblank = nopfunc;
+
        intr_disable();
        interrupt(INTR_VBLANK, vblank);
        REG_DISPSTAT |= DISPSTAT_IEN_VBLANK;
@@ -35,8 +38,14 @@ static void vblank(void)
 {
        vblperf_count++;
 
+       screen_vblank();
+
 #ifndef NOSOUND
        mmVBlank();
        mmFrame();
 #endif
 }
+
+static void nopfunc(void)
+{
+}
diff --git a/src/sprite.c b/src/sprite.c
new file mode 100644 (file)
index 0000000..e4253fb
--- /dev/null
@@ -0,0 +1,79 @@
+#include "sprite.h"
+#include "gbaregs.h"
+
+
+void spr_setup(int xtiles, int ytiles, unsigned char *pixels, unsigned char *cmap)
+{
+       int i, j, num_tiles;
+       uint16_t *cptr, *src, *dst;
+
+       num_tiles = xtiles * ytiles;
+       dst = (uint16_t*)VRAM_LFB_OBJ_ADDR;
+       src = (uint16_t*)pixels;
+       for(i=0; i<num_tiles; i++) {
+               /* copy every row of tile i (8x8) */
+               for(j=0; j<8; j++) {
+                       *dst++ = src[j * 64];
+                       *dst++ = src[j * 64 + 1];
+                       *dst++ = src[j * 64 + 2];
+                       *dst++ = src[j * 64 + 3];
+               }
+               src += 4;
+
+               if((i & 15) == 15) {
+                       src += 7 * 64;  /* skip to the next row of tiles (skip 7 rows of pixels) */
+               }
+       }
+
+       cptr = (uint16_t*)CRAM_OBJ_ADDR;
+       for(i=0; i<256; i++) {
+               unsigned char r = *cmap++ >> 3;
+               unsigned char g = *cmap++ >> 3;
+               unsigned char b = *cmap++ >> 3;
+               *cptr++ = r | (g << 5) | (b < 10);
+       }
+}
+
+void spr_clear(void)
+{
+       int i;
+
+       for(i=0; i<128; i++) {
+               spr_oam_clear(0, i);
+       }
+}
+
+void spr_oam(uint16_t *oam, int idx, int spr, int x, int y, unsigned int flags)
+{
+       if(!oam) oam = (uint16_t*)OAM_ADDR;
+
+       oam += idx << 2;
+
+       oam[0] = (y & 0xff) | (flags & 0xff00);
+       oam[1] = (x & 0x1ff) | ((flags >> 8) & 0xfe00);
+       oam[2] = (spr & 0x3ff) | ((flags & 3) << 10);
+}
+
+void spr_spr_oam(uint16_t *oam, int idx, struct sprite *spr)
+{
+       int i;
+       struct hwsprite *s;
+
+       s = spr->hwspr;
+       for(i=0; i<spr->num_hwspr; i++) {
+               spr_oam(oam, idx, s->id, spr->x + s->x, spr->y + s->y, s->flags);
+               s++;
+       }
+}
+
+void spr_transform(uint16_t *oam, int idx, int16_t *mat)
+{
+       if(!oam) oam = (uint16_t*)OAM_ADDR;
+
+       oam += (idx << 4) + 3;
+
+       oam[0] = *mat++;
+       oam[4] = *mat++;
+       oam[8] = *mat++;
+       oam[12] = *mat;
+}
diff --git a/src/sprite.h b/src/sprite.h
new file mode 100644 (file)
index 0000000..27d16ff
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef SPRITE_H_
+#define SPRITE_H_
+
+#include <stdint.h>
+
+enum {
+       SPR_ROTSCL      = 0x0100,
+       SPR_DBLSZ       = 0x0200,
+       SPR_BLEND       = 0x0400,
+       SPR_OBJWIN      = 0x0800,
+       SPR_MOSAIC      = 0x1000,
+       SPR_256COL      = 0x2000,
+       SPR_HRECT       = 0x4000,
+       SPR_VRECT       = 0x8000,
+
+       SPR_HFLIP       = 0x100000,
+       SPR_VFLIP       = 0x200000,
+       SPR_SZ16        = 0x400000,
+       SPR_SZ32        = 0x800000,
+       SPR_SZ64        = 0xc00000
+};
+#define SPR_SZ8                0
+#define SPR_ROTSCL_SEL(x)      ((unsigned int)(x) << 17)
+#define SPR_PRIO(x)                    ((unsigned int)(x) & 3)
+
+
+struct hwsprite {
+       short id;
+       short width, height;
+       short x, y;
+       unsigned int flags;
+};
+
+struct sprite {
+       short x, y;
+       struct hwsprite hwspr[8];
+       short num_hwspr;
+};
+
+void spr_setup(int xtiles, int ytiles, unsigned char *pixels, unsigned char *cmap);
+void spr_clear(void);
+
+#define spr_oam_clear(oam, idx) spr_oam(oam, idx, 0, 0, 160, 0)
+void spr_oam(uint16_t *oam, int idx, int spr, int x, int y, unsigned int flags);
+void spr_spr_oam(uint16_t *oam, int idx, struct sprite *spr);
+
+/* idx is the rotation/scale parameter index (0-31), not the sprite index */
+void spr_transform(uint16_t *oam, int idx, int16_t *mat);
+
+
+#endif /* SPRITE_H_ */
index d374aef..5181ba1 100644 (file)
                ((uint16_t*)CRAM_BG_ADDR)[idx] = (uint16_t)(r) | ((uint16_t)(g) << 5) | ((uint16_t)(b) << 10); \
        } while(0)
 
+extern int8_t sinlut[];
+
+#define SIN(x) sinlut[(x) & 0xff]
+#define COS(x) sinlut[((x) + 64) & 0xff]
+
 int iwram_brk(void *addr);
 void *iwram_sbrk(intptr_t delta);
 
diff --git a/tools/lutgen.c b/tools/lutgen.c
new file mode 100644 (file)
index 0000000..c3f003a
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <math.h>
+
+int main(void)
+{
+       int i;
+
+       puts("\t.data");
+       puts("\t.globl sinlut");
+       puts("sinlut:");
+       for(i=0; i<256; i++) {
+               float x = sin((float)i / 128.0f * M_PI);
+               printf("\t.byte %d\n", (int)(x * 127.5f - 0.5f));
+       }
+       return 0;
+}
index 4148b26..62e0d63 100644 (file)
@@ -87,7 +87,12 @@ invalopt:    fprintf(stderr, "invalid argument: %s\n", argv[i]);
                        float u = ptr->x;
                        float v = ptr->y;
                        int r = (int)(u * 8.0 * 255.0f) & 0xff;
-                       int b = (int)(v * 8.0 * 255.0f) & 0xff;
+                       int g = (int)(v * 8.0 * 255.0f) & 0xff;
+                       int b = (~(int)(v * 0.5 * 255.0f) & 0xff) + 105;
+                       if(b > 255) b = 255;
+                       if(b < 0) b = 0;
+
+                       /*if(v > 2.0) r = g = b = 0;*/
 
                        ptr++;
 
@@ -97,7 +102,7 @@ invalopt:    fprintf(stderr, "invalid argument: %s\n", argv[i]);
 
                        if(fp) {
                                fputc(r, fp);
-                               fputc(0, fp);
+                               fputc(g, fp);
                                fputc(b, fp);
                        }
                }