示例#1
0
文件: render.cpp 项目: jsykes/starkas
void Render::InitBackgrounds()
{
    /*  Set up affine background 3 on main as a 16-bit color background. */
    REG_BG3CNT = BG_BMP16_256x256 |
                 BG_BMP_BASE(0) | // The starting place in memory
                 BG_PRIORITY(3); // A low priority

    /*  Set the affine transformation matrix for the main screen background 3
     *  to be the identity matrix.
     */
    REG_BG3PA = 1 << 8;
    REG_BG3PB = 0;
    REG_BG3PC = 0;
    REG_BG3PD = 1 << 8;

    /*  Place main screen background 3 at the origin (upper left of the
     *  screen).
     */
    REG_BG3X = 0;
    REG_BG3Y = 0;

    /*  Set up affine background 2 on main as a 16-bit color background. */
    REG_BG2CNT = BG_BMP16_256x256 |
                 BG_BMP_BASE(8) | // The starting place in memory
                 BG_PRIORITY(2);  // A higher priority

    /*  Set the affine transformation matrix for the main screen background 3
     *  to be the identity matrix.
     */
    REG_BG2PA = 1 << 8;
    REG_BG2PB = 0;
    REG_BG2PC = 0;
    REG_BG2PD = 1 << 8;

    /*  Place main screen background 2 in an interesting place. */
    REG_BG2X = -(SCREEN_WIDTH / 2 - 32) << 8;
    REG_BG2Y = -32 << 8;

    /*  Set up affine background 3 on the sub screen as a 16-bit color
     *  background.
     */
    REG_BG3CNT_SUB = BG_BMP16_256x256 |
                     BG_BMP_BASE(9) | // The starting place in memory
                     BG_PRIORITY(3); // A low priority

    /*  Set the affine transformation matrix for the sub screen background 3
     *  to be the identity matrix.
     */
    REG_BG3PA_SUB = 1 << 8;
    REG_BG3PB_SUB = 0;
    REG_BG3PC_SUB = 0;
    REG_BG3PD_SUB = 1 << 8;

    /*
     *  Place main screen background 3 at the origin (upper left of the screen)
     */
    REG_BG3X_SUB = 0;
    REG_BG3Y_SUB = 0;
}
示例#2
0
/* Fondo sistema konfiguratzeko prozedura */
void hasieratuFondoak() {
    /*  Pantaila nagusiko 3 fondoaren afinitatea ezarri 16 biteko koloretarako. */
    REG_BG3CNT = BG_BMP16_256x256 |
                 BG_BMP_BASE(0) | // Memoriako hasierako helbidea
                 BG_PRIORITY(3); // Lehentasun baxua

    /*  Pantaila nagusiko 3 fondoaren transformazio matrizeari identitate matrizea esleitu. */
    REG_BG3PA = 1 << 8;
    REG_BG3PB = 0;
    REG_BG3PC = 0;
    REG_BG3PD = 1 << 8;

/*******************************************************************************************/
    /*  Pantaila nagusiko 3 fondoaren egoera definitu. */
    /*  Grafikoa beste posizio batean jarri nahi izanez gero hau aldatu beharko da. */
    REG_BG3X = 0;
    REG_BG3Y = 0;
/*******************************************************************************************/

    /*  Pantaila nagusiko 3 fondoaren afinitatea ezarri 16 biteko koloretarako. */
    REG_BG2CNT = BG_BMP16_128x128 |
                 BG_BMP_BASE(8) | // Memoriako hasierako helbidea
                 BG_PRIORITY(2);  // Lehentasun baxua

    /*  Pantaila nagusiko 3 fondoaren transformazio matrizeari identitate matrizea esleitu. */
    REG_BG2PA = 1 << 8;
    REG_BG2PB = 0;
    REG_BG2PC = 0;
    REG_BG2PD = 1 << 8;

/*******************************************************************************************/
    /*  Pantaila nagusiko 3 fondoaren egoera definitu. */
    /*  Grafikoa beste posizio batean jarri nahi izanez gero hau aldatu beharko da. */
    REG_BG2X = -(SCREEN_WIDTH / 2 - 32) << 8;
    REG_BG2Y = -32 << 8;
/*******************************************************************************************/

    /*  Bigarren mailako pantailako 3 fondoaren afinitatea ezarri 16 biteko koloretarako. */
    REG_BG3CNT_SUB = BG_BMP16_256x256 |
                     BG_BMP_BASE(0) | // Memoriako hasierako helbidea
                     BG_PRIORITY(3); // Lehentasun baxua

    /*  Bigarren mailako pantailako 3 fondoaren transformazio matrizeari identitate matrizea esleitu. */
    REG_BG3PA_SUB = 1 << 8;
    REG_BG3PB_SUB = 0;
    REG_BG3PC_SUB = 0;
    REG_BG3PD_SUB = 1 << 8;

/*******************************************************************************************/
    /*  Bigarren mailako pantailako 3 fondoaren egoera definitu. */
    /*  Grafikoa beste posizio batean jarri nahi izanez gero hau aldatu beharko da. */
    REG_BG3X_SUB = 0;
    REG_BG3Y_SUB = 0;
/*******************************************************************************************/
}
示例#3
0
void init_backgrounds()
{
	int main_bg2 = bgInit(2, BgType_Bmp16, BgSize_B16_256x256, 0, 0);
	bgSetPriority(main_bg2, BG_PRIORITY(1));
	int main_bg3 = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 6, 0);
	bgSetPriority(main_bg3, BG_PRIORITY(0));
	consoleInit(&top_screen, 0, BgType_Text4bpp, BgSize_T_256x256, 31, 0, 0, 1);
	consoleSelect(&top_screen);
	consoleClear();
	puts("Made by Lennart Kroes, s1062295");
}
示例#4
0
文件: main.c 项目: robojan/EmuAll
void videoInitMode0() {
	VBlankIntrWait();
	
	// Create palette
	BG_COLORS[0] = RGB8(0xFF, 0xFF, 0xFF);
	BG_COLORS[1] = RGB8(0x00, 0x00, 0x00);
	BG_COLORS[2] = RGB8(0xFF, 0x00, 0x00);
	BG_COLORS[3] = RGB8(0x00, 0xFF, 0x00);
	BG_COLORS[4] = RGB8(0x00, 0x00, 0xFF);
	BG_COLORS[5] = RGB8(0xFF, 0x00, 0xFF);
	BG_COLORS[6] = RGB8(0xFF, 0xFF, 0x00);
	// Create tiles
	for(int i = 0; i< 64; i+=4) {
		*((s32 *)(TILE_BASE_ADR(0)+64*0+i)) = 0x00000000;
		*((s32 *)(TILE_BASE_ADR(0)+64*1+i)) = 0x01010101;
		*((s32 *)(TILE_BASE_ADR(0)+64*2+i)) = 0x02020202;
		*((s32 *)(TILE_BASE_ADR(0)+64*3+i)) = 0x03030303;
		*((s32 *)(TILE_BASE_ADR(0)+64*4+i)) = 0x04040404;
		*((s32 *)(TILE_BASE_ADR(0)+64*5+i)) = 0x05050505;
		*((s32 *)(TILE_BASE_ADR(0)+64*6+i)) = 0x06060606;
	}
	// create maps
	for(int y = 0; y < 32; y++) {
		for(int x = 0; x < 32; x++) {		
			// Checkerboard
			if(((x ^ y) & 1) != 0) {
				MAP[8][y][x] = 0x0002;
			} else {
				MAP[8][y][x] = 0x0001;
			}
			// 32x32 block
			if(x < 4 && y < 4) {
				MAP[12][y][x] = 0x0004;
			} else {
				MAP[12][y][x] = 0x0000;
			}
		}
	}
	
	REG_BG3CNT = BG_256_COLOR | BG_SIZE_0 | BG_TILE_BASE(0) | BG_MAP_BASE(8) | BG_PRIORITY(2);
	REG_BG2CNT = BG_256_COLOR | BG_SIZE_0 | BG_TILE_BASE(0) | BG_MAP_BASE(12) | BG_PRIORITY(1);
	
	REG_BG3HOFS = 0;
	REG_BG3VOFS = 0;
	REG_BG2HOFS = 0;
	REG_BG2VOFS = 0;
	
	REG_DISPCNT = MODE_0 | BG2_ON | BG3_ON;
	
}
示例#5
0
文件: dual3D.c 项目: Almamu/portalDS
void initD3D()
{
	int x,y,i;
	
	videoSetMode(MODE_3_3D);
	videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_2D_BMP_256);
    vramSetPrimaryBanks(VRAM_A_TEXTURE,VRAM_B_TEXTURE,VRAM_C_SUB_BG,VRAM_D_SUB_SPRITE);
	vramSetBankH(VRAM_H_LCD);
	vramSetBankI(VRAM_I_LCD);
	
	REG_BG0CNT = BG_PRIORITY(1);
	
	REG_BG2CNT_SUB = BG_BMP16_256x256 | BG_BMP_BASE(0) | BG_PRIORITY(1);
        REG_BG2PA_SUB = 1 << 8;
        REG_BG2PB_SUB = 0;
        REG_BG2PC_SUB = 0;
        REG_BG2PD_SUB = 1 << 8;
		
        REG_BG2X_SUB = 0;
        REG_BG2Y_SUB = 0;
	
	initSprites();
	
	d3dSpriteRotations[0].hdx=256;
	d3dSpriteRotations[0].hdy=0;
	d3dSpriteRotations[0].vdx=0;
	d3dSpriteRotations[0].vdy=256;
	
	i=0;
	
	for (y = 0; y < 3; y++)
	{
		for (x = 0; x < 4; x++) {
			d3dSprites[i].attribute[0] = ATTR0_BMP | ATTR0_SQUARE | (64 * y);
			d3dSprites[i].attribute[1] = ATTR1_SIZE_64 | (64 * x);
			d3dSprites[i].attribute[2] = ATTR2_ALPHA(1) | (8 * 32 * y) | (8 * x);
			i++;
		}
	}
	
	updateOAM();
	d3dScreen=true;
}
示例#6
0
文件: arm9_main.c 项目: 0xtob/dsmi
int main(void)
{
	
	lcdMainOnBottom();

	// Set modes
	videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
	videoSetModeSub(MODE_5_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG2_ACTIVE);
	
	// Set banks
	vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000,
		VRAM_C_SUB_BG_0x06200000 , VRAM_D_LCD);
	
	// Gfx on main
	REG_BG3CNT = BG_BMP16_256x256 | BG_BMP_BASE(0) | BG_PRIORITY(0);
	REG_BG3PA = 1 << 8;
	REG_BG3PB = 0;
	REG_BG3PC = 0;
	REG_BG3PD = 1 << 8;
	
	// Text bg on sub
	REG_BG0CNT_SUB = BG_MAP_BASE(4) | BG_TILE_BASE(0) | BG_PRIORITY(0);
	BG_PALETTE_SUB[255] = RGB15(31,15,0);
	consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false, true);
	
	// Gfx on sub
	REG_BG2CNT_SUB = BG_BMP16_256x256 | BG_MAP_BASE(2) | BG_PRIORITY(1);
	REG_BG2PA_SUB = 1 << 8;
	REG_BG2PB_SUB = 0;
	REG_BG2PC_SUB = 0;
	REG_BG2PD_SUB = 1 << 8;
	
	u16 i;
	for(i=0; i<256*192; ++i)
		sub_vram[i] = dsmi_logo_ds[i];
	drawKaos();
	drawSlider1();
	drawSlider2();
	drawSlider3();
	
	iprintf("\x1b[12;12HOSC Demo\n");
	
	iprintf("\x1b[15;0H\x1b[KConnecting\n");
	int res = dsmi_connect();
	
	if(res == 1) {
		iprintf("\x1b[15;0H\x1b[KOK\n");
	} else {
		iprintf("\x1b[15;0H\x1b[KOh no, could not connect!\n");
		while(1);
	}
	
	
	while(1)
	{
		int ret, i;
		char data[32];
		size_t size = sizeof(data);
	       	char type;

		VblankHandler();
		while( dsmi_osc_read() ){
			iprintf("\x1b[17;0H\x1b[K%s\n", dsmi_osc_getaddr());
			while( ret = dsmi_osc_getnextarg( data, &size, &type)){
				if( ret == -1) break; //buffer too small error
				switch(type){
					case 'i':
					case 'f':
					  iprintf("%c : 0x%x%x%x%x\n", type, data[0], data[1], data[2], data[3]);
					  break;
					case 's':
					  iprintf("%c : %s\n", type, data);
					  break;
					default:
					  break;
				}
			}
		}
		swiWaitForVBlank();
	}
	
}
示例#7
0
int main() {
    /* ドロイド君の x, y 座標 */
    s16 dx = 120, dy = 120;
    /* りんごの x, y 座標 */
    const s16 ax = 160, ay = 120;
    /* 窓の x, y 座標 */
    const s16 wx = 40, wy = 40;
    /* タイルのベースアドレス */
    u16* tile = (u16*)TILE_BASE_ADR(0);
    /*
     * ドロイド君の状態。
     * 0 => 待機
     * 1 => ジャンプ準備中
     * 2 => ジャンプ中
     */
    int state = 0;
    /* 歩き状態 (0, 1, 2) */
    int wstate = 0;
    /* ドロイド君の y 方向の速度 */
    float vy = 0;
    /* フレーム数用の変数 */
    u16 f = 0;
    /* 表示するキャラクタ */
    u16 ch = 0;
    /* キー状態取得用変数 */
    u16 kd = 0;
    u16 kdr = 0;
    u16 ku = 0;
    u16 kh = 0;
    /* 汎用変数 */
    u16 i, xx, yy;

    /* フレーム数初期化 */
    frame = 0;

    /* 割り込みの初期化 */
    irqInit();
    /*
     * VBLANK 割り込みを有効化
     * これによって VBlankIntrWait() が使えるようになる
     */
    irqEnable(IRQ_VBLANK);

    /*
     * モードの設定。
     * MODE 0、スプライト有効化、BG0 有効化
     */
    SetMode(MODE_0 | OBJ_ENABLE | BG0_ON);

    /* スプライトのメモリ領域(OAM)にスプライトデータをコピー */
    GbaGraphics::setSpriteData(spritesTiles, spritesTilesLen / 2);

    /* スプライトと BG のパレットのメモリ領域にパレットデータをコピー */
    GbaGraphics::setSpritePalette(spritesPal, 16);
    GbaGraphics::setBGPalette(spritesPal, 16);
    GbaGraphics::setBGColor(RGB5(15,15,31));

    /* スプライトの初期化 */
    GbaGraphics::initSprites();

    /* ドロイド君の準備 */
    GbaGraphics::Sprite droid(0, 0, Sprite_16x16);
    droid.setPosition(dx, dy);
    droid.draw();

    /* りんごの準備 */
    GbaGraphics::Sprite apple(1, (2 * 32), Sprite_16x16);
    apple.setPosition(ax, ay);
    apple.draw();

    /* 窓の準備 */
    GbaGraphics::Sprite window(2, 2 + (2 * 32), Sprite_16x16);
    window.setPosition(wx, wy);
    window.draw();

    /* BG 0 の設定 */
    BGCTRL[0] = BG_MAP_BASE(31) | BG_16_COLOR | BG_SIZE_0 | TILE_BASE(0) | BG_PRIORITY(0);

    /* BG0 を初期化 */
    for ( xx = 0; xx < 32; xx++ ) {
        for ( yy = 0; yy < 32; yy++ ) {
            MAP[31][yy][xx] = 6 * 32;
        }
    }

    /* 画像をタイルにコピー */
    for ( i = 0; i < spritesTilesLen / 2; i++ ) {
        tile[i] = spritesTiles[i];
    }

    /* BG0 をセット */
    MAP[31][17][0] = 5 * 32;
    MAP[31][17][29] = 2 + 5 * 32;
    for ( i = 1; i < 29; i++ ) {
        MAP[31][17][i] = 1 + 5 * 32;
    }
    for ( xx = 0; xx < 30; xx++ ) {
        for ( yy = 18; yy < 32; yy++ ) {
            MAP[31][yy][xx] = 3 + 5 * 32;
        }
    }

    // コンソール出力のテスト
    cprintf("droid(%d, %d), apple(%d, %d), window(%d, %d), %s", dx, dy, ax, ay, wx, wy, "console test.");

    /* メインループ */
    while (1) {
        /* VBLANK 割り込み待ち */
        VBlankIntrWait();
        /* フレーム数カウント */
        frame += 1;
        /* キー状態取得 */
        scanKeys();
        kd = keysDown();
        kdr = keysDownRepeat();
        ku = keysUp();
        kh = keysHeld();

        switch(state) {
        case 0:
            /* 待機中 */
            if( (kd & KEY_UP) ) {
                state = 1;
                f = 0;
                ch = 0;
                break;
            }
            if( (kh & KEY_LEFT)  ) {
                dx--;
                droid.setHFlip(true);
            }
            if( (kh & KEY_RIGHT) ) {
                dx++;
                droid.setHFlip(false);
            }
            if( dx < -16 ) {
                dx = SCREEN_WIDTH;
            }
            if( kd & ( KEY_LEFT | KEY_RIGHT ) ) {
                wstate = 0;
                f = 0;
            }
            if( ku & ( KEY_LEFT | KEY_RIGHT ) ) {
                ch = 0;
            }
            if ( SCREEN_WIDTH < dx ) {
                dx = -16;
            }

            if ( kh & ( KEY_LEFT | KEY_RIGHT ) ) {
                /* 歩きモーション */
                if ( 5 < f++ ) {
                    switch ( wstate ) {
                    case 0:
                        wstate = 1;
                        ch = 2;
                        break;
                    case 1:
                        wstate = 2;
                        ch = 0;
                        break;
                    case 2:
                        wstate = 3;
                        ch = 4;
                        break;
                    default:
                        wstate = 0;
                        ch = 0;
                        break;
                    }
                    f = 0;
                }
            }

            if ( dy == (ay - 13) ) {
                if ( !(((ax - 11) < dx) &&
                       (dx < (ax + 11))) ) {
                    /* りんごから落ちる */
                    vy = -0.;
                    state = 2;
                    wstate = 0;
                    break;
                }
            }
            droid.setCharacter(ch);
            droid.setPosition(dx, dy);
            break;
        case 1:
        case 3:
            /* ジャンプ準備 */
            droid.setCharacter(6);
            if( 3 < f++ ) {
                vy = 4.;
                if ( 1 == state ) state = 2;
                else state = 4;
            }
            break;
        case 2:
        case 4:
            /* ジャンプ中 */
            if( (kd & KEY_UP) ) {
                /* 二段ジャンプ */
                if ( state == 2 ) {
                    state = 3;
                    f = 0;
                    break;
                }
            }
            if( kh & KEY_LEFT ) {
                dx--;
                droid.setHFlip(true);
            }
            if( kh & KEY_RIGHT ) {
                dx++;
                droid.setHFlip(false);
            }
            if( dx < -16 ) {
                dx = SCREEN_WIDTH;
            }
            if ( SCREEN_WIDTH < dx ) {
                dx = -16;
            }
            if( (0.5 < vy) && ( kh & KEY_UP ) ) {
                vy += 0.2;
            }
            dy -= (s16)vy;
            if(vy < 0) {
                droid.setCharacter(10);
            } else {
                droid.setCharacter(8);
            }
            if ( dy < 0 ) {
                dy = 0;
                vy = -0.;
            }

            if ( (vy < 0) &&
                 ((ax - 11) < dx) &&
                 (dx < (ax + 11)) ) {
                if ( ay - 13 < dy ) {
                    /* りんごに乗る */
                    dy = ay - 13;
                    state = 0;
                }
            }

            if ( 120 < dy ) {
                /* 着地 */
                dy = 120;
                state = 0;
            }
            droid.setPosition(dx, dy);
            vy = vy - 0.3;
            break;
        }
        droid.draw();
    }
}
示例#8
0
void kbd_set_map() {
  REG_BG0CNT = BG_TILE_BASE(0) | BG_MAP_BASE(4 + (caps | (shift<<1))) | BG_PRIORITY(0) | BG_COLOR_16;
}
示例#9
0
文件: game.c 项目: dibas/portalDS
void initGame(void)
{
	lcdMainOnTop();
	int oldv=getMemFree();
	NOGBA("mem free : %dko (%do)",getMemFree()/1024,getMemFree());
	NOGBA("initializing...");
	videoSetMode(MODE_5_3D | DISPLAY_BG3_ACTIVE);
	videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE);
	
	glInit();
	
	vramSetPrimaryBanks(VRAM_A_TEXTURE,VRAM_B_TEXTURE,VRAM_C_LCD,VRAM_D_MAIN_BG_0x06000000);
	vramSetBankH(VRAM_H_SUB_BG);
	vramSetBankI(VRAM_I_SUB_BG_0x06208000);
	
	glEnable(GL_TEXTURE_2D);
	// glEnable(GL_ANTIALIAS);
	glDisable(GL_ANTIALIAS);
	glEnable(GL_BLEND);
	glEnable(GL_OUTLINE);
	
	glSetOutlineColor(0,RGB15(0,0,0)); //TEMP?
	glSetOutlineColor(1,RGB15(0,0,0)); //TEMP?
	glSetOutlineColor(7,RGB15(31,0,0)); //TEMP?
	glSetToonTableRange(0, 15, RGB15(8,8,8)); //TEMP?
	glSetToonTableRange(16, 31, RGB15(24,24,24)); //TEMP?
	
	glClearColor(31,31,0,31);
	glClearPolyID(63);
	glClearDepth(0x7FFF);

	glViewport(0,0,255,191);
	
	// initVramBanks(1);
	initVramBanks(2);
	initTextures();
	initSound();
	
	initCamera(NULL);
	
	initPlayer(NULL);
	
	initLights();
	initParticles();
	
	initMaterials();
	
	loadMaterialSlices("slices.ini");
	loadMaterials("materials.ini");
	loadControlConfiguration("config.ini");
	
	initElevators();
	initWallDoors();
	initTurrets();
	initBigButtons();
	initTimedButtons();
	initEnergyBalls();
	initPlatforms();
	initCubes();
	initEmancipation();
	initDoors();
	initSludge();
	initPause();

	initText();

	NOGBA("lalala");

	getPlayer()->currentRoom=&gameRoom;
	
	currentBuffer=false;
	
	getVramStatus();
	fadeIn();
	
	mainBG=bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 0, 0);
	bgSetPriority(mainBG, 0);
	REG_BG0CNT=BG_PRIORITY(3);
	
	#ifdef DEBUG_GAME
		consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 16, 0, false, true);
		consoleSelect(&bottomScreen);
	#endif
	
	// glSetToonTableRange(0, 14, RGB15(16,16,16));
	// glSetToonTableRange(15, 31, RGB15(26,26,26));
	
	initPortals();
	
	//PHYSICS
	initPI9();

	strcpy(&mapFilePath[strlen(mapFilePath)-3], "map");
	newReadMap(mapFilePath, NULL, 255);
	
	transferRectangles(&gameRoom);
	makeGrid();
	generateRoomGrid(&gameRoom);
	gameRoom.displayList=generateRoomDisplayList(&gameRoom, vect(0,0,0), vect(0,0,0), false);
	
	getVramStatus();
	
	startPI();

	NOGBA("START mem free : %dko (%do)",getMemFree()/1024,getMemFree());
	NOGBA("vs mem free : %dko (%do)",oldv/1024,oldv);

	levelInfoCounter=60;
}
示例#10
0
文件: main.cpp 项目: kusma/nds
int main()
{
	irqInit();
	SetMode((LCDC_BITS)(MODE_1 | BG0_ON | BG2_ON | OBJ_ENABLE));
	
	irqSet(IRQ_VBLANK, vblank);
	irqEnable(IRQ_VBLANK);
	
	float xpos = 0;
	float ypos = 0;
	
	float xdir = 0;
	float ydir = 0;
	int dir = 0;
	
	BG_COLORS[0] = RGB5(31, 0, 31);
	CpuFastSet(tileset_img, OBJ_BASE_ADR, COPY32 | (256 * 16) / 4);
	CpuFastSet(tileset_pal, OBJ_COLORS, COPY32 | (256 / 4));
	
	CpuFastSet(tileset_img, PATRAM4(0, 0), COPY32 | (256 * 16) / 4);
	CpuFastSet(tileset_pal, BG_COLORS, COPY32 | (256 / 4));
	
	// mock up a map
/*	((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[0] = 0;
	((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[1] = 1;
	((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[32] = 32;
	((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[33] = 33;
	((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[64] = 64;
	((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[65] = 65; */
	
	for (int y = 0; y < 32; ++y)
	{
		for (int x = 0; x < 32; ++x)
		{
			((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[x + y * 32] = 5;
		}
	}
	for (int x = 0; x < 32; ++x) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[x] = 16;
	for (int x = 0; x < 32; ++x) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[31 * 32 + x] = 16;
	for (int y = 0; y < 32; ++y) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[y * 32] = 16;
	for (int y = 0; y < 32; ++y) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[y * 32 + 31] = 16;
	
	BGCTRL[0] = SCREEN_BASE(MAP_BASE_BLOCK + 0) | CHAR_BASE(0) | BG_SIZE_0 | BG_16_COLOR | BG_PRIORITY(1); // | CHAR_PALETTE(1);
	BGCTRL[2] = SCREEN_BASE(MAP_BASE_BLOCK + 1) | CHAR_BASE(0) | BG_SIZE_1 | BG_16_COLOR | BG_PRIORITY(0); // | CHAR_PALETTE(1);
	
	float rot = 0.0f;
	float last_rot = rot;
	float bg_scroll = 0;
	
	int frame = 0;
	while (1)
	{
		int sprite_frame = (int(floor(bg_scroll)) >> 3) & 1;
		if (fabs(xdir) < 1e-1) sprite_frame = 0;
//		if (ypos > 0) sprite_frame = 2;
		int tile_start = sprite_frame * 2;
		int pal = 0;
		
		for (int i = 0; i < 128; ++i)
		{
			sprites[i].attr0 = ATTR0_DISABLED;
		}
		
		int sprite = 0;
//		sprites[sprite].attr0 = OBJ_Y(int(ypos) + 80 - 8) | ATTR0_COLOR_16 | ATTR0_WIDE;
//		sprites[sprite].attr1 = OBJ_X(int(xpos) + 120) | OBJ_SIZE(Sprite_16x8) | (dir ? ATTR1_FLIP_X : 0);
		sprites[sprite].attr0 = OBJ_Y(int(0) + 80 - 16) | ATTR0_COLOR_16 | ATTR0_WIDE;
		sprites[sprite].attr1 = OBJ_X(int(0) + 120 - 8) | OBJ_SIZE(Sprite_16x8) | (dir ? ATTR1_FLIP_X : 0);
		sprites[sprite].attr2 = OBJ_CHAR(tile_start) | ATTR2_PALETTE(pal); // | OBJ_TRANSLUCENT;
		sprite++;

//		sprites[sprite].attr0 = OBJ_Y(int(ypos) + 80)  | ATTR0_COLOR_16 | ATTR0_SQUARE;
//		sprites[sprite].attr1 = OBJ_X(int(xpos) + 120) | OBJ_SIZE(Sprite_16x16) | (dir ? ATTR1_FLIP_X : 0);
		sprites[sprite].attr0 = OBJ_Y(int(0) + 80 - 8)  | ATTR0_COLOR_16 | ATTR0_SQUARE;
		sprites[sprite].attr1 = OBJ_X(int(0) + 120 - 8) | OBJ_SIZE(Sprite_16x16) | (dir ? ATTR1_FLIP_X : 0);
		sprites[sprite].attr2 = OBJ_CHAR(tile_start + 32)   | ATTR2_PALETTE(pal); // | OBJ_TRANSLUCENT;
		sprite++;

		float st = sin(last_rot);
		float ct = cos(last_rot);
		
		last_rot = last_rot + (rot - last_rot) * 0.1;
		
		int pa = int(0x100 * ct);
		int pb =-int(0x100 * st);
		int pc = int(0x100 * st);
		int pd = int(0x100 * ct);
		
		// don't setup any hw-regs until vblank
		VBlankIntrWait();
		
		// setup bg0 scroll
		REG_BG0HOFS = int(bg_scroll) & 0xFFFF;
		
		// setup bg2 transform
		REG_BG2PA = pa;
		REG_BG2PB = pb;
		REG_BG2PC = pc;
		REG_BG2PD = pd;
		REG_BG2X = (int(xpos) << 8) - (pa * 120 + pb * 80);
		REG_BG2Y = (int(ypos) << 8) - (pc * 120 + pd * 80);		
		
		++frame;
		CpuSet(sprites,  OAM, (128 * sizeof(OAM[0])) / 2);
		
		scanKeys();
		u32 held = keysHeld();
		u32 down = keysDown();
		u32 up = keysUp();
		
		float upx =  sin(rot);
		float upy = -cos(rot);
		float leftx =  upy;
		float lefty = -upx;
		
		if (KEY_UP    & down) { xdir = upx * 5; ydir = upy * 5; }
		if (KEY_L     & down) { rot += M_PI / 2; }
		if (KEY_R     & down) { rot -= M_PI / 2; }
/*		if (KEY_L     & up) { rot += M_PI / 4; }
		if (KEY_R     & up) { rot -= M_PI / 4; } */
		
		// external forces
#if 0
		xdir *= 0.95; // friction
		ydir *= 0.95; // friction
#else
		float a = leftx * xdir + lefty * ydir; // dot(dir, left)
		float b = upx   * xdir +   upy * ydir; // dot(dir, up)
		float new_xdir = upx * b + 0.85 * leftx * a;
		float new_ydir = upy * b + 0.85 * lefty * a;
		xdir = new_xdir;
		ydir = new_ydir;
#endif	
		if (fabs(xdir) < 1e-1) xdir = 0;
		if (fabs(ydir) < 1e-1) ydir = 0;
		
		if (KEY_RIGHT & held) { xdir -= leftx * 0.5f; ydir -= lefty * 0.5f; dir = 0; }
		if (KEY_LEFT  & held) { xdir += leftx * 0.5f; ydir += lefty * 0.5f; dir = 1; }
		
		xdir -= upx * 0.25;   // gravity
		ydir -= upy * 0.25;   // gravity
		
		float last_xpos = xpos;
		float last_ypos = ypos;
		
		// apply forces
		xpos += xdir;
		ypos += ydir;
		
		// resolve constraints
		if (xpos < 0)   xpos = 0;
		if (xpos > 255) xpos = 255;
		if (ypos < 0)   ypos = 0;
		if (ypos > 255) ypos = 255;
		
		float delta_xpos = last_xpos - xpos;
		float delta_ypos = last_ypos - ypos;
		
		bg_scroll += (delta_xpos * leftx + delta_ypos * lefty) * 0.5f;
	}
	return 0;
}