mirror of
https://github.com/NotImplementedLife/FSPDS.git
synced 2025-06-18 17:05:33 -04:00
410 lines
10 KiB
C++
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();
|
|
} |