*.a
pngdump
mmutil
+lutgen
tungen
*.ppm
*.png
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
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
tools/pngdump/pngdump:
$(MAKE) -C tools/pngdump
+tools/lutgen: tools/lutgen.c
+ cc -o $@ $< -lm
+
tools/tungen: tools/tungen.c
cc -o $@ $< -lm
%.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 >$@
extern uint32_t tunmap[];
+extern unsigned char spr_game_pixels[];
+extern unsigned char spr_game_cmap[];
+
extern unsigned char sound_data[];
#endif /* DATA_H_ */
.globl tuncross_pixels
.globl tuncross_cmap
.globl tunmap
+ .globl spr_game_pixels
+ .globl spr_game_cmap
.globl sound_data
.align 1
.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"
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;
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;
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;
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;
#ifndef GAME_H_
#define GAME_H_
+void (*screen_vblank)(void);
+
void menuscr(void);
void gamescr(void);
#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++) {
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();
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;
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);
+}
#include "maxmod.h"
static void vblank(void);
+static void nopfunc(void);
int main(void)
{
mmStart(MOD_POPCORN, MM_PLAY_LOOP);
#endif
+ screen_vblank = nopfunc;
+
intr_disable();
interrupt(INTR_VBLANK, vblank);
REG_DISPSTAT |= DISPSTAT_IEN_VBLANK;
{
vblperf_count++;
+ screen_vblank();
+
#ifndef NOSOUND
mmVBlank();
mmFrame();
#endif
}
+
+static void nopfunc(void)
+{
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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_ */
((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);
--- /dev/null
+#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;
+}
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++;
if(fp) {
fputc(r, fp);
- fputc(0, fp);
+ fputc(g, fp);
fputc(b, fp);
}
}