FSPDS/arm9/source/title.cpp
2024-08-02 16:16:47 +03:00

410 lines
10 KiB
C++

#include <nds.h>
#include "globals.hpp"
#include "logo_front_bin.h"
#include "logo_back_bin.h"
#include "logo_side_bin.h"
#include "logo_tb_bin.h"
#include "esodev_logo.h"
#include "background.h"
#include "opt_box.h"
#include "fat_fail.h"
#include "empty.h"
#if USE_NTFS==1
#include "title_spr_nitro.h"
#else
#include "title_spr.h"
#endif
#include "scenes.hpp"
static char BK_RESERVED[1024*512];
using namespace DSC;
Scene* return_scene()
{
Debug::log("Selected path = %s", picked_folder_path);
delete[] picked_folder_path;
picked_folder_path = nullptr;
return gen_title_scene();
}
Scene* get_browse_scene()
{
//if(!is_fat_inited())
//return get_player_scene();
return get_playlists_scene();
//folder_picker_next_scene_gen = return_scene;
//return get_folder_picker_scene();
}
class TitleScene : public GenericScene256
{
int textureID[4];
int i;
float rotateX = 0.0;
float rotateY = 0.0;
Sprite* empty = nullptr;
Sprite* title[2];
Sprite* fat_fail;
void* ______ = BK_RESERVED;
Sprite* esodev_logo;
VwfEngine* vwf = new VwfEngine(Resources::Fonts::default_8x16);
void init() override
{
GenericScene256::init();
key_down.add_event(&TitleScene::on_key_down, this);
key_held.add_event(&TitleScene::on_key_held, this);
init3d();
require_tiledmap(SUB_BG2, 256, 256, &ROA_background4);
require_tiledmap_4bpp(SUB_BG0, 256, 256, 32*24);
title[0] = create_sprite(new Sprite(SIZE_64x64, Engine::Main));
title[1] = create_sprite(new Sprite(SIZE_64x64, Engine::Main));
begin_sprites_init();
empty = create_sprite(new Sprite(SIZE_8x8, Engine::Sub));
empty->add_frame(new ObjFrame(&ROA_empty8, 0,0));
#if USE_NTFS==1
title[0]->add_frame(new ObjFrame(&ROA_title_spr_nitro8, 0,0));
title[1]->add_frame(new ObjFrame(&ROA_title_spr_nitro8, 0,1));
#else
title[0]->add_frame(new ObjFrame(&ROA_title_spr8, 0,0));
title[1]->add_frame(new ObjFrame(&ROA_title_spr8, 0,1));
#endif
title[0]->set_position(128-64, 116);
title[1]->set_position(128, 116);
if(!is_fat_inited())
{
fat_fail = create_sprite(new Sprite(SIZE_64x32, Engine::Sub));
fat_fail->add_frame(new ObjFrame(&ROA_fat_fail8, 0,0));
fat_fail->set_position(14,112);
}
esodev_logo = create_sprite(new Sprite(SIZE_32x32, Engine::Sub));
esodev_logo->add_frame(new ObjFrame(&ROA_esodev_logo8, 0,0));
esodev_logo->set_position(15,149);
end_sprites_init();
}
bool sinit=false;
void frame() override
{
if(!sinit)
{
sinit=true;
BG_PALETTE_SUB[0x91]=Colors::Red;
Debug::log("MAPPPPP = %X", bgGetGfxPtr(4));
Debug::log("MAPPPPP = %X", bgGetMapPtr(4));
vwf->set_render_space(bgGetGfxPtr(4),24,32);
VwfEngine::prepare_map(*vwf, 4, 32, 0, 0, 0x9);
vwf->clear(Pal4bit);
vwf->set_cursor(1, 150);
vwf->put_text("Browse", Pal4bit, SolidColorBrush(0x1));
vwf->set_cursor(3, 150);
vwf->put_text("Settings", Pal4bit, SolidColorBrush(0x1));
vwf->set_cursor(5, 150);
vwf->put_text("Help", Pal4bit, SolidColorBrush(0x1));
vwf->set_cursor(7, 150);
vwf->put_text("Credits", Pal4bit, SolidColorBrush(0x1));
}
frame3d();
GenericScene256::frame();
}
typedef Scene*(*fgen)();
inline static constexpr fgen scenegens[4] = { &get_browse_scene, &get_settings_scene, &get_help_scene, &get_credits_scene };
void on_key_down(void* sender, void* args)
{
int keys = (int)args;
if(keys & KEY_TOUCH)
{
touchPosition touch;
touchRead(&touch);
if(touch.px<137) return;
int y=touch.py-8;
if(y<0 || y%32>28) return;
int option = y/32;
if(option<0 || option>=4) return;
close()->next(scenegens[option]());
}
if(keys & KEY_B)
{
close()->next(get_browse_scene());
}
}
void on_key_held(void* sender, void* args)
{
int keys = (int)args;
if((keys & KEY_UP))
{
if(rotateX<30)
rotateX += 2;
}
if((keys & KEY_DOWN))
{
if(rotateX>-30)
rotateX -= 2;
}
}
void init3d()
{
//set mode 0, enable BG0 and set it to 3D
videoSetMode(MODE_0_3D);
// initialize gl
glInit();
glResetMatrixStack();
glResetTextures();
//enable textures
glEnable(GL_TEXTURE_2D);
//this should work the same as the normal gl call
glViewport(0,0,255,191);
// enable antialiasing
glEnable(GL_ANTIALIAS);
// setup the rear plane
glClearColor(30,27,25,31); // BG must be opaque for AA to work
glClearPolyID(63); // BG must have a unique polygon ID for AA to work
glClearDepth(0x7FFF);
vramSetBankB(VRAM_B_LCD);
REG_DISPCAPCNT =
DCAP_MODE(DCAP_MODE_BLEND) //blend source A and source B
//| DCAP_SRC_ADDR //this is not used since we are setting the display to render from VRAM
| DCAP_SRC_B(DCAP_SRC_B_VRAM)
| DCAP_SRC_A(DCAP_SRC_A_3DONLY)
| DCAP_SIZE(DCAP_SIZE_256x192)
| DCAP_OFFSET(0) //where to write the captured data within our chosen VRAM bank
| DCAP_BANK(DCAP_BANK_VRAM_B)
| DCAP_B(8) //blend mostly from B to make a very dramatic effect
| DCAP_A(8) //and blend only a little bit from the new scene
;
//but, dramatic effects tend to leave some garbage on the screen since the precision of the math is low,
//and we're not putting a lot of dampening on the effect.
//a more realistic value might be 8 and 8, but perhaps in a more complex 3d scene the garbage isn't such a bad thing
//since the scene is changing constantly
//DisplayEnableMotionBlur();
DisplayEnableNormal();
vramSetBankA(VRAM_A_TEXTURE);
glGenTextures(4, textureID);
glBindTexture(0, textureID[0]);
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32 , TEXTURE_SIZE_32, 0, TEXGEN_TEXCOORD, (u8*)logo_front_bin);
glBindTexture(1, textureID[1]);
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32 , TEXTURE_SIZE_32, 0, TEXGEN_TEXCOORD, (u8*)logo_back_bin);
glBindTexture(2, textureID[2]);
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32 , TEXTURE_SIZE_16, 0, TEXGEN_TEXCOORD, (u8*)logo_side_bin);
glBindTexture(3, textureID[3]);
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32 , TEXTURE_SIZE_16, 0, TEXGEN_TEXCOORD, (u8*)logo_tb_bin);
//any floating point gl call is being converted to fixed prior to being implemented
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 256.0 / 192.0, 0.1, 40);
gluLookAt( 0.0, 0.4, 1.3, //camera possition
0.0, 0.0, 0.0, //look at
0.0, 1.0, 0.0); //up
}
//verticies for the cube
inline static constexpr v16 CubeVectors[24] = {
floattov16(-0.15), floattov16(-0.5), floattov16(0.5),
floattov16(0.15), floattov16(-0.5), floattov16(0.5),
floattov16(0.15), floattov16(-0.5), floattov16(-0.5),
floattov16(-0.15), floattov16(-0.5), floattov16(-0.5),
floattov16(-0.15), floattov16(0.5), floattov16(0.5),
floattov16(0.15), floattov16(0.5), floattov16(0.5),
floattov16(0.15), floattov16(0.5), floattov16(-0.5),
floattov16(-0.15), floattov16(0.5), floattov16(-0.5)
};
//polys
inline static constexpr u8 CubeFaces[24] = {
3,2,1,0,
0,1,5,4,
1,2,6,5,
2,3,7,6,
3,0,4,7,
5,6,7,4
};
inline static constexpr u32 normals[6] =
{
NORMAL_PACK(0,(u32)floattov10(-.97),0),
NORMAL_PACK(0,0,floattov10(.97)),
NORMAL_PACK(floattov10(.97),0,0),
NORMAL_PACK(0,0,(u32)floattov10(-.97)),
NORMAL_PACK((u32)floattov10(-.97),0,0),
NORMAL_PACK(0,floattov10(.97),0)
};
//draw a cube face at the specified color
void drawQuad(int poly, int u, int v)
{
u32 f1 = CubeFaces[poly * 4] ;
u32 f2 = CubeFaces[poly * 4 + 1] ;
u32 f3 = CubeFaces[poly * 4 + 2] ;
u32 f4 = CubeFaces[poly * 4 + 3] ;
glNormal(normals[poly]);
GFX_TEX_COORD = (TEXTURE_PACK(inttot16(u), 0));
glVertex3v16(CubeVectors[f1*3], CubeVectors[f1*3 + 1], CubeVectors[f1*3 + 2] );
GFX_TEX_COORD = (TEXTURE_PACK(inttot16(u),inttot16(v)));
glVertex3v16(CubeVectors[f2*3], CubeVectors[f2*3 + 1], CubeVectors[f2*3 + 2] );
GFX_TEX_COORD = (TEXTURE_PACK(0, inttot16(v)));
glVertex3v16(CubeVectors[f3*3], CubeVectors[f3*3 + 1], CubeVectors[f3*3 + 2] );
GFX_TEX_COORD = (TEXTURE_PACK(0,0));
glVertex3v16(CubeVectors[f4*3], CubeVectors[f4*3 + 1], CubeVectors[f4*3 + 2] );
}
void DisplayEnableMotionBlur()
{
u32 dispcnt = REG_DISPCNT;
//set main display to display from VRAM
dispcnt &= ~(0x00030000); dispcnt |= 2<<16; //choose to display screen from VRAM
dispcnt &= ~(0x000C0000); dispcnt |= 1<<18; //choose to display screen from VRAM_B
REG_DISPCNT = dispcnt;
}
void DisplayEnableNormal()
{
u32 dispcnt = REG_DISPCNT;
dispcnt &= ~(0x00030000); dispcnt |= 1<<16; //choose to display screen from normal layer composition
REG_DISPCNT = dispcnt;
}
void frame3d()
{
glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0), 0);
glLight(1, RGB15(31,13,21), 0, floattov10(1) - 1, 0);
glLight(2, RGB15(31,13,21) , floattov10(-1.0), 0, 0);
glLight(3, RGB15(31,13,21) , floattov10(1.0) - 1, 0, 0);
glPushMatrix();
//move it away from the camera
glTranslatef32(0, 0, floattof32(-1));
glRotateX(rotateX);
glRotateY(rotateY);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glMaterialf(GL_AMBIENT, RGB15(8,8,8));
glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
glMaterialf(GL_SPECULAR, BIT(15) | RGB15(8,8,8));
glMaterialf(GL_EMISSION, RGB15(5,5,5));
//ds uses a table for shinyness..this generates a half-ass one
glMaterialShinyness();
//not a real gl function and will likely change
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK | POLY_FORMAT_LIGHT0 | POLY_FORMAT_LIGHT1 |
POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3 ) ;
for(int i=0, u=32, v=32;i<6;i++)
{
u=v=32;
if(i==2)
glBindTexture(0, textureID[1]);
else if(i==4)
glBindTexture(0, textureID[0]);
else if(i==0 || i==5)
{
glBindTexture(0, textureID[3]);
v=16;
}
else
{
glBindTexture(0, textureID[2]);
v=16;
}
glBegin(GL_QUAD);
drawQuad(i,u,v);
glEnd();
}
glPopMatrix(1);
glFlush(0);
rotateY += 3;
//the display capture enable bit must be set again each frame if you want to continue capturing.
REG_DISPCAPCNT |= DCAP_ENABLE;
}
~TitleScene()
{
key_down.remove_event(&TitleScene::on_key_down, this);
key_held.remove_event(&TitleScene::on_key_held, this);
delete vwf;
delete empty;
delete title[0];
delete title[1];
delete fat_fail;
delete esodev_logo;
Sprite::oam_deploy_main();
Sprite::oam_deploy_sub();
}
};
Scene* gen_title_scene()
{
return new TitleScene();
}