From 5f8671b1002eea61c1e7e00a9b91f30d732ce261 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 5 Nov 2019 16:23:46 +0000 Subject: [PATCH] Sound test is cool now! https://cdn.discordapp.com/attachments/405336003239477249/641295998395613224/srb20042.gif * Port MUSICDEFs from Kart. * Safe to modify without modifying game, so we can put it in music.dta eventually. * "Title", "AltTitle", "Authors" fields are self-evident. * "Soundtestpage" and "Soundtestcond" are used to determine which sound test unlockable can play them (set with Unlockable's variable, just like Level Select). * "Stoppingtime" and "BPM" both accept floats, and are used for presentation stuff on the sound test. * Ironically, we don't share a single field name with them. Such is the case of differing foci, though, and I expect they'll change their implementation to match (since this is necessary for a sound test). * Change how S_AddSoundFx works to avoid iterating through all of them, and to allow cv_soundtest to only scroll through defined slots (instead of the infinite wall of thok sounds when scrolling to the left). * Change V_DrawFixedPatch to allow scaling on two seperate axes. * Now called "V_DrawStretchyFixedPatch". * "V_DrawFixedPatch" is a macro to V_DrawStretchyFixedPatch now (same scale on both axes). * Available to Lua under v.drawStretched! * Even works in GL! * Bugfix: Add SR_PLAYER to SOC's menutypes_list. Stay tuned for the merge request, where I put the onus on the Music Team to finish this off... --- src/d_main.c | 1 + src/d_netcmd.c | 5 +- src/dehacked.c | 2 + src/hardware/hw_draw.c | 4 +- src/hardware/hw_main.h | 2 +- src/lua_hudlib.c | 28 +++ src/m_menu.c | 401 ++++++++++++++++++++++++++++++++++++++--- src/m_menu.h | 1 + src/p_setup.c | 5 + src/s_sound.c | 269 +++++++++++++++++++++++++++ src/s_sound.h | 28 +++ src/sounds.c | 48 +++-- src/sounds.h | 1 + src/v_video.c | 19 +- src/v_video.h | 3 +- src/w_wad.c | 1 + 16 files changed, 763 insertions(+), 55 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 52f1d2997..3a6592cb1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1277,6 +1277,7 @@ void D_SRB2Main(void) I_StartupSound(); I_InitMusic(); S_InitSfxChannels(cv_soundvolume.value); + S_InitMusicDefs(); } CONS_Printf("ST_Init(): Init status bar.\n"); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b14f92b33..ba5f7fcaf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3831,13 +3831,14 @@ static void Gravity_OnChange(void) static void SoundTest_OnChange(void) { + INT32 sfxfreeint = (INT32)sfxfree; if (cv_soundtest.value < 0) { - CV_SetValue(&cv_soundtest, NUMSFX-1); + CV_SetValue(&cv_soundtest, sfxfreeint-1); return; } - if (cv_soundtest.value >= NUMSFX) + if (cv_soundtest.value >= sfxfreeint) { CV_SetValue(&cv_soundtest, 0); return; diff --git a/src/dehacked.c b/src/dehacked.c index 34ee1f170..e71c920bd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8590,6 +8590,8 @@ static const char *const MENUTYPES_LIST[] = { "SR_LEVELSELECT", "SR_UNLOCKCHECKLIST", "SR_EMBLEMHINT", + "SR_PLAYER", + "SR_SOUNDTEST", // Addons (Part of MISC, but let's make it our own) "AD_MAIN", diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index d9e688c0a..c95de29ee 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -137,7 +137,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, const UINT8 *colormap) +void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) { FOutVector v[4]; FBITFIELD flags; @@ -182,6 +182,8 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, dupx = dupy = (dupx < dupy ? dupx : dupy); fscalew = fscaleh = FIXED_TO_FLOAT(pscale); + if (vscale != pscale) + fscaleh = FIXED_TO_FLOAT(vscale); // See my comments in v_video.c's V_DrawFixedPatch // -- Monster Iestyn 29/10/18 diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 31e97cc13..bf69cb84f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -42,7 +42,7 @@ void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum) void HWR_InitTextureMapping(void); void HWR_SetViewSize(void); void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, const UINT8 *colormap); +void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 865b61e8f..62be61283 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -551,6 +551,33 @@ static int libd_drawScaled(lua_State *L) return 0; } +static int libd_drawStretched(lua_State *L) +{ + fixed_t x, y, hscale, vscale; + INT32 flags; + patch_t *patch; + const UINT8 *colormap = NULL; + + HUDONLY + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + hscale = luaL_checkinteger(L, 3); + if (hscale < 0) + return luaL_error(L, "negative horizontal scale"); + vscale = luaL_checkinteger(L, 4); + if (vscale < 0) + return luaL_error(L, "negative vertical scale"); + patch = *((patch_t **)luaL_checkudata(L, 5, META_PATCH)); + flags = luaL_optinteger(L, 6, 0); + if (!lua_isnoneornil(L, 7)) + colormap = *((UINT8 **)luaL_checkudata(L, 7, META_COLORMAP)); + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + + V_DrawStretchyFixedPatch(x, y, hscale, vscale, flags, patch, colormap); + return 0; +} + static int libd_drawNum(lua_State *L) { INT32 x, y, flags, num; @@ -902,6 +929,7 @@ static luaL_Reg lib_draw[] = { // drawing {"draw", libd_draw}, {"drawScaled", libd_drawScaled}, + {"drawStretched", libd_drawStretched}, {"drawNum", libd_drawNum}, {"drawPaddedNum", libd_drawPaddedNum}, {"drawFill", libd_drawFill}, diff --git a/src/m_menu.c b/src/m_menu.c index 8fe782cac..3257ee3b6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -228,6 +228,7 @@ static void M_GetAllEmeralds(INT32 choice); static void M_DestroyRobots(INT32 choice); static void M_LevelSelectWarp(INT32 choice); static void M_Credits(INT32 choice); +static void M_SoundTest(INT32 choice); static void M_PandorasBox(INT32 choice); static void M_EmblemHints(INT32 choice); static void M_HandleChecklist(INT32 choice); @@ -336,8 +337,8 @@ static void M_DrawGenericMenu(void); static void M_DrawGenericScrollMenu(void); static void M_DrawCenteredMenu(void); static void M_DrawAddons(void); -static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); +static void M_DrawSoundTest(void); static void M_DrawEmblemHints(void); static void M_DrawPauseMenu(void); static void M_DrawServerMenu(void); @@ -706,6 +707,11 @@ static menuitem_t SR_UnlockChecklistMenu[] = {IT_KEYHANDLER | IT_STRING, NULL, "", M_HandleChecklist, 0}, }; +static menuitem_t SR_SoundTestMenu[] = +{ + {IT_KEYHANDLER | IT_STRING, NULL, "", M_HandleSoundTest, 0}, +}; + static menuitem_t SR_EmblemHintMenu[] = { {IT_STRING|IT_CVAR, NULL, "Emblem Radar", &cv_itemfinder, 10}, @@ -1600,18 +1606,8 @@ menu_t SR_PandoraDef = 0, M_ExitPandorasBox }; -menu_t SR_MainDef = -{ - MN_SR_MAIN, - "M_SECRET", - sizeof (SR_MainMenu)/sizeof (menuitem_t), - &MainDef, - SR_MainMenu, - M_DrawSkyRoom, - 60, 40, - 0, - NULL -}; + +menu_t SR_MainDef = DEFAULTMENUSTYLE(MN_SR_MAIN, "M_SECRET", SR_MainMenu, &MainDef, 60, 40); menu_t SR_LevelSelectDef = MAPPLATTERMENUSTYLE( MN_SR_MAIN + (MN_SR_LEVELSELECT << 6), @@ -1629,6 +1625,20 @@ menu_t SR_UnlockChecklistDef = 0, NULL }; + +menu_t SR_SoundTestDef = +{ + MN_SR_MAIN + (MN_SR_SOUNDTEST << 6), + NULL, + sizeof (SR_SoundTestMenu)/sizeof (menuitem_t), + &SR_MainDef, + SR_SoundTestMenu, + M_DrawSoundTest, + 60, 150, + 0, + NULL +}; + menu_t SR_EmblemHintDef = { MN_SR_MAIN + (MN_SR_EMBLEMHINT << 6), @@ -2309,6 +2319,11 @@ void M_InitMenuPresTables(void) strncpy(menupres[i].musname, "_nitat", 7); else if (i == MN_SP_PLAYER) strncpy(menupres[i].musname, "_chsel", 7); + else if (i == MN_SR_SOUNDTEST) + { + *menupres[i].musname = '\0'; + menupres[i].musstop = true; + } } } @@ -6922,7 +6937,7 @@ static void M_DrawEmblemHints(void) M_DrawGenericMenu(); } -static void M_DrawSkyRoom(void) +/*static void M_DrawSkyRoom(void) { INT32 i, y = 0; @@ -6949,6 +6964,266 @@ static void M_DrawSkyRoom(void) } if (cv_soundtest.value) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y + 8, V_YELLOWMAP, S_sfx[cv_soundtest.value].name); +}*/ + +static musicdef_t *curplaying = NULL; +static INT32 st_sel = 0, st_cc = 0; +static tic_t st_time = 0; +static patch_t* st_radio[9]; +static patch_t* st_launchpad[4]; + +static void M_SoundTest(INT32 choice) +{ + INT32 ul = skyRoomMenuTranslations[choice-1]; + UINT8 i; + char buf[8]; + + soundtestpage = (UINT8)(unlockables[ul].variable); + if (!soundtestpage) + soundtestpage = 1; + + if (!S_PrepareSoundTest()) + { + M_StartMessage(M_GetText("No selectable tracks found.\n"),NULL,MM_NOTHING); + return; + } + + STRBUFCPY(buf, "M_RADIOn"); + for (i = 0; i < 9; i++) + { + if (st_radio[i]) + W_UnlockCachedPatch(st_radio[i]); + buf[7] = (char)('0'+i); + st_radio[i] = W_CachePatchName(buf, PU_STATIC); + } + + STRBUFCPY(buf, "M_LPADn"); + for (i = 0; i < 4; i++) + { + if (st_launchpad[i]) + W_UnlockCachedPatch(st_launchpad[i]); + buf[6] = (char)('0'+i); + st_launchpad[i] = W_CachePatchName(buf, PU_STATIC); + } + + curplaying = NULL; + st_time = 0; + + st_sel = 0; + + st_cc = cv_closedcaptioning.value; // hack; + cv_closedcaptioning.value = 1; // hack + + M_SetupNextMenu(&SR_SoundTestDef); +} + +static void M_DrawSoundTest(void) +{ + INT32 x, y, i; + fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0; + UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY}; + + // let's handle the ticker first. ideally we'd tick this somewhere else, BUT... + if (curplaying) + { + if (curplaying == &soundtestsfx) + { + if (cv_soundtest.value) + { + frame[1] = (2-st_time); + frame[2] = ((cv_soundtest.value - 1) % 9); + frame[3] += (((cv_soundtest.value - 1) / 9) % (MAXSKINCOLORS - frame[3])); + if (st_time < 2) + st_time++; + } + } + else + { + if (curplaying->stoppingtics && st_time >= curplaying->stoppingtics) + { + curplaying = NULL; + st_time = 0; + } + else + { + fixed_t work, bpm = curplaying->bpm; + angle_t ang; + //bpm = FixedDiv((60*TICRATE)<= (FRACUNIT>>1)) // prevent overflow jump - takes about 15 minutes of loop on the same song to reach + st_time = (work>>FRACBITS); + + work = FixedDiv(work*180, bpm); + frame[0] = 8-(work/(20<>ANGLETOFINESHIFT) & FINEMASK; + bounce = (FINESINE(ang) - FRACUNIT/2); + hscale -= bounce/16; + vscale += bounce/16; + + st_time++; + } + } + } + + x = 90<alttitle[0]) + titl = va("%s - %s - ", curplaying->title, curplaying->alttitle); + else + titl = va("%s - ", curplaying->title); + } + else + titl = "NONE - "; + + i = V_LevelNameWidth(titl); + + if (++st_scroll >= i) + st_scroll %= i; + + x -= st_scroll; + + while (x < BASEVIDWIDTH-y) + x += i; + while (x > y) + { + x -= i; + V_DrawLevelTitle(x, 24, 0, titl); + } + + if (curplaying) + V_DrawRightAlignedString(BASEVIDWIDTH-16, 46, V_ALLOWLOWERCASE, curplaying->authors); + } + + V_DrawFill(165, 60, 140, 112, 159); + + { + INT32 t, b, q, m = 112; + + if (numsoundtestdefs <= 7) + { + t = 0; + b = numsoundtestdefs - 1; + i = 0; + } + else + { + q = m; + m = (5*m)/numsoundtestdefs; + if (st_sel < 3) + { + t = 0; + b = 6; + i = 0; + } + else if (st_sel >= numsoundtestdefs-4) + { + t = numsoundtestdefs - 7; + b = numsoundtestdefs - 1; + i = q-m; + } + else + { + t = st_sel - 3; + b = st_sel + 3; + i = (t * (q-m))/(numsoundtestdefs - 7); + } + } + + V_DrawFill(165+140-1, 60 + i, 1, m, 0); + + if (t != 0) + V_DrawString(165+140+4, 60+4 - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); + + if (b != numsoundtestdefs - 1) + V_DrawString(165+140+4, 60+112-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); + + x = 169; + y = 64; + + while (t <= b) + { + if (t == st_sel) + V_DrawFill(165, y-4, 140-1, 16, 155); + if (!soundtestdefs[t]->allowed) + { + V_DrawString(x, y, (t == st_sel ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, "???"); + } + else if (soundtestdefs[t] == &soundtestsfx) + { + const char *sfxstr = va("SFX %s", cv_soundtest.string); + V_DrawString(x, y, (t == st_sel ? V_YELLOWMAP : 0), sfxstr); + if (t == st_sel) + { + V_DrawCharacter(x - 10 - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(x + 2 + V_StringWidth(sfxstr, 0) + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } + + if (curplaying == soundtestdefs[t]) + { + sfxstr = (cv_soundtest.value) ? S_sfx[cv_soundtest.value].name : "N/A"; + i = V_StringWidth(sfxstr, 0); + V_DrawFill(165+140-9-i, y-4, i+8, 16, 150); + V_DrawRightAlignedString(165+140-5, y, V_YELLOWMAP, sfxstr); + } + } + else + { + V_DrawString(x, y, (t == st_sel ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, soundtestdefs[t]->title); + if (curplaying == soundtestdefs[t]) + { + V_DrawFill(165+140-9, y-4, 8, 16, 150); + //V_DrawCharacter(165+140-8, y, '\x19' | V_YELLOWMAP, false); + V_DrawFixedPatch((165+140-9)<= numsoundtestdefs-1) + st_sel = 0; + { + cv_closedcaptioning.value = st_cc; // hack + S_StartSound(NULL, sfx_menu1); + cv_closedcaptioning.value = 1; // hack + } break; case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL, sfx_menu1); + if (!st_sel--) + st_sel = numsoundtestdefs-1; + { + cv_closedcaptioning.value = st_cc; // hack + S_StartSound(NULL, sfx_menu1); + cv_closedcaptioning.value = 1; // hack + } + break; + case KEY_PGDN: + if (st_sel < numsoundtestdefs-1) + { + st_sel += 3; + if (st_sel >= numsoundtestdefs-1) + st_sel = numsoundtestdefs-1; + cv_closedcaptioning.value = st_cc; // hack + S_StartSound(NULL, sfx_menu1); + cv_closedcaptioning.value = 1; // hack + } + break; + case KEY_PGUP: + if (st_sel) + { + st_sel -= 3; + if (st_sel < 0) + st_sel = 0; + cv_closedcaptioning.value = st_cc; // hack + S_StartSound(NULL, sfx_menu1); + cv_closedcaptioning.value = 1; // hack + } break; case KEY_BACKSPACE: + if (curplaying) + { + S_StopSounds(); + S_StopMusic(); + curplaying = NULL; + st_time = 0; + cv_closedcaptioning.value = st_cc; // hack + S_StartSound(NULL, sfx_skid); + cv_closedcaptioning.value = 1; // hack + } + break; case KEY_ESCAPE: exitmenu = true; break; case KEY_RIGHTARROW: - CV_AddValue(&cv_soundtest, 1); + if (soundtestdefs[st_sel] == &soundtestsfx && soundtestdefs[st_sel]->allowed) + { + S_StopSounds(); + S_StopMusic(); + curplaying = soundtestdefs[st_sel]; + st_time = 0; + CV_AddValue(&cv_soundtest, 1); + } break; case KEY_LEFTARROW: - CV_AddValue(&cv_soundtest, -1); + if (soundtestdefs[st_sel] == &soundtestsfx && soundtestdefs[st_sel]->allowed) + { + S_StopSounds(); + S_StopMusic(); + curplaying = soundtestdefs[st_sel]; + st_time = 0; + CV_AddValue(&cv_soundtest, -1); + } break; case KEY_ENTER: S_StopSounds(); - S_StartSound(NULL, cv_soundtest.value); + S_StopMusic(); + st_time = 0; + if (soundtestdefs[st_sel]->allowed) + { + curplaying = soundtestdefs[st_sel]; + if (curplaying == &soundtestsfx) + { + // S_StopMusic() -- is this necessary? + if (cv_soundtest.value) + S_StartSound(NULL, cv_soundtest.value); + } + else + S_ChangeMusicInternal(curplaying->name, !curplaying->stoppingtics); + } + else + { + curplaying = NULL; + S_StartSound(NULL, sfx_lose); + } break; default: @@ -6986,6 +7336,11 @@ static void M_HandleSoundTest(INT32 choice) } if (exitmenu) { + Z_Free(soundtestdefs); + soundtestdefs = NULL; + + cv_closedcaptioning.value = st_cc; // undo hack + if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else @@ -7060,8 +7415,8 @@ static void M_SecretsMenu(INT32 choice) SR_MainMenu[i].itemaction = M_Credits; break; case SECRET_SOUNDTEST: - SR_MainMenu[i].status = IT_STRING|IT_KEYHANDLER; - SR_MainMenu[i].itemaction = M_HandleSoundTest; + SR_MainMenu[i].status = IT_STRING|IT_CALL; + SR_MainMenu[i].itemaction = M_SoundTest; default: break; } diff --git a/src/m_menu.h b/src/m_menu.h index 3bfa48597..afcad3577 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -105,6 +105,7 @@ typedef enum MN_SR_UNLOCKCHECKLIST, MN_SR_EMBLEMHINT, MN_SR_PLAYER, + MN_SR_SOUNDTEST, // Addons (Part of MISC, but let's make it our own) MN_AD_MAIN, diff --git a/src/p_setup.c b/src/p_setup.c index cef176636..2983bccda 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3447,6 +3447,11 @@ boolean P_AddWadFile(const char *wadfilename) R_PatchSkins(wadnum); // toast: PATCH PATCH ST_ReloadSkinFaceGraphics(); + // + // edit music defs + // + S_LoadMusicDefs(wadnum); + // // search for maps // diff --git a/src/s_sound.c b/src/s_sound.c index 6134e338c..323921c19 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -38,6 +38,7 @@ extern INT32 msg_id; #include "p_local.h" // camera info #include "fastcmp.h" #include "m_misc.h" // for tunes command +#include "m_cond.h" // for conditionsets #if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) #include "lua_hook.h" // MusicChange hook @@ -1423,6 +1424,274 @@ static UINT32 queue_fadeinms; static tic_t pause_starttic; +/// ------------------------ +/// Music Definitions +/// ------------------------ + +musicdef_t soundtestsfx = { + "_STSFX", // prevents exactly one valid track name from being used on the sound test + "Sound Effects", + "", + "SEGA, Sonic Team Jr, other sources", + 1, // show on soundtest page 1 + 0, // with no conditions + 0, + 0, + false, + NULL +}; + +musicdef_t *musicdefstart = &soundtestsfx; + +// +// 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; + INT32 i; + musicdef_t *def = NULL; + 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'; + + 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*/ + { + musicdef_t *prev = NULL; + 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); + def->bpm = TICRATE<<(FRACBITS-1); // FixedDiv((60*TICRATE)<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; + } + + i = atoi(value); + + 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")) { +#if 0 // Ignore for now + 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->usage); +#endif + } else if (!stricmp(stoken, "title")) { + STRBUFCPY(def->title, value); + for (value = def->title; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + //CONS_Printf("S_LoadMusicDefs: Set title to '%s'\n", def->source); + } else if (!stricmp(stoken, "alttitle")) { + STRBUFCPY(def->alttitle, value); + for (value = def->alttitle; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + //CONS_Printf("S_LoadMusicDefs: Set alttitle to '%s'\n", def->source); + } else if (!stricmp(stoken, "authors")) { + STRBUFCPY(def->authors, value); + for (value = def->authors; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + //CONS_Printf("S_LoadMusicDefs: Set authors to '%s'\n", def->source); + } else if (!stricmp(stoken, "soundtestpage")) { + def->soundtestpage = (UINT8)i; + } else if (!stricmp(stoken, "soundtestcond")) { + // Convert to map number + if (value[0] >= 'A' && value[0] <= 'Z' && value[2] == '\0') + i = M_MapNumber(value[0], value[1]); + def->soundtestcond = (INT16)i; + } else if (!stricmp(stoken, "stoppingtime")) { + double stoppingtime = atof(value)*TICRATE; + def->stoppingtics = (tic_t)stoppingtime; + } else if (!stricmp(stoken, "bpm")) { + double bpm = atof(value); + fixed_t bpmf = FLOAT_TO_FIXED(bpm); + if (bpmf > 0) + def->bpm = FixedDiv((60*TICRATE)<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); +} + +musicdef_t **soundtestdefs = NULL; +INT32 numsoundtestdefs = 0; +UINT8 soundtestpage = 1; + +// +// S_PrepareSoundTest +// +// Prepare sound test. What am I, your butler? +// +boolean S_PrepareSoundTest(void) +{ + musicdef_t *def; + INT32 pos = numsoundtestdefs = 0; + + for (def = musicdefstart; def; def = def->next) + { + if (!(def->soundtestpage & soundtestpage)) + continue; + def->allowed = false; + numsoundtestdefs++; + } + + if (!numsoundtestdefs) + return false; + + if (soundtestdefs) + Z_Free(soundtestdefs); + + if (!(soundtestdefs = Z_Malloc(numsoundtestdefs*sizeof(musicdef_t *), PU_STATIC, NULL))) + I_Error("S_PrepareSoundTest(): could not allocate soundtestdefs."); + + for (def = musicdefstart; def /*&& i < numsoundtestdefs*/; def = def->next) + { + if (!(def->soundtestpage & soundtestpage)) + continue; + soundtestdefs[pos++] = def; + if (def->soundtestcond > 0 && !(mapvisited[def->soundtestcond-1] & MV_BEATEN)) + continue; + if (def->soundtestcond < 0 && !M_Achieved(1-def->soundtestcond)) + continue; + def->allowed = true; + } + + return true; +} + + /// ------------------------ /// Music Status /// ------------------------ diff --git a/src/s_sound.h b/src/s_sound.h index 20b2489a5..6551d8020 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -188,6 +188,34 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); // Set Speed of Music boolean S_SpeedMusic(float speed); +// Music credits +typedef struct musicdef_s +{ + char name[7]; + char title[32]; + char alttitle[64]; + //char usage[256]; -- probably never going to be relevant to vanilla but was in kart's struct + //char source[256]; -- ditto + char authors[256]; + UINT8 soundtestpage; + INT16 soundtestcond; // +ve for map, -ve for conditionset, 0 for already here + tic_t stoppingtics; + fixed_t bpm; + boolean allowed; // question marks or listenable on sound test? + struct musicdef_s *next; +} musicdef_t; + +extern musicdef_t soundtestsfx; +extern musicdef_t *musicdefstart; +extern musicdef_t **soundtestdefs; +extern INT32 numsoundtestdefs; +extern UINT8 soundtestpage; + +void S_LoadMusicDefs(UINT16 wadnum); +void S_InitMusicDefs(void); + +boolean S_PrepareSoundTest(void); + // // Music Seeking // diff --git a/src/sounds.c b/src/sounds.c index 8dc97b1e6..bcd332fdf 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -857,35 +857,45 @@ void S_InitRuntimeSounds (void) } } +sfxenum_t sfxfree = sfx_freeslot0; + // Add a new sound fx into a free sfx slot. // sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound) { - sfxenum_t i, slot; + sfxenum_t i; if (skinsound) - slot = sfx_skinsoundslot0; - else - slot = sfx_freeslot0; - - for (i = slot; i < NUMSFX; i++) { - if (!S_sfx[i].priority) + for (i = sfx_skinsoundslot0; i < NUMSFX; i++) { - strncpy(freeslotnames[i-sfx_freeslot0], name, 6); - S_sfx[i].singularity = singular; - S_sfx[i].priority = 60; - S_sfx[i].pitch = flags; - S_sfx[i].volume = -1; - S_sfx[i].lumpnum = LUMPERROR; - S_sfx[i].skinsound = -1; - S_sfx[i].usefulness = -1; - - /// \todo if precached load it here - S_sfx[i].data = NULL; - return i; + if (S_sfx[i].priority) + continue; + break; } } + else + i = sfxfree; + + if (i < NUMSFX) + { + strncpy(freeslotnames[i-sfx_freeslot0], name, 6); + S_sfx[i].singularity = singular; + S_sfx[i].priority = 60; + S_sfx[i].pitch = flags; + S_sfx[i].volume = -1; + S_sfx[i].lumpnum = LUMPERROR; + S_sfx[i].skinsound = -1; + S_sfx[i].usefulness = -1; + + /// \todo if precached load it here + S_sfx[i].data = NULL; + + if (!skinsound) + sfxfree++; + + return i; + } CONS_Alert(CONS_WARNING, M_GetText("No more free sound slots\n")); return 0; } diff --git a/src/sounds.h b/src/sounds.h index 9f6e0bab6..d48deb540 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -879,6 +879,7 @@ typedef enum void S_InitRuntimeSounds(void); sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound); +extern sfxenum_t sfxfree; // sound test and slotting void S_RemoveSoundFx(sfxenum_t id); #endif diff --git a/src/v_video.c b/src/v_video.c index 34d64cb04..c108f51c8 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -541,12 +541,12 @@ static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fix } // Draws a patch scaled to arbitrary size. -void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) +void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) { UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); UINT32 alphalevel = 0; - fixed_t col, ofs, colfrac, rowfrac, fdup; + fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dupx, dupy; const column_t *column; UINT8 *desttop, *dest, *deststart, *destend; @@ -563,7 +563,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t //if (rendermode != render_soft && !con_startup) // Why? if (rendermode != render_soft) { - HWR_DrawFixedPatch((GLPatch_t *)patch, x, y, pscale, scrn, colormap); + HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap); return; } #endif @@ -618,9 +618,11 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t // only use one dup, to avoid stretching (har har) dupx = dupy = (dupx < dupy ? dupx : dupy); - fdup = FixedMul(dupx<topoffset)<topoffset)<>= 1; + vdup >>= 1; rowfrac <<= 1; y >>= 1; #ifdef QUADS if (splitscreen > 1) // 3 or 4 players { fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1)); + fdup >>= 1; colfrac <<= 1; x >>= 1; if (stplyr == &players[displayplayer]) @@ -825,7 +828,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t dest = desttop; if (scrn & V_FLIP) dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) { diff --git a/src/v_video.h b/src/v_video.h index 01d50cd57..cd32ac5f8 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -140,7 +140,8 @@ extern RGBA_t *pMasterPalette; #define V_DrawSmallTranslucentPatch(x,y,s,p) V_DrawFixedPatch((x)<