#include #include #include #include #include #include #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: %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; } } }