473 lines
8.8 KiB
C
473 lines
8.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <psx.h>
|
|
#include <modplay.h>
|
|
|
|
#if defined(EXAMPLES_VMODE) == VMODE_PAL
|
|
#define TICKS_PER_SECOND 50
|
|
#else
|
|
#define TICKS_PER_SECOND 60
|
|
#endif
|
|
|
|
unsigned char fileBuffer[0x80000]; // 512 kilobytes
|
|
|
|
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];
|
|
ModMusic *music = NULL;
|
|
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, ok, allowed_ext;
|
|
unsigned short padbuf;
|
|
char *cp;
|
|
FILE *f;
|
|
|
|
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, "MOD") == 0)
|
|
allowed_ext = 1;
|
|
}
|
|
|
|
if(allowed_ext)
|
|
{
|
|
if(file_list[file_list_pos].type == 0)
|
|
{
|
|
if(music != NULL)
|
|
{
|
|
MODUnload(music);
|
|
music = NULL;
|
|
}
|
|
|
|
// It is a file, we will play it
|
|
|
|
// First check if there is a file which contains the
|
|
// samples
|
|
strcpy(name_buf, file_list[file_list_pos].name);
|
|
|
|
if((cp = strchr(name_buf, '.')))
|
|
*(cp+1) = '\0';
|
|
|
|
strcat(name_buf, "SMP");
|
|
|
|
ok = 0;
|
|
|
|
if(!(padbuf & PAD_SELECT))
|
|
{
|
|
for(i = 0; file_list[i].size != -1; i++)
|
|
{
|
|
if(strcmp(name_buf, file_list[i].name) == 0)
|
|
{
|
|
ok = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ok)
|
|
{
|
|
// We found a sample file
|
|
printf("Loading sample file for %s...\n",
|
|
file_list[file_list_pos].name);
|
|
|
|
sprintf(name_buf2, "cdrom:%s;1", name_buf);
|
|
printf("namebuf2=%s\n",name_buf2);
|
|
|
|
f = fopen(name_buf2, "rb");
|
|
|
|
// printf("SZ = %d\n", file_list[i].size);
|
|
|
|
fread(fileBuffer, sizeof(char), file_list[i].size, f);
|
|
fclose(f);
|
|
|
|
memcpy(name_buf, fileBuffer, 8);
|
|
name_buf[8] = 0;
|
|
|
|
MOD4PSX_Upload(fileBuffer, SPU_DATA_BASE_ADDR);
|
|
}
|
|
else
|
|
printf("No sample file found for %s!\n",
|
|
file_list[file_list_pos].name);
|
|
|
|
sprintf(name_buf2, "cdrom:%s;1", file_list[file_list_pos].name);
|
|
|
|
f = fopen(name_buf2, "rb");
|
|
|
|
fread(fileBuffer, sizeof(char), file_list[file_list_pos].size, f);
|
|
|
|
fclose(f);
|
|
|
|
music = MODLoadEx(fileBuffer, ok?MODLOAD_NOSAMPLES:0);
|
|
|
|
if(!ok)
|
|
MODUploadSamples(music, SPU_DATA_BASE_ADDR);
|
|
|
|
music_player_fname = file_list[file_list_pos].name;
|
|
music_player_time = 0;
|
|
music_player_vol = SPU_MAXVOL+1;
|
|
music_player_vol_pc = 100;
|
|
MODSetMaxVolume(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, "-= PsxMod =-");
|
|
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, "-= PsxMod =-");
|
|
GsPrintFont(0, 8, "File: %s", music_player_fname);
|
|
GsPrintFont(0, 16, "Title: %s", music->title);
|
|
GsPrintFont(0, 24, "pat:%03d/%03d pos:%02X spd:%d/%d",
|
|
music->song_pos, music->song_pos_num - 1, music->pat_pos,
|
|
music->ticks_division, music->beats_minute);
|
|
|
|
GsPrintFont(0, 32, "vol: %03d%%/100%% time: %d:%02d chn: %d",
|
|
music_player_vol_pc, music_player_time / (TICKS_PER_SECOND * 60),
|
|
(music_player_time % (TICKS_PER_SECOND * 60) ) / TICKS_PER_SECOND,
|
|
music->channel_num);
|
|
|
|
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 > music->song_pos)
|
|
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)
|
|
{
|
|
music->pat_pos = 0;
|
|
|
|
if(music->song_pos > 0)
|
|
music->song_pos--;
|
|
}
|
|
|
|
wasLeft++;
|
|
}
|
|
|
|
if(padbuf & PAD_RIGHT)
|
|
{
|
|
if(!wasRight)
|
|
{
|
|
music->pat_pos = 0;
|
|
|
|
if(music->song_pos < (music->song_pos_num - 1))
|
|
music->song_pos++;
|
|
else
|
|
music->song_pos = 0;
|
|
}
|
|
|
|
wasRight++;
|
|
}
|
|
|
|
if(!(padbuf & PAD_LEFT) || wasLeft >= 15)
|
|
wasLeft = 0;
|
|
|
|
if(!(padbuf & PAD_RIGHT) || wasRight >= 15)
|
|
wasRight = 0;
|
|
|
|
if((padbuf & PAD_CROSS) && !wasEnter)
|
|
{
|
|
MODStop(music);
|
|
MODUnload(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)));
|
|
MODSetMaxVolume((music_player_vol == 0)?0:(music_player_vol-1));
|
|
}
|
|
|
|
music_player_time++;
|
|
|
|
old_song_pos = music->song_pos;
|
|
}
|
|
|
|
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;
|
|
MODPlay(music, &music_loop);
|
|
music_player_draw();
|
|
}
|
|
else
|
|
{
|
|
file_browser(redraw);
|
|
redraw=0;
|
|
}
|
|
|
|
display_is_old = 0;
|
|
}
|
|
}
|
|
}
|