Files
2014-01-18 15:06:11 +01:00

559 lines
11 KiB
C
Raw Permalink Blame History

#include <nds.h>
#include "options.h"
// Commands
#define CMTXMODE 0x10
#define CMTXPUSH 0x11
#define CMTXPOP 0x12
#define CMTXIDENTITY 0x15
#define CMTXLOAD4x4 0x16
#define CMTXLOAD4x3 0x17
#define CMTXMULT3x3 0x1A
#define CMTXSCALE 0x1B
#define CMTXTRANSLATE 0x1C
#define CCOLOR 0x20
#define CNORMAL 0x21
#define CVERTEX 0x24
#define CPOLYATTR 0x29
#define CDIFAMB 0x30
#define CLIGHTVECTOR 0x32
#define CLIGHTCOLOR 0x33
#define CBEGIN 0x40
#define CVIEWPORT 0x60
// Parameters
#define PROJECTION 0
#define MODELVIEW 2
#define QUAD 1
#define NORMAL(x,y,z) (((x)&0x3FF)|(((y)&0x3FF)<<10)|(((z)&0x3FF)<<20))
#define VERTEX(x,y,z) \
(((x)&0x3FF)|(((y)&0x3FF)<<10)|(((z)&0x3FF)<<20))
#define DIFAMB(dif,amb) ((dif)|((amb)<<16))
#define VIEWPORT(x1,y1,x2,y2) ((x1)|((y1)<<8)|((x2)<<16)|((y2)<<24))
// Polygon attributes
#define LIGHT0 BIT(0)
#define POLYFRONT BIT(7)
#define POLYBACK BIT(6)
#define SOLID (31<<16)
#define WIREFRAME (0<<16)
// FIFO command packer
#define COMMAND(a,b,c,d) \
(((a)&0xFF)|(((b)&0xFF)<<8)|(((c)&0xFF)<<16)|(((d)&0xFF)<<24))
int uber_sin(int x)
{
x = 4096 - (x & 0x1FFF);
int ax = x;
if ( ax < 0 )
ax = -ax;
return 4 * x - ((4 * x * ax) >> 12);
}
#define uber_cos(x) uber_sin(x + 0x800)
#undef B
#undef C
void callList(u32 * list, int size)
{
DMA_SRC(0) = (unsigned int) list;
DMA_DEST(0) = 0x4000400; //GXFIFO
DMA_CR(0) = DMA_FIFO | size;
while ( DMA_CR(0) & DMA_BUSY )
;
}
u32 bglist[] =
{
COMMAND(CCOLOR, CVERTEX, CVERTEX, CCOLOR),
RGB15(31, 31, 31),
VERTEX(-4*64, -4*64, 0),
VERTEX( 4*64, -4*64, 0),
RGB15(12, 12, 31),
COMMAND(CVERTEX, CVERTEX, 0, 0),
VERTEX( 4*64, 4*64, 0),
VERTEX(-4*64, 4*64, 0),
};
#define bg() callList(bglist, sizeof(bglist)/sizeof(u32))
u32 cubelist[] =
{
COMMAND(CDIFAMB, CBEGIN, CNORMAL, CVERTEX),
DIFAMB(RGB15(16, 16, 16), RGB15(8, 8, 8)),
QUAD,
NORMAL(0, 512, 0),
VERTEX(-64,-64,-64),
COMMAND(CVERTEX, CVERTEX, CVERTEX, CNORMAL),
VERTEX( 64,-64,-64),
VERTEX( 64,-64, 64),
VERTEX(-64,-64, 64),
NORMAL(0, 511, 0),
COMMAND(CVERTEX, CVERTEX, CVERTEX, CVERTEX),
VERTEX(-64, 64,-64),
VERTEX(-64, 64, 64),
VERTEX( 64, 64, 64),
VERTEX( 64, 64,-64),
COMMAND(CNORMAL, CVERTEX, CVERTEX, CVERTEX),
NORMAL(512, 0, 0),
VERTEX(-64,-64,-64),
VERTEX(-64,-64, 64),
VERTEX(-64, 64, 64),
COMMAND(CVERTEX, CNORMAL, CVERTEX, CVERTEX),
VERTEX(-64, 64,-64),
NORMAL(511, 0, 0),
VERTEX( 64,-64,-64),
VERTEX( 64, 64,-64),
COMMAND(CVERTEX, CVERTEX, CNORMAL, CVERTEX),
VERTEX( 64, 64, 64),
VERTEX( 64,-64, 64),
NORMAL( 0, 0, 512),
VERTEX(-64,-64,-64),
COMMAND(CVERTEX, CVERTEX, CVERTEX, CNORMAL),
VERTEX(-64, 64,-64),
VERTEX( 64, 64,-64),
VERTEX( 64,-64,-64),
NORMAL( 0, 0, 511),
COMMAND(CVERTEX, CVERTEX, CVERTEX, CVERTEX),
VERTEX(-64,-64, 64),
VERTEX( 64,-64, 64),
VERTEX( 64, 64, 64),
VERTEX(-64, 64, 64),
};
#define cube() callList(cubelist, sizeof(cubelist)/sizeof(u32))
u32 initlist[] =
{
COMMAND(CVIEWPORT, CMTXMODE, CMTXLOAD4x4, CMTXMODE),
VIEWPORT(0, 0, 255, 191),
PROJECTION,
// Projection matrix Perspective(fov=50<35>, near=0.1, far=40, ratio=1.33)
6587, 0, 0, 0,
0, 8783, 0, 0,
0, 0, -4116, -4096,
0, 0, -821, 0,
MODELVIEW,
COMMAND(CPOLYATTR, CMTXIDENTITY, CLIGHTVECTOR, CLIGHTCOLOR),
LIGHT0|POLYFRONT|SOLID,
NORMAL(-96, -144, -482),
RGB15(31, 31, 31),
};
#define init() callList(initlist, sizeof(initlist)/sizeof(u32))
int abs(int x)
{
return ( x < 0 ) ? -x : x;
}
int min(int a, int b)
{
return ( a < b ) ? a : b;
}
// input : fixed .12
// output : fixed .12
int sin(int x)
{
// translate x into [-pi, pi].f12
while ( x > 12868 )
x -= 25736;
while ( x < -12868 )
x += 25736;
// compute sin(x)
// see http://www.devmaster.net/forums/showthread.php?t=5784
const int B = 5215;
const int C = -1660;
return (B*x + ((C*x)>>12)*abs(x))>>12;
}
int cos(int x)
{
x += 6434;
return sin(x);
}
inline void push()
{
MATRIX_PUSH = 0;
}
inline void pop()
{
MATRIX_POP = 1;
}
inline void identity()
{
MATRIX_IDENTITY = 0;
}
inline void translate(int x, int y, int z)
{
MATRIX_TRANSLATE = x;
MATRIX_TRANSLATE = y;
MATRIX_TRANSLATE = z;
}
inline void scale(int x, int y, int z)
{
MATRIX_SCALE = x;
MATRIX_SCALE = y;
MATRIX_SCALE = z;
}
void rotate(int angle, int x, int y, int z)
{
int s = sin(angle);
int c = cos(angle);
MATRIX_MULT3x3 = (x == 0) ? c : 1<<12;
MATRIX_MULT3x3 = z * s;
MATRIX_MULT3x3 = y * -s;
MATRIX_MULT3x3 = z * -s;
MATRIX_MULT3x3 = (y == 0) ? c : 1<<12;
MATRIX_MULT3x3 = x * s;
MATRIX_MULT3x3 = y * s;
MATRIX_MULT3x3 = x * -s;
MATRIX_MULT3x3 = (z == 0) ? c : 1<<12;
}
void uber_rotate(int angle, int x, int y, int z)
{
int s = uber_sin(angle);
int c = uber_cos(angle);
MATRIX_MULT3x3 = (x == 0) ? c : 1<<12;
MATRIX_MULT3x3 = z * s;
MATRIX_MULT3x3 = y * -s;
MATRIX_MULT3x3 = z * -s;
MATRIX_MULT3x3 = (y == 0) ? c : 1<<12;
MATRIX_MULT3x3 = x * s;
MATRIX_MULT3x3 = y * s;
MATRIX_MULT3x3 = x * -s;
MATRIX_MULT3x3 = (z == 0) ? c : 1<<12;
}
#define rotateX(angle) rotate(angle, 1, 0, 0)
#define rotateY(angle) rotate(angle, 0, 1, 0)
#define rotateZ(angle) rotate(angle, 0, 0, 1)
#define uber_rotateX(angle) uber_rotate(angle, 1, 0, 0)
#define uber_rotateY(angle) uber_rotate(angle, 0, 1, 0)
#define uber_rotateZ(angle) uber_rotate(angle, 0, 0, 1)
void arms(int t, int m)
{
push();
// translate(0.24f*m, 0.4f, 0);
translate(983*m, 1638, 0);
// rotateZ(30<33>*m);
rotateZ(2145*m);
// rotateX(cos(t)*20<32>+180<38>);
rotateX(((cos(t)*1430)>>12)+12868);
// translate(0, 0.3, 0);
translate(0, 1229, 0);
push();
// scale(0.1, 0.3, 0.1);
scale(410, 1229, 410);
cube();
pop();
// translate(0, 0.22, 0);
translate(0, 901, 0);
// rotateY(abs(cos(t))*16*m);
rotateY((abs(cos(t)*1144)>>12)*m);
// rotateX(100<30>);
rotateX(7149);
// rotateZ(165<36>*m);
rotateZ(11796*m);
// translate(0, 0.21, 0);
translate(0, 860, 0);
push();
// scale(0.09, 0.27, 0.09);
scale(369, 1106, 369);
cube();
pop();
pop();
}
void legs(int t, int m)
{
push();
// translate(0.19*m, 0, -0.015);
translate(778*m, 0, -61);
// rotateX(cos(t)*13<31>-2.5);
rotateX(((cos(t)*929)>>12)-228);
// translate(0, -0.7, 0);
translate(0, -2867, 0);
push();
// scale(0.1, 0.25, 0.1);
scale(410, 1024, 410);
cube();
pop();
// float d = -min(0, cos(t+3.14157/2));
int d = -min(0, cos(t+6434));
// translate(0, d*0.15-0.52, d*0.015-0.06);
translate(0, ((d*614)>>12)-2130, ((d*61)>>12)-246);
// rotateX(10<31>);
rotateX(715);
push();
// scale(0.1, 0.3, 0.1);
scale(410, 1229, 410);
cube();
pop();
// translate(0, -0.3, 0.1);
translate(0, -1229, 410);
push();
// scale(0.1, 0.03, 0.2);
scale(410, 123, 819);
cube();
pop();
pop();
}
void robot(int t)
{
// head
push();
// translate(0, 0.71+0.05*abs(sin(t)), 0.04);
translate(0, 2908+((abs(sin(t))*204)>>12), 164);
// rotateX(-5<>+10<31>*abs(cos(t)));
rotateX((-357+715*abs(cos(t)))>>12);
// scale(0.2, 0.2, 0.2);
scale(819, 819, 819);
cube();
pop();
// body
push();
// translate(0, 0.05*abs(sin(t)), 0);
translate(0, (abs(sin(t))*204)>>12, 0);
// rotateY(2.5<EFBFBD>-5<>*cos(t));
rotateY(179-((357*cos(t))>>12));
// scale(0.3, 0.5, 0.17);
scale(1229, 2048, 696);
cube();
pop();
// left side
arms(t, -1);
legs(t, -1);
// right side
t += 12868;
arms(t, 1);
legs(t, 1);
}
// r * cos((x*pi/2)/r) * cos((y*pi/2)/r) - r
int f(int x, int y)
{
const int r = 25;
return (r * (uber_cos(x) * uber_cos(y))>>18) - (r<<6);
}
void sonic(int t)
{
int i = 0;
int y, x;
const u16 colors[2] = { RGB15(29, 15, 4), RGB15(4, 11, 28) };
for ( y = -7*64+t ; y < 6*64+t ; y += 64 ) {
for ( x = -7*64 ; x < 6*64 ; x += 64 ) {
GFX_VERTEX10 = VERTEX(x, f(x, y), y);
GFX_VERTEX10 = VERTEX(x, f(x, y+64), y+64);
GFX_VERTEX10 = VERTEX(x+64, f(x+64, y+64), y+64);
GFX_VERTEX10 = VERTEX(x+64, f(x+64, y), y);
// -4B by putting next two lines at the end of this loop
GFX_COLOR = colors[i&1];
i++;
}
//i++;
}
}
#if STDLIB
int main()
#else
void Main()
#endif
{
int t = 0;
#if CAMERA
int rX = 0, rrX = 0;
int rY = 0, rrY = 0;
int tX = 0;
int tY = 0;
int tZ = 0;
touchPosition start;
touchPosition now;
#endif
// initialize 3D
REG_POWERCNT = POWER_ALL;
#if SAFE
while ( GFX_STATUS & BIT(27) )
;
GFX_STATUS |= BIT(29); // clear fifo
GFX_FLUSH = 0;
GFX_CONTROL = 0;
#endif
GFX_CLEAR_DEPTH = 0x7FFF;
GFX_CONTROL = GL_ANTIALIAS;
GFX_CLEAR_COLOR = 0x3F1F0000; // black, alpha=31, id=63
init();
// Initialize 2D Engines
REG_DISPCNT = MODE_0_2D
| DISPLAY_BG0_ACTIVE
| ENABLE_3D;
REG_DISPCNT_SUB = MODE_5_2D
| DISPLAY_BG3_ACTIVE
| DISPLAY_SPR_ACTIVE
| DISPLAY_SPR_2D
| DISPLAY_SPR_2D_BMP_256;
// Init SUB BG0
//VRAM_C_CR = VRAM_C_SUB_BG | VRAM_ENABLE;
REG_BG3CNT_SUB = BG_BMP16_256x256;
REG_BG3PA_SUB = 1<<8;
#if SAFE
REG_BG3PB_SUB = 0;
REG_BG3PC_SUB = 0;
#endif
REG_BG3PD_SUB = 1<<8;
// Init sprites to display like a big bitmap background
//VRAM_D_CR = VRAM_D_SUB_SPRITE | VRAM_ENABLE;
int y, x;
u16 * ptr = OAM_SUB;
for ( y = 0 ; y < 3 ; y++ ) {
for ( x = 0 ; x < 4 ; x++ ) {
// attribute 0
*ptr++ = ATTR0_BMP | (y*64); // attr0
// attribute 1
*ptr++ = ATTR1_SIZE_64 | (x*64); // attr1
// attribute 2
*ptr++ = ATTR2_ALPHA(15) | (x*8+y*256);
// pad/matrix
*ptr++;
}
}
while ( 1 ) {
identity();
if ( t&1 ) {
REG_POWERCNT &= ~POWER_SWAP_LCDS; // main on bottom
VRAM_C_CR = VRAM_ENABLE;
VRAM_D_CR = VRAM_D_SUB_SPRITE | VRAM_ENABLE;
REG_DISPCAPCNT = DCAP_BANK(2) | DCAP_ENABLE | DCAP_SIZE(3);
//rotateX(-t+512);
} else {
REG_POWERCNT |= POWER_SWAP_LCDS; // main on top
VRAM_C_CR = VRAM_C_SUB_BG | VRAM_ENABLE;
VRAM_D_CR = VRAM_ENABLE;
REG_DISPCAPCNT = DCAP_BANK(3) | DCAP_ENABLE | DCAP_SIZE(3);
rotateZ(8192);
rotateX(6144);
translate(0, -4*4096, 9216);
}
#if 0
#if CAMERA
rotateX((rX+rrX) * DEGREES_IN_CIRCLE / 360.0);
rotateY((rY+rrY) * DEGREES_IN_CIRCLE / 360.0);
translate(tX, tZ, tY);
#endif
#endif
translate(0, 1024, -4096);
push();
translate(0, 128, -11059);
rotateX(-512);
scale(0, 0, 0);
robot(t*402);
pop();
push();
translate(0, 0, -40960);
scale(20480, 8192, 4096);
bg();
pop();
push();
translate(0, -9216, -20480);
uber_rotateX((rX+rrX)*16);
sonic(-(t*2)&127);
pop();
GFX_FLUSH = 0;
t++;
#if CAMERA
scanKeys();
// look around
u16 keys = keysDown();
if ( keys & KEY_TOUCH )
touchRead(& start);
keys = keysUp();
if ( keys & KEY_TOUCH ) {
rX = rX + rrX;
rY = rY + rrY;
rrX = 0;
rrY = 0;
}
keys = keysHeld();
if ( keys & KEY_TOUCH ) {
touchRead(& now);
rrX = now.py - start.py;
rrY = now.px - start.px;
}
// world move
if ( keys & KEY_UP ) tY += 128;
if ( keys & KEY_DOWN ) tY -= 128;
if ( keys & KEY_LEFT ) tX += 128;
if ( keys & KEY_RIGHT ) tX -= 128;
if ( keys & KEY_L ) tZ += 128;
if ( keys & KEY_R ) tZ -= 128;
// reset
if ( keys & KEY_SELECT ) { rX = rY = tX = tY = tZ = 0; }
#endif
}
#if STDLIB
return 0;
#endif
}