426 lines
14 KiB
C++
426 lines
14 KiB
C++
#include <tamtypes.h>
|
|
#include <kernel.h>
|
|
#include <libpad.h>
|
|
#include <fileio.h>
|
|
#include <malloc.h>
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <gsDriver.h>
|
|
#include <gsPipe.h>
|
|
#include <gsFont.h>
|
|
|
|
#include <sifrpc.h>
|
|
#include <loadfile.h>
|
|
|
|
#include "cdvd_rpc.h"
|
|
|
|
#define scr_w 640
|
|
#define scr_h 480
|
|
|
|
|
|
#define TEXT_COL_BRIGHT GS_SET_RGBA(0xFF, 0xFF, 0xFF, 0x80)
|
|
#define TEXT_COL_DIM GS_SET_RGBA(0x40, 0x40, 0xFF, 0x80)
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
gsDriver *pDisplay;
|
|
|
|
extern int screen;
|
|
int filelisty = 60;
|
|
|
|
static float selected = 1; // The currently selected file/dir
|
|
|
|
|
|
int button_released = TRUE;
|
|
|
|
//A pointer to an array of TocEntries to be alloc'd later
|
|
static struct TocEntry *TocEntryList;
|
|
|
|
|
|
|
|
gsFontTex *fontTex;
|
|
|
|
|
|
|
|
// pathname on CD
|
|
char pathname[1024 + 1] __attribute__((aligned(64)));
|
|
|
|
gsFont myFont;
|
|
|
|
int WaitPadReady(int port, int slot);
|
|
void SetPadMode(int port, int slot);
|
|
|
|
|
|
void ClearScreen(void)
|
|
{
|
|
pDisplay->drawPipe.setAlphaEnable(GS_DISABLE);
|
|
pDisplay->drawPipe.RectFlat(0, 0, scr_w, scr_h, 0, GS_SET_RGBA(0, 0, 0, 0x80));
|
|
pDisplay->drawPipe.setAlphaEnable(GS_ENABLE);
|
|
pDisplay->drawPipe.Flush();
|
|
}
|
|
|
|
|
|
int main(void)
|
|
{
|
|
SifInitRpc(0);
|
|
|
|
SifLoadModule("rom0:SIO2MAN", 0, NULL); /* load sio2 manager irx */
|
|
SifLoadModule("rom0:PADMAN", 0, NULL); /* load pad manager irx */
|
|
|
|
SifLoadModule("host:cdvd.irx", 0, NULL);
|
|
|
|
CDVD_Init();
|
|
|
|
padInit(0);
|
|
|
|
char *padBuf = (char *)memalign(64, 256);
|
|
|
|
padPortOpen(0, 0, padBuf);
|
|
|
|
SetPadMode(0, 0);
|
|
|
|
// allocate the memory for a large file list
|
|
TocEntryList = (TocEntry *)memalign(64, 4000 * sizeof(struct TocEntry));
|
|
|
|
|
|
// open the font file, find the size of the file, allocate memory for it, and load it
|
|
int fontfile = fioOpen("host:font.fnt", O_RDONLY);
|
|
int fontsize = fioLseek(fontfile, 0, SEEK_END);
|
|
fioLseek(fontfile, 0, SEEK_SET);
|
|
fontTex = (gsFontTex *)memalign(64, fontsize);
|
|
fioRead(fontfile, fontTex, fontsize);
|
|
fioClose(fontfile);
|
|
|
|
// Upload the background to the texture buffer
|
|
pDisplay = new gsDriver;
|
|
|
|
pDisplay->setDisplayMode(scr_w, scr_h,
|
|
170, 80,
|
|
GS_PSMCT32, 2,
|
|
GS_TV_AUTO, GS_TV_INTERLACE,
|
|
GS_DISABLE, GS_DISABLE);
|
|
|
|
// Enable Alpha Blending
|
|
pDisplay->drawPipe.setAlphaEnable(GS_ENABLE);
|
|
|
|
myFont.assignPipe(&(pDisplay->drawPipe));
|
|
|
|
// Upload the font into the texture memory past the screen buffers
|
|
myFont.uploadFont(fontTex, pDisplay->getTextureBufferBase(),
|
|
fontTex->TexWidth, // Use the fontTex width as texbuffer width (can use diff width)
|
|
0, 0);
|
|
|
|
|
|
#define list_max 21
|
|
int list_size = 21; // Number of files to display in list
|
|
int first_file = 1; // The first file to display in the on-screen list
|
|
int num_files = 0; // The total number of files in the list
|
|
int offset; // Offset of the selected file into the displayed list
|
|
|
|
struct padButtonStatus padButtons;
|
|
int ps2_buttons;
|
|
|
|
button_released = TRUE;
|
|
|
|
while (1) {
|
|
|
|
while (1) // until we've selected a file
|
|
{
|
|
// Get entries from specified path, don't filter by file extension,
|
|
// get files and directories, get a maximum of 4000 entries, and update path if dir changed
|
|
num_files = CDVD_GetDir(pathname, NULL, CDVD_GET_FILES_AND_DIRS, TocEntryList, 4000, pathname);
|
|
|
|
if (num_files < list_max)
|
|
list_size = num_files;
|
|
else
|
|
list_size = list_max;
|
|
|
|
// Don't leave the drive spinning, it's annoying !
|
|
CDVD_Stop();
|
|
|
|
while (1) // Until we've selected something (dir or file)
|
|
{
|
|
|
|
// Get button presses
|
|
// If X then select the previously highlighted file
|
|
// If up/down then increase/decrease the selected file
|
|
int padState;
|
|
|
|
// only listen to pad input if it's plugged in, and stable
|
|
padState = padGetState(0, 0);
|
|
if (padState == PAD_STATE_STABLE) {
|
|
padRead(0, 0, &padButtons);
|
|
ps2_buttons = (padButtons.btns[0] << 8) | padButtons.btns[1];
|
|
ps2_buttons = ~ps2_buttons;
|
|
|
|
if (num_files > 0) {
|
|
// file Selected
|
|
if (ps2_buttons & PAD_CROSS) {
|
|
if (button_released == TRUE) {
|
|
button_released = FALSE;
|
|
break;
|
|
}
|
|
} else
|
|
button_released = TRUE;
|
|
|
|
// DPAD + Shoulder file Selection
|
|
if (ps2_buttons & PAD_UP)
|
|
selected -= 0.15;
|
|
else if (ps2_buttons & PAD_DOWN)
|
|
selected += 0.15;
|
|
else if (ps2_buttons & PAD_R1)
|
|
selected -= 1;
|
|
else if (ps2_buttons & PAD_R2)
|
|
selected += 1;
|
|
else if (ps2_buttons & PAD_L1)
|
|
selected = 1;
|
|
else if (ps2_buttons & PAD_L2)
|
|
selected = num_files;
|
|
}
|
|
|
|
if (ps2_buttons & PAD_SELECT) {
|
|
strcpy(pathname, "/");
|
|
|
|
ClearScreen();
|
|
|
|
myFont.Print(0, 640, 220, 4,
|
|
TEXT_COL_BRIGHT,
|
|
GSFONT_ALIGN_CENTRE, "Please Change CD\nThen Press 'X'");
|
|
|
|
pDisplay->drawPipe.Flush();
|
|
|
|
// Wait for VSync and then swap buffers
|
|
pDisplay->WaitForVSync();
|
|
|
|
pDisplay->swapBuffers();
|
|
|
|
|
|
CDVD_FlushCache();
|
|
strcpy(pathname, "/");
|
|
|
|
while (1) {
|
|
int padState;
|
|
|
|
// only listen to pad input if it's plugged in, and stable
|
|
padState = padGetState(0, 0);
|
|
if (padState == PAD_STATE_STABLE) {
|
|
padRead(0, 0, &padButtons);
|
|
ps2_buttons = (padButtons.btns[0] << 8) | padButtons.btns[1];
|
|
ps2_buttons = ~ps2_buttons;
|
|
|
|
// ROM Selected
|
|
if (ps2_buttons & PAD_CROSS) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
pDisplay->WaitForVSync();
|
|
}
|
|
|
|
num_files = CDVD_GetDir(pathname, NULL, CDVD_GET_FILES_AND_DIRS, TocEntryList, 4000, pathname);
|
|
|
|
if (num_files < list_max)
|
|
list_size = num_files;
|
|
else
|
|
list_size = list_max;
|
|
|
|
selected = 1;
|
|
|
|
CDVD_Stop();
|
|
}
|
|
|
|
if ((padButtons.mode >> 4) == 0x07) {
|
|
// Analogue file selection
|
|
float pad_v;
|
|
|
|
pad_v = (float)(padButtons.ljoy_v - 128); // Range = +127 to -128
|
|
|
|
|
|
if (pad_v > 32) {
|
|
// scrolling down, so incrementing selected tom
|
|
pad_v -= 32;
|
|
selected += (pad_v / 96);
|
|
}
|
|
|
|
if (pad_v < -32) {
|
|
// scrolling down, so incrementing selected tom
|
|
pad_v += 32;
|
|
selected += (pad_v / 96);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (selected < 1)
|
|
selected = 1;
|
|
|
|
if ((int)selected > num_files)
|
|
selected = (float)num_files;
|
|
}
|
|
|
|
// calculate which file to display first in the list
|
|
if ((int)selected <= list_size / 2)
|
|
first_file = 1;
|
|
else {
|
|
if ((int)selected >= (num_files - (list_size / 2) + 1))
|
|
first_file = num_files - list_size + 1;
|
|
else
|
|
first_file = (int)selected - ((list_size / 2));
|
|
}
|
|
|
|
// calculate the offset of the selected file into the displayed list
|
|
offset = (int)selected - first_file;
|
|
|
|
|
|
ClearScreen();
|
|
|
|
if (num_files > 0) {
|
|
// pDisplay->drawPipe.setScissorRect(list_xpos,list_ypos,list_xpos+list_width,list_ypos+list_height);
|
|
|
|
for (int file = 0; file < list_size; file++) {
|
|
// if the entry is a dir, then display the directory symbol before the name
|
|
if (TocEntryList[first_file + file - 1].fileProperties & 0x02) {
|
|
// display a dir symbol (character 001 in the bitmap font)
|
|
myFont.Print(128, 640, filelisty + (file * 18), 4, GS_SET_RGBA(0x80, 0x80, 0x80, 0x80), GSFONT_ALIGN_LEFT, "\001");
|
|
|
|
if (file == ((int)selected - first_file)) {
|
|
myFont.Print(148, 640, filelisty + (file * 18), 4, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
TocEntryList[first_file + file - 1].filename);
|
|
} else {
|
|
myFont.Print(148, 640, filelisty + (file * 18), 4, TEXT_COL_DIM, GSFONT_ALIGN_LEFT,
|
|
TocEntryList[first_file + file - 1].filename);
|
|
}
|
|
} else {
|
|
if (file == ((int)selected - first_file)) {
|
|
myFont.Print(128, 640, filelisty + (file * 18), 4, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
TocEntryList[first_file + file - 1].filename);
|
|
} else {
|
|
myFont.Print(128, 640, filelisty + (file * 18), 4, TEXT_COL_DIM, GSFONT_ALIGN_LEFT,
|
|
TocEntryList[first_file + file - 1].filename);
|
|
}
|
|
}
|
|
}
|
|
|
|
myFont.Print(420, 640, 440, 0, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
"Press X to Select");
|
|
|
|
myFont.Print(420, 640, 458, 0, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
"Press SELECT to Change CD");
|
|
}
|
|
|
|
|
|
pDisplay->drawPipe.Flush();
|
|
|
|
// Wait for VSync and then swap buffers
|
|
pDisplay->WaitForVSync();
|
|
|
|
pDisplay->swapBuffers();
|
|
}
|
|
|
|
// We've selected something, but is it a file or a dir ?
|
|
if (TocEntryList[((int)selected) - 1].fileProperties & 0x02) {
|
|
// Append name onto current path
|
|
//gui_getfile_dispname((int)selected, tempname);
|
|
strcat(pathname, "/");
|
|
strcat(pathname, TocEntryList[((int)selected) - 1].filename);
|
|
|
|
// file list will be got next time round the while loop
|
|
|
|
// Start from top of list
|
|
selected = 1;
|
|
} else {
|
|
// It's not a dir, so it must be a file
|
|
break;
|
|
}
|
|
}
|
|
|
|
char size_string[64];
|
|
|
|
if (TocEntryList[((int)selected) - 1].fileSize < (2 * 1024))
|
|
sprintf(size_string, "%d bytes", TocEntryList[((int)selected) - 1].fileSize);
|
|
else {
|
|
if (TocEntryList[((int)selected) - 1].fileSize < (2 * 1024 * 1024))
|
|
sprintf(size_string, "%d Kb", TocEntryList[((int)selected) - 1].fileSize / 1024);
|
|
else
|
|
sprintf(size_string, "%d Mb", TocEntryList[((int)selected) - 1].fileSize / (1024 * 1024));
|
|
}
|
|
|
|
|
|
for (int frame = 0; frame < 200; frame++) {
|
|
|
|
// Selected a file, so display file properties for a couple of seconds
|
|
ClearScreen();
|
|
|
|
myFont.Print(100, 200, 220, 1, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
"File name:");
|
|
|
|
myFont.Print(200, 640, 220, 1, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
TocEntryList[((int)selected) - 1].filename);
|
|
|
|
myFont.Print(100, 200, 240, 1, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
"File path:");
|
|
|
|
myFont.Print(200, 640, 240, 1, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
pathname);
|
|
|
|
|
|
myFont.Print(100, 200, 260, 1, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
"File size:");
|
|
|
|
myFont.Print(200, 640, 260, 1, TEXT_COL_BRIGHT, GSFONT_ALIGN_LEFT,
|
|
size_string);
|
|
|
|
pDisplay->drawPipe.Flush();
|
|
|
|
// Wait for VSync and then swap buffers
|
|
pDisplay->WaitForVSync();
|
|
|
|
pDisplay->swapBuffers();
|
|
}
|
|
}
|
|
|
|
free(fontTex);
|
|
|
|
free(TocEntryList);
|
|
|
|
delete pDisplay;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int WaitPadReady(int port, int slot)
|
|
{
|
|
int state = 0;
|
|
|
|
while ((state != PAD_STATE_STABLE) &&
|
|
(state != PAD_STATE_FINDCTP1)) {
|
|
state = padGetState(port, slot);
|
|
|
|
if (state == PAD_STATE_DISCONN)
|
|
break; // If no pad connected then dont wait for it to be plugged in
|
|
|
|
//pEmuDisplay->WaitForVSync();
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
|
|
void SetPadMode(int port, int slot)
|
|
{
|
|
// If the controller is already plugged in then
|
|
// put the controller into Analogue mode (and lock it)
|
|
// so that analogue stick can be used
|
|
|
|
if (WaitPadReady(port, slot) == PAD_STATE_STABLE) // if pad is connected then initialise it
|
|
{
|
|
padSetMainMode(port, slot, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK);
|
|
|
|
WaitPadReady(port, slot);
|
|
}
|
|
}
|