psxsdk/examples/psxs3m/psxs3m.c

413 lines
7.5 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <psx.h>
#include <f3m.h>
#if defined(EXAMPLES_VMODE) == VMODE_PAL
#define TICKS_PER_SECOND 50
#else
#define TICKS_PER_SECOND 60
#endif
unsigned int primList[0x8000];
int dbuf = 0;
volatile int display_is_old = 1;
char current_dir[256] = "cdrom:";
char name_buf[24];
char name_buf2[32];
mod_s *music = NULL;
player_s player;
int music_loop;
char *music_player_fname;
int music_player_time;
short music_player_vol;
int music_player_vol_pc;
GsRectangle prog_rect;
void program_vblank_handler()
{
display_is_old = 1;
}
struct
{
char name[20];
int size;
int type; /* 0 = file, 1 = directory */
}file_list[256];
int file_list_size = 0;
int file_list_pos = 0;
int wasUp = 0;
int wasDown = 0;
int wasEnter = 0;
int wasLeft = 0;
int wasRight = 0;
void update_file_list()
{
struct DIRENTRY de;
struct DIRENTRY *r;
char *cp;
int i, k=0;
if(strcmp(current_dir, "cdrom:") != 0)
{
strcpy(file_list[0].name, "..");
file_list[0].type = 1;
k=1;
}
r = firstfile("cdrom:*", &de);
for(i = k; i < 256 && r; i++)
{
if(de.name[0] == 0x1)
{
// Throw away useless entry.
r = nextfile(&de);
i--;
continue;
}
memcpy(file_list[i].name, de.name, 20);
if((cp = strrchr(file_list[i].name, ';')))
{
*cp = '\0';
file_list[i].type = 0;
}
else
file_list[i].type = 1;
file_list[i].size = de.size;
r = nextfile(&de);
}
file_list[i].size = -1;
file_list_size = i;
}
void file_browser(int redraw)
{
int i, k, allowed_ext;
unsigned short padbuf;
char *cp;
PSX_ReadPad(&padbuf, NULL);
if(wasUp)
wasUp++;
if(wasDown)
wasDown++;
if((padbuf & PAD_UP) && !wasUp)
{
if(file_list_pos > 0)
{
file_list_pos--;
redraw=1;
}
wasUp=1;
}
if((padbuf & PAD_DOWN) && !wasDown)
{
file_list_pos++;
if(file_list[file_list_pos].size == -1)
file_list_pos--;
else
redraw = 1;
wasDown = 1;
}
if((padbuf & PAD_CROSS) && !wasEnter)
{
if(file_list[file_list_pos].type == 1)
allowed_ext = 1;
else
allowed_ext = 0;
if((cp = strchr(file_list[file_list_pos].name, '.')))
{
if(strcmp(cp+1, "S3M") == 0)
allowed_ext = 1;
}
if(allowed_ext)
{
if(file_list[file_list_pos].type == 0)
{
if(music != NULL)
{
f3m_mod_free(music);
music = NULL;
}
// It is a file, we will play it
sprintf(name_buf2, "cdrom:%s;1", file_list[file_list_pos].name);
music = f3m_mod_load_filename(name_buf2);
f3m_player_init(&player, music);
music_player_fname = file_list[file_list_pos].name;
music_player_time = 0;
music_player_vol = SPU_MAXVOL+1;
music_player_vol_pc = 100;
f3m_set_max_volume(&player, music_player_vol-1);
music_loop = -1;
}
else
{
// It is a directory, we will go inside it
if(strcmp(file_list[file_list_pos].name, "..") == 0)
{
*(strrchr(current_dir, '\\')) = '\0';
if(strcmp(current_dir, "cdrom:") == 0)
chdir("cdrom:\\");
else
chdir(current_dir);
}
else
{
strcat(current_dir, "\\");
strcat(current_dir, file_list[file_list_pos].name);
chdir(current_dir);
}
file_list_pos = 0;
update_file_list();
redraw = 1;
}
}
wasEnter = 1;
}
if(!(padbuf & PAD_UP) || wasUp >= 15)
wasUp = 0;
if(!(padbuf & PAD_DOWN) || wasDown >= 15)
wasDown = 0;
if(!(padbuf & PAD_CROSS))
wasEnter = 0;
/* Drawing */
if(!redraw)
return;
GsSortCls(0, 0, 0);
GsPrintFont(0, 0, "-= PsxS3M =-");
GsPrintFont(0, 8, "Folder: <root>%s", current_dir + 6);
GsPrintFont(0, 16, "X to play, hold SELECT to convert SFX");
k=0;
if(file_list_size > 24)
{
if(file_list_pos > 12)
{
k = file_list_pos - 12;
if(k > (file_list_size - 26))
k = file_list_size - 26;
}
}
prog_rect.x = 0;
prog_rect.y = 32 + ((file_list_pos-k) * 8);
prog_rect.w = GsScreenW / 2;
prog_rect.h = 8;
prog_rect.r = 0;
prog_rect.g = 0;
prog_rect.b = 255;
prog_rect.attribute = 0;
GsSortRectangle(&prog_rect);
for(i = 0; file_list[i+k].size != -1; i++)
{
if(file_list[i+k].type == 1)
GsPrintFont(0, 32 + (i * 8), " +- %s", file_list[i+k].name);
else
GsPrintFont(0, 32 + (i * 8), " %s", file_list[i+k].name);
}
GsDrawList();
dbuf = !dbuf;
GsSetDispEnvSimple(0, dbuf?256:0);
GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240);
}
void music_player_draw()
{
unsigned short padbuf;
static int old_song_pos = 10000;
int change_vol = 0;
GsSortCls(0, 0, 0);
GsPrintFont(0, 0, "-= PsxS3M =-");
GsPrintFont(0, 8, "File: %s", music_player_fname);
GsPrintFont(0, 16, "Title: %s", music->name);
GsPrintFont(0, 24, "ord:%03d/%03d pat:%03d/%03d pos:%02X spd:%d/%d",
player.cord, music->ord_num - 1, player.cpat, music->pat_num - 1, player.crow,
music->ispeed, music->itempo);
GsPrintFont(0, 32, "vol: %03d%%/100%% time: %d:%02d",
music_player_vol_pc, music_player_time / (TICKS_PER_SECOND * 60),
(music_player_time % (TICKS_PER_SECOND * 60) ) / TICKS_PER_SECOND);
GsPrintFont(0, 56, "Press X to change music.");
dbuf = !dbuf;
GsSetDispEnvSimple(0, dbuf?256:0);
GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240);
GsDrawList();
if(old_song_pos > player.cord)
music_player_time = 0;
PSX_ReadPad(&padbuf, NULL);
if(padbuf & PAD_UP)
{
music_player_vol+=32;
change_vol = 1;
}
if(padbuf & PAD_DOWN)
{
music_player_vol-=32;
change_vol = 1;
}
if(padbuf & PAD_LEFT)
{
if(!wasLeft)
{
player.crow = 0;
player.cord--;
player.crow = 64;
if(player.cord > -1)
player.cord--;
}
wasLeft++;
}
if(padbuf & PAD_RIGHT)
{
if(!wasRight)
{
player.crow = 64;
}
wasRight++;
}
if(!(padbuf & PAD_LEFT) || wasLeft >= 15)
wasLeft = 0;
if(!(padbuf & PAD_RIGHT) || wasRight >= 15)
wasRight = 0;
if((padbuf & PAD_CROSS) && !wasEnter)
{
f3m_player_stop(&player);
f3m_mod_free(music);
music = NULL;
wasEnter = 1;
}
if(!(padbuf & PAD_CROSS))
wasEnter = 0;
if(music_player_vol < 0)
music_player_vol = 0;
if(music_player_vol > (SPU_MAXVOL+1))
music_player_vol = SPU_MAXVOL+1;
if(change_vol)
{
music_player_vol_pc = (int)((float)100 * ((float)music_player_vol / (float)(SPU_MAXVOL+1)));
f3m_set_max_volume(&player, (music_player_vol == 0)?0:(music_player_vol-1));
}
music_player_time++;
old_song_pos = player.cord;
}
int main()
{
int redraw=1;
FILE *f;
PSX_Init();
GsInit();
SsInit();
GsClearMem();
GsSetAutoWait();
GsSetList(primList);
GsSetVideoMode(320, 240, EXAMPLES_VMODE);
GsLoadFont(768, 0, 768, 256);
SetVBlankHandler(program_vblank_handler);
// Open any existing file before calling firstfile() for the first time.
// If before calling firstfile() for the first time, you have never called open() on an existing file before,
// every subsequent read will fail but it will report that files are opened ok!
// This bug happens at least with the SCPH1001 BIOS version.
// We try to open PSX.EXE and SYSTEM.CNF, as one of them must exist in order to boot from CDROM.
f = fopen("cdrom:PSX.EXE;1", "rb");
if(f)fclose(f);
f = fopen("cdrom:SYSTEM.CNF;1", "rb");
if(f)fclose(f);
update_file_list();
dbuf = !dbuf;
GsSetDispEnvSimple(0, dbuf?256:0);
GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240);
while(1)
{
if(display_is_old)
{
/* Update music */
if(music)
{
redraw = 1;
f3m_player_play(&player);
// MODPlay(music, &music_loop);
music_player_draw();
}
else
{
file_browser(redraw);
redraw=0;
}
display_is_old = 0;
}
}
}