diff --git a/src/d_main.c b/src/d_main.c index 2a5993c1776ab4e1d8de58e106912af91cadb14e..29a916863a9231afead3d6722a623374d7afb21d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1350,6 +1350,7 @@ void D_SRB2Main(void) I_StartupSound(); I_InitMusic(); S_InitSfxChannels(cv_soundvolume.value); + S_InitMusicDefs(); CONS_Printf("ST_Init(): Init status bar.\n"); ST_Init(); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 64580c82daf0e7b04d2c5ccb7510cc5cb93931d6..a38e91a78c8a8ffbf264ad1c8f0606d0a979b294 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2130,12 +2130,18 @@ static void HU_DrawDemoInfo(void) // static void HU_DrawSongCredits(void) { - const char *str = va("\x1F"" %s", songCredits[cursongcredit.index].info); - INT32 len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE); - INT32 destx = (len+7); + char *str; + INT32 len, destx; INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32); INT32 bgt; + if (!cursongcredit.def) // No def + return; + + str = va("\x1F"" %s", cursongcredit.def->source); + len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE); + destx = (len+7); + if (cursongcredit.anim) { if (cursongcredit.trans > 0) diff --git a/src/k_kart.c b/src/k_kart.c index 63425d1afbf9365f7c9580d012539a7f34e519be..50d19c199541c8b8d4610f2f9eab5d9eb09ba3d6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4446,7 +4446,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (P_IsLocalPlayer(player) && leveltime == (starttime + (TICRATE/2))) { S_ChangeMusicInternal(mapmusname, true); - S_InitMusicCredit(); + S_ShowMusicCredit(); } } diff --git a/src/p_setup.c b/src/p_setup.c index 57a069a1fc7d1db6d0ceba7d82e941f9e84dce4b..90ac3a7cf28189d585ffe1f03ec1e9cb99a221ea 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3439,6 +3439,11 @@ boolean P_AddWadFile(const char *wadfilename) // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] + // + // edit music defs + // + S_LoadMusicDefs(wadnum); + // // search for maps // diff --git a/src/p_spec.c b/src/p_spec.c index b6661bba0fcf5258b897d3b546fd13ad921cf4e1..e3b54cbeaed301efb46b93fabde0303bad1a2d29 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2450,7 +2450,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) mapmusflags |= MUSIC_RELOADRESET; S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4)); - S_InitMusicCredit(); + S_ShowMusicCredit(); // Except, you can use the ML_BLOCKMONSTERS flag to change this behavior. // if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn. diff --git a/src/s_sound.c b/src/s_sound.c index 87ab6359ada4f23cedf701d5e435ece9e3005c2d..e3a62768e52f363761b85ba2eeb756240e1a31c0 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1541,131 +1541,209 @@ static void *music_data; static UINT16 music_flags; static boolean music_looping; -songcredits_t songCredits[] = { - // Race maps - {"kmap01","Toot Toot Sonic Warrior (Instrumental) - Sonic CD"}, - {"kmap02","Chao Race (Extended Mix) - Sonic Adventure 2"}, - {"kmap03","Touhou 10.5: Broken Moon (Jazz Arrangement) - Tokyo Active NEETs"}, - {"kmap04","Mortvia Fountain - Castlevania: Curse of Darkness"}, - {"kmap05","Let's Go Away - Daytona USA"}, - {"kmap06","War Machine - Marvel vs. Capcom"}, - {"kmap07","Sonic 3D Blast: Green Grove Zone, Act 1 (Remix) - Tee Lopes"}, - {"kmap08","Sonic Drift 2: Hill Top (Remix) - SeventhSentinel"}, - {"kmap09","Industrial District - Columns III"}, - {"kmap10","Dream Uneven Bars - Mario & Sonic at the London 2012 Olympic Games"}, - {"kmap11","Moon Palace 2 - Drift City"}, - {"kmap12","Authentic Sky - Tekken 4"}, - {"kmap13","Plant Man's Stage - Rockman 6 Complete Works"}, - {"kmap14","Twinkle Cart - Sonic Adventure"}, - {"kmap15","Pleasure Castle - Sonic Adventure"}, - {"kmap16","Horizon Heights Zone, Act 2 - Sonic: After the Sequel"}, - {"kmap17","Frost Man's Stage - Mega Man 8"}, - {"kmap18","Foliage Furnace Zone, Act 1 - Sonic: After the Sequel"}, - {"kmap19","Sand Ocean - F-Zero"}, - {"kmap20","El Anoir Field South - LaTale"}, - {"kmap21","Western GunRun - LaTale"}, - {"kmap22","Jr. Street - Mario Hoops 3 on 3"}, - {"kmap23","Fight or Flight (Air Armada) - Rivals of Aether"}, - {"kmap24","White Land I - F-Zero"}, - {"kmap25","Donkey Kong Country: Fear Factory (Remix) - Vincent Rubinetti"}, - {"kmap26","Desert Palace - Sonic the Hedgehog 3"}, - {"kmap27","Aurora Atoll Zone - SeventhSentinel"}, - {"kmap28","Hol Horse - JoJo's Bizarre Adventure (Arcade)"}, - {"kmap29","Red Barrage Area - Sonic Adventure"}, - {"kmap30","Reach Out To The Truth - Persona 4 Arena"}, - {"kmap31","Ave de Rapina - Beatmania IIDX 7th Style"}, - {"kmap32","Atomic Waste Zone - Michael Staple"}, - {"kmap33","Desert Area - LaTale"}, - {"kmap34","DuckTales: The Moon (Remix) - Chris Holland, Luke Kwing"}, - {"kmap35","Eggman Empire Zone - Michael Staple"}, - {"kmap36","Shooting Star - Elwood"}, - {"kmap37","Vigaku (Theme of Ein) - Dead or Alive 2"}, - {"kmap38","Lovely Gate 3 - Sonic Adventure 2"}, - {"kmap39","The Biggest Dreamer - Digimon Rumble Arena"}, - {"kmap40","Soft Collision - Mighty Switch Force 2"}, - {"kmap41","Ganbare Dochu - Konami Krazy Racers"}, - {"kmap42","Theme of 'CHAO' - Sonic Adventure"}, - {"kmap43","Join Us 4 Happy Time - Sonic Adventure"}, - {"kmap44","Search ~ In the Midst - Ace Attorney: Justice for All"}, - {"kmap45","Venezia, Italy - Tekken"}, - {"kmap46","Balloon Panic - Sonic Drift 2"}, - {"kmap47","Dimension Heist - Sonic Mania"}, - {"kmap48","MKSC Sky Garden (Remix) - Mario Kart DS"}, - {"kmap49","MKDS Peach Gardens (Remix) - Mario Kart Wii"}, - {"kmap50","MKSC Rainbow Road (Remix) - Panman14"}, - {"kmap51","Donut Plains - Super Mario Kart"}, - {"kmap52","Mario Circuit - Super Mario Kart"}, - {"kmap53","Ghost Valley - Super Mario Kart"}, - {"kmap54","Bowser Castle - Super Mario Kart"}, - {"kmap55","Vanilla Lake - Super Mario Kart"}, - // Battle maps - {"kmapb0","Tropic Turf Zone, Act 1 - Karl Brueggemann"}, - {"kmapb1","Seascape - Knuckles' Chaotix"}, - {"kmapb2","Boss Challenge I - Diddy Kong Racing"}, - {"kmapb3","Al's Toy Barn - Toy Story 2 (PS1)"}, - {"kmapb4","SRB2: Techno Hill Zone, Act 1 (Remix) - SeventhSentinel"}, - {"kmapb5","Sonic the Hedgehog: Marble Zone (Remix) - Tee Lopes"}, - {"kmapb6","Phi Battle - Sonic Battle"}, - {"kmapb7","Khan - JoJo's Bizarre Adventure (Arcade)"}, - {"kmapb8","Underground - Wild Guns Reloaded"}, - {"kmapb9","Disease Transport - DrTapeworm"}, - {"kmapba","Shining Force II: Shrine (Remix) - gxf4c3"}, - {"kmapbb","Bad Taste Aquarium - Sonic Adventure"}, - {"kmapbc","Space Ship: Strut - Space Channel 5"}, - {"kmapbd","Strollin' the City - Karl Brueggemann"}, - {"kmapbe","Fakery Way - Sonic Adventure"}, - {"kmapbf","Twinkle Circuit - Sonic Adventure"}, - {"kmapbg","Never Let It Go - Sonic the Fighters"}, - {"kmapbh","Power Plant - Sonic Heroes"}, - {"kmapbi","Tails' Lab - Sonic Battle"}, - {"kmapbj","Mega Man X: Armored Armadillo's Stage (Arranged) - Synthescissor"}, - {"kmapbk","School Ordeal - Danganronpa V3: Killing Harmony"}, - {"kmapbl","Mementos - Persona 5"}, - {"kmapbm","Special Stage (US) - Sonic CD"}, - {"kmapbn","Battle Mode - Super Mario Kart"}, - {"kmapbp","Vanilla Lake (Beta) - Super Mario Kart"}, - {"kmapbr","Choco Mountain - Mario Kart 64"}, - // Hell maps - {"kmaph0","Neo City - Drift City"}, - {"kmaph1","World Open Finals - Mario Power Tennis"}, - {"kmaph2","Arid Sands: Day - Sonic Unleashed"}, - {"kmaph3","Graveyard Gig - Sonic & All-Stars Racing Transformed"}, - {"kmaph4","Dr. Robotnik's Mean Bean Machine: 2 Player (Remix) - Jonny Atma, The8BitDrummer"}, - {"kmaph5","Living In One More City - Nib Roc"}, - {"kmaph6","Ema Skye ~ Scientific Detective - Apollo Justice: Ace Attorney"}, - {"kmaph7","4 Minutes Before Death - Ghost Trick: Phantom Detective"}, - {"kmaph8","Napoleon Disappeared!? - Pop'n Music 10"}, - {"kmaph9","Retro Maze - Pac-Man World Rally"}, - {"kmapha","Midnight Freeze Zone - Arrow, SSNTails"}, - {"kmaphb","Townsville Raceway - Cartoon Network Racing (DS)"}, - {"kmaphc","F-Zero: Silence (Remix) - Tony Thai"}, - {"kmaphd","Rainbow Road - Super Mario Kart"}, - {"kmaphe","Meadow Match Zone - Arrow, SSNTails"}, - {"kmaphf","merge-break - xaki"}, - // Misc - {"titles","Fluvial Beat Deposits - Simon Stalenhag"}, // Stålenhag - {"vote", "Chaotic World - Knuckles' Chaotix"}, - {"voteea","Decision - Knuckles' Chaotix"}, - {"voteeb","Decision - Knuckles' Chaotix"}, - {"kinvnc","Invincibility - Sonic the Hedgehog 3"}, - {"kgrow", "Surging Power - Knuckles' Chaotix"}, - {"kstart","Race Start - Diddy Kong Racing"}, - {"estart","Phantom Ruby Ambience - Sonic Mania"}, - {"krwin", "Practice - Sora"}, - {"krok", "Practice - Sora"}, - {"krlose","Hit 'Em Up (Instrumental) - 2Pac"}, - {"krfail","Results - F-Zero"}, - {"kbwin", "Wild Charabom Defeated! - Bomberman Tournament"}, - {"kbok", "Deadly Bomber Base Cleared! - Bomberman Tournament"}, - {"kblose","You Lose! - Bomberman Tournament"}, - {"racent","Menu - Metropolis Street Racer"}, - {"wait2j","Competition Results - Sonic the Hedgehog 3"}, - {"chalng","Sonic the Hedgehog 3: Minor Boss (Dual PCM) - MarkeyJester"}, - {"credit","Moot Booxle - Chomp"}, - {NULL,NULL} -}; +/// ------------------------ +/// Music Definitions +/// ------------------------ + +musicdef_t *musicdefstart = NULL; // First music definition +struct cursongcredit cursongcredit; // Currently displayed song credit info + +// +// search for music definition in wad +// +static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid) +{ + UINT16 i; + lumpinfo_t *lump_p; + + lump_p = wadfiles[wadid]->lumpinfo; + for (i = 0; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name, "MUSICDEF", 8) == 0) + return i; + + return INT16_MAX; // not found +} + +void S_LoadMusicDefs(UINT16 wadnum) +{ + UINT16 lump; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + musicdef_t *def, *prev; + UINT16 line = 1; // for better error msgs + + lump = W_CheckForMusicDefInPwad(wadnum); + if (lump == INT16_MAX) + return; + + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("S_LoadMusicDefs: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + def = prev = NULL; + + stoken = strtok (buf2, "\r\n "); + // Find music def + while (stoken) + { + /*if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#')) // skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + if (def) + stoken = strtok(NULL, "\r\n= "); + else + stoken = strtok(NULL, "\r\n "); + line++; + } + else*/ if (!stricmp(stoken, "lump")) + { + value = strtok(NULL, "\r\n "); + + if (!value) + { + CONS_Alert(CONS_WARNING, "MUSICDEF: Lump '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_lump; + } + + // No existing musicdefs + if (!musicdefstart) + { + musicdefstart = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); + STRBUFCPY(musicdefstart->name, value); + strlwr(musicdefstart->name); + def = musicdefstart; + //CONS_Printf("S_LoadMusicDefs: Initialized musicdef w/ song '%s'\n", def->name); + } + else + { + def = musicdefstart; + + // Search if this is a replacement + //CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n"); + while (def) + { + if (!stricmp(def->name, value)) + { + //CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name); + break; + } + + prev = def; + def = def->next; + } + + // Nothing found, add to the end. + if (!def) + { + def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); + STRBUFCPY(def->name, value); + strlwr(def->name); + if (prev != NULL) + prev->next = def; + //CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name); + } + } + +skip_lump: + stoken = strtok(NULL, "\r\n "); + line++; + } + else + { + value = strtok(NULL, "\r\n= "); + + if (!value) + { + CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_field; + } + + if (!def) + { + CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); + free(buf2); + return; + } + + if (!stricmp(stoken, "usage")) { +#if 0 // Ignore for now + STRBUFCPY(def->usage, value); + for (value = def->usage; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + //CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage); +#endif + } else if (!stricmp(stoken, "source")) { + STRBUFCPY(def->source, value); + for (value = def->source; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + //CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->source); + } else { + CONS_Alert(CONS_WARNING, "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); + } + +skip_field: + stoken = strtok(NULL, "\r\n= "); + line++; + } + } + + free(buf2); + return; +} + +// +// S_InitMusicDefs +// +// Simply load music defs in all wads. +// +void S_InitMusicDefs(void) +{ + UINT16 i; + for (i = 0; i < numwadfiles; i++) + S_LoadMusicDefs(i); +} -struct cursongcredit cursongcredit; +// +// S_ShowMusicCredit +// +// Display current song's credit on screen +// +void S_ShowMusicCredit(void) +{ + musicdef_t *def = musicdefstart; + + if (!cv_songcredits.value) + return; + + if (!def) // No definitions + return; + + while (def) + { + if (!stricmp(def->name, music_name)) + { + cursongcredit.def = def; + cursongcredit.anim = 5*TICRATE; + cursongcredit.x = 0; + cursongcredit.trans = NUMTRANSMAPS; + return; + } + else + def = def->next; + } +} /// ------------------------ /// Music Status @@ -1731,26 +1809,6 @@ boolean S_SpeedMusic(float speed) return I_SetSongSpeed(speed); } -void S_InitMusicCredit(void) -{ - UINT16 i; - - if (!cv_songcredits.value) - return; - - for (i = 0; songCredits[i].lump; i++) - { - if (!stricmp(songCredits[i].lump, music_name)) - { - cursongcredit.index = i; - cursongcredit.anim = 5*TICRATE; - cursongcredit.x = 0; - cursongcredit.trans = NUMTRANSMAPS; - return; // Don't return when there's SOC support, to see if there's any "replacement" credits? - } - } -} - /// ------------------------ /// Music Playback /// ------------------------ diff --git a/src/s_sound.h b/src/s_sound.h index ae11065c7cc1a2f4bfef3883d0a5e2bd3b945d48..df90ecb12051fd2b6e40b951ffc8db8c9c7d0584 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -129,23 +129,27 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); boolean S_SpeedMusic(float speed); // Music credits +typedef struct musicdef_s +{ + char name[7]; + //char usage[256]; + char source[256]; + struct musicdef_s *next; +} musicdef_t; + extern struct cursongcredit { - UINT16 index; + musicdef_t *def; UINT16 anim; INT32 x; UINT8 trans; } cursongcredit; -typedef struct -{ - const char *lump; - const char *info; -} songcredits_t; - -extern songcredits_t songCredits[]; +extern musicdef_t *musicdefstart; -void S_InitMusicCredit(void); +void S_LoadMusicDefs(UINT16 wadnum); +void S_InitMusicDefs(void); +void S_ShowMusicCredit(void); // // Music Routines diff --git a/src/w_wad.c b/src/w_wad.c index 69b4cb2e7d9a7f965d64f0d6dea8b6fc5407b727..63bee97ded616fdf31b92e4b64c42e4757efd22e 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1738,6 +1738,7 @@ int W_VerifyNMUSlumps(const char *filename) {"MKFNT", 5}, // Kart font changes {"K_", 2}, // Kart graphic changes + {"MUSICDEF", 8}, // Kart song definitions {NULL, 0}, };