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...
This commit is contained in:
toaster 2019-11-05 16:23:46 +00:00
parent 96aa11c825
commit 5f8671b100
16 changed files with 763 additions and 55 deletions

View File

@ -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");

View File

@ -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;

View File

@ -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",

View File

@ -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

View File

@ -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);

View File

@ -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},

View File

@ -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)<<FRACBITS, bpm); -- bake this in on load
work = st_time<<FRACBITS;
work %= bpm;
if (st_time >= (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<<FRACBITS));
ang = (FixedAngle(work)>>ANGLETOFINESHIFT) & FINEMASK;
bounce = (FINESINE(ang) - FRACUNIT/2);
hscale -= bounce/16;
vscale += bounce/16;
st_time++;
}
}
}
x = 90<<FRACBITS;
y = (BASEVIDHEIGHT-32)<<FRACBITS;
V_DrawStretchyFixedPatch(x, y,
hscale, vscale,
0, st_radio[frame[0]], NULL);
V_DrawFixedPatch(x, y, FRACUNIT/2, 0, st_launchpad[0], NULL);
for (i = 0; i < 9; i++)
{
if (i == frame[2])
{
UINT8 *colmap = R_GetTranslationColormap(TC_RAINBOW, frame[3], GTC_CACHE);
V_DrawFixedPatch(x, y + (frame[1]<<FRACBITS), FRACUNIT/2, 0, st_launchpad[frame[1]+1], colmap);
}
else
V_DrawFixedPatch(x, y, FRACUNIT/2, 0, st_launchpad[1], NULL);
if ((i % 3) == 2)
{
x -= ((2*28) + 25)<<(FRACBITS-1);
y -= ((2*7) - 11)<<(FRACBITS-1);
}
else
{
x += 28<<(FRACBITS-1);
y += 7<<(FRACBITS-1);
}
}
y = (BASEVIDWIDTH-(vid.width/vid.dupx))/2;
V_DrawFill(y, 20, vid.width/vid.dupx, 24, 159);
{
static fixed_t st_scroll = -1;
const char* titl;
x = 16;
V_DrawString(x, 10, 0, "NOW PLAYING:");
if (curplaying)
{
if (curplaying->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)<<FRACBITS, (y<<FRACBITS)-(bounce*4), FRACUNIT, 0, hu_font['\x19'-HU_FONTSTART], V_GetStringColormap(V_YELLOWMAP));
}
}
t++;
y += 16;
}
}
}
static void M_HandleSoundTest(INT32 choice)
@ -6958,27 +7233,102 @@ static void M_HandleSoundTest(INT32 choice)
switch (choice)
{
case KEY_DOWNARROW:
M_NextOpt();
S_StartSound(NULL, sfx_menu1);
if (st_sel++ >= 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;
}

View File

@ -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,

View File

@ -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
//

View File

@ -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)<<FRACBITS, 120<<FRACBITS)
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;
}
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)<<FRACBITS, bpmf);
} 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);
}
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
/// ------------------------

View File

@ -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
//

View File

@ -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;
}

View File

@ -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

View File

@ -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<<FRACBITS, pscale);
fdup = vdup = FixedMul(dupx<<FRACBITS, pscale);
if (vscale != pscale)
vdup = FixedMul(dupx<<FRACBITS, vscale);
colfrac = FixedDiv(FRACUNIT, fdup);
rowfrac = FixedDiv(FRACUNIT, fdup);
rowfrac = FixedDiv(FRACUNIT, vdup);
// So it turns out offsets aren't scaled in V_NOSCALESTART unless V_OFFSET is applied ...poo, that's terrible
// For now let's just at least give V_OFFSET the ability to support V_FLIP
@ -637,7 +639,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
// top offset
// TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!?
offsety = FixedMul(SHORT(patch->topoffset)<<FRACBITS, pscale);
offsety = FixedMul(SHORT(patch->topoffset)<<FRACBITS, vscale);
if ((scrn & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs
{
@ -653,13 +655,14 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
if (splitscreen && (scrn & V_PERPLAYER))
{
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
fdup >>= 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,fdup))*vid.width;
dest += FixedInt(FixedMul(topdelta<<FRACBITS,vdup))*vid.width;
for (ofs = 0; dest < deststop && (ofs>>FRACBITS) < column->length; ofs += rowfrac)
{

View File

@ -140,7 +140,8 @@ extern RGBA_t *pMasterPalette;
#define V_DrawSmallTranslucentPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, s, p, NULL)
#define V_DrawTinyTranslucentPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, s, p, NULL)
#define V_DrawSciencePatch(x,y,s,p,sc) V_DrawFixedPatch(x,y,sc,s,p,NULL)
void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
#define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c)
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor);

View File

@ -1888,6 +1888,7 @@ int W_VerifyNMUSlumps(const char *filename)
{"STT", 3}, // Acceptable HUD changes (Score Time Rings)
{"YB_", 3}, // Intermission graphics, goes with the above
{"M_", 2}, // As does menu stuff
{"MUSICDEF", 8}, // Song definitions (thanks kart)
{NULL, 0},
};