Now diablo.h is treated in the same way as all other header files of Source, as it only contains the declarations of global variables and functions of diablo.cpp. Besides consistency, this also enables mods to include diablo.h just like any other header file without having to include every header file (and without having to include C++ specific aspects of the now all.h).
408 lines
8.7 KiB
C++
408 lines
8.7 KiB
C++
#include "all.h"
|
|
|
|
BYTE *optbar_cel;
|
|
BOOLEAN mouseNavigation;
|
|
BYTE *PentSpin_cel;
|
|
TMenuItem *sgpCurrItem;
|
|
BYTE *BigTGold_cel;
|
|
int PentSpin_tick;
|
|
BYTE PentSpin_frame;
|
|
void (*dword_63447C)(TMenuItem *);
|
|
TMenuItem *sgpCurrentMenu;
|
|
BYTE *option_cel;
|
|
BYTE *sgpLogo;
|
|
int sgCurrentMenuIdx;
|
|
|
|
const BYTE lfontframe[127] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 37, 49, 38, 0, 39, 40, 47,
|
|
42, 43, 41, 45, 52, 44, 53, 55, 36, 27,
|
|
28, 29, 30, 31, 32, 33, 34, 35, 51, 50,
|
|
0, 46, 0, 54, 0, 1, 2, 3, 4, 5,
|
|
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
|
|
26, 42, 0, 43, 0, 0, 0, 1, 2, 3,
|
|
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
|
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
|
24, 25, 26, 20, 0, 21, 0
|
|
};
|
|
const BYTE lfontkern[56] = {
|
|
18, 33, 21, 26, 28, 19, 19, 26, 25, 11,
|
|
12, 25, 19, 34, 28, 32, 20, 32, 28, 20,
|
|
28, 36, 35, 46, 33, 33, 24, 11, 23, 22,
|
|
22, 21, 22, 21, 21, 21, 32, 10, 20, 36,
|
|
31, 17, 13, 12, 13, 18, 16, 11, 20, 21,
|
|
11, 10, 12, 11, 21, 23
|
|
};
|
|
|
|
void gmenu_draw_pause()
|
|
{
|
|
if (currlevel != 0)
|
|
RedBack();
|
|
if (!sgpCurrentMenu) {
|
|
light_table_index = 0;
|
|
gmenu_print_text(316 + PANEL_LEFT, 336, "Pause");
|
|
}
|
|
}
|
|
|
|
void gmenu_print_text(int x, int y, char *pszStr)
|
|
{
|
|
BYTE c;
|
|
|
|
while (*pszStr) {
|
|
c = gbFontTransTbl[(BYTE)*pszStr++];
|
|
c = lfontframe[c];
|
|
if (c)
|
|
CelDrawLight(x, y, BigTGold_cel, c, 46);
|
|
x += lfontkern[c] + 2;
|
|
}
|
|
}
|
|
|
|
void FreeGMenu()
|
|
{
|
|
MemFreeDbg(sgpLogo);
|
|
MemFreeDbg(BigTGold_cel);
|
|
MemFreeDbg(PentSpin_cel);
|
|
MemFreeDbg(option_cel);
|
|
MemFreeDbg(optbar_cel);
|
|
}
|
|
|
|
void gmenu_init_menu()
|
|
{
|
|
PentSpin_frame = 1;
|
|
sgpCurrentMenu = 0;
|
|
sgpCurrItem = 0;
|
|
dword_63447C = 0;
|
|
sgCurrentMenuIdx = 0;
|
|
mouseNavigation = FALSE;
|
|
sgpLogo = LoadFileInMem("Data\\Diabsmal.CEL", NULL);
|
|
BigTGold_cel = LoadFileInMem("Data\\BigTGold.CEL", NULL);
|
|
PentSpin_cel = LoadFileInMem("Data\\PentSpin.CEL", NULL);
|
|
option_cel = LoadFileInMem("Data\\option.CEL", NULL);
|
|
optbar_cel = LoadFileInMem("Data\\optbar.CEL", NULL);
|
|
}
|
|
|
|
BOOL gmenu_exception()
|
|
{
|
|
return sgpCurrentMenu != 0;
|
|
}
|
|
|
|
void gmenu_call_proc(TMenuItem *pItem, void (*gmFunc)(TMenuItem *))
|
|
{
|
|
int i;
|
|
|
|
PauseMode = 0;
|
|
mouseNavigation = FALSE;
|
|
sgpCurrentMenu = pItem;
|
|
dword_63447C = gmFunc;
|
|
if (gmFunc) {
|
|
dword_63447C(sgpCurrentMenu);
|
|
pItem = sgpCurrentMenu;
|
|
}
|
|
sgCurrentMenuIdx = 0;
|
|
if (sgpCurrentMenu) {
|
|
for (i = 0; sgpCurrentMenu[i].fnMenu; i++) {
|
|
sgCurrentMenuIdx++;
|
|
}
|
|
}
|
|
// BUGFIX: OOB access when sgCurrentMenuIdx is 0; should be set to NULL instead.
|
|
sgpCurrItem = &sgpCurrentMenu[sgCurrentMenuIdx - 1];
|
|
gmenu_up_down(TRUE);
|
|
}
|
|
|
|
void gmenu_up_down(BOOL isDown)
|
|
{
|
|
int i;
|
|
|
|
if (!sgpCurrItem) {
|
|
return;
|
|
}
|
|
mouseNavigation = FALSE;
|
|
i = sgCurrentMenuIdx;
|
|
if (sgCurrentMenuIdx) {
|
|
while (i) {
|
|
i--;
|
|
if (isDown) {
|
|
sgpCurrItem++;
|
|
if (!sgpCurrItem->fnMenu)
|
|
sgpCurrItem = &sgpCurrentMenu[0];
|
|
} else {
|
|
if (sgpCurrItem == sgpCurrentMenu)
|
|
sgpCurrItem = &sgpCurrentMenu[sgCurrentMenuIdx];
|
|
sgpCurrItem--;
|
|
}
|
|
if ((sgpCurrItem->dwFlags & GMENU_ENABLED) != 0) {
|
|
if (i)
|
|
PlaySFX(IS_TITLEMOV);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gmenu_draw()
|
|
{
|
|
int y;
|
|
TMenuItem *i;
|
|
DWORD ticks;
|
|
|
|
if (sgpCurrentMenu) {
|
|
if (dword_63447C)
|
|
dword_63447C(sgpCurrentMenu);
|
|
CelDraw((SCREEN_WIDTH - 296) / 2 + SCREEN_X, 102 + SCREEN_Y, sgpLogo, 1, 296);
|
|
y = 160 + SCREEN_Y;
|
|
i = sgpCurrentMenu;
|
|
if (sgpCurrentMenu->fnMenu) {
|
|
while (i->fnMenu) {
|
|
gmenu_draw_menu_item(i, y);
|
|
i++;
|
|
y += 45;
|
|
}
|
|
}
|
|
|
|
ticks = GetTickCount();
|
|
if ((int)(ticks - PentSpin_tick) > 25) { // BUGFIX: thould be 50ms
|
|
PentSpin_frame++;
|
|
if (PentSpin_frame == 9)
|
|
PentSpin_frame = 1;
|
|
PentSpin_tick = ticks;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gmenu_draw_menu_item(TMenuItem *pItem, int y)
|
|
{
|
|
DWORD w, x, nSteps, step, pos, t;
|
|
t = y - 2;
|
|
w = gmenu_get_lfont(pItem);
|
|
if (pItem->dwFlags & GMENU_SLIDER) {
|
|
x = 16 + w / 2 + SCREEN_X;
|
|
CelDraw(x + PANEL_LEFT, t - 8, optbar_cel, 1, 287);
|
|
step = pItem->dwFlags & 0xFFF;
|
|
nSteps = (pItem->dwFlags & 0xFFF000) >> 12;
|
|
if (nSteps < 2)
|
|
nSteps = 2;
|
|
pos = step * 256 / nSteps;
|
|
gmenu_clear_buffer(x + 2 + PANEL_LEFT, t - 10, pos + 13, 28);
|
|
CelDraw(x + 2 + pos + PANEL_LEFT, y - 12, option_cel, 1, 27);
|
|
}
|
|
x = SCREEN_WIDTH / 2 - w / 2 + SCREEN_X;
|
|
light_table_index = (pItem->dwFlags & GMENU_ENABLED) ? 0 : 15;
|
|
gmenu_print_text(x, y, pItem->pszStr);
|
|
if (pItem == sgpCurrItem) {
|
|
CelDraw(x - 54, y + 1, PentSpin_cel, PentSpin_frame, 48);
|
|
CelDraw(x + 4 + w, y + 1, PentSpin_cel, PentSpin_frame, 48);
|
|
}
|
|
}
|
|
|
|
void gmenu_clear_buffer(int x, int y, int width, int height)
|
|
{
|
|
BYTE *i;
|
|
|
|
i = gpBuffer + PitchTbl[y] + x;
|
|
while (height--) {
|
|
memset(i, 205, width);
|
|
i -= BUFFER_WIDTH;
|
|
}
|
|
}
|
|
|
|
int gmenu_get_lfont(TMenuItem *pItem)
|
|
{
|
|
char *text;
|
|
int i;
|
|
BYTE c;
|
|
|
|
if (pItem->dwFlags & GMENU_SLIDER)
|
|
return 490;
|
|
text = pItem->pszStr;
|
|
i = 0;
|
|
while (*text) {
|
|
c = gbFontTransTbl[(BYTE)*text++];
|
|
i += lfontkern[lfontframe[c]] + 2;
|
|
}
|
|
return i - 2;
|
|
}
|
|
|
|
BOOL gmenu_presskeys(int vkey)
|
|
{
|
|
if (!sgpCurrentMenu)
|
|
return FALSE;
|
|
switch (vkey) {
|
|
case VK_RETURN:
|
|
if ((sgpCurrItem->dwFlags & GMENU_ENABLED) != 0) {
|
|
PlaySFX(IS_TITLEMOV);
|
|
sgpCurrItem->fnMenu(TRUE);
|
|
}
|
|
break;
|
|
case VK_ESCAPE:
|
|
PlaySFX(IS_TITLEMOV);
|
|
gmenu_call_proc(0, 0);
|
|
break;
|
|
case VK_SPACE:
|
|
return FALSE;
|
|
case VK_LEFT:
|
|
gmenu_left_right(FALSE);
|
|
break;
|
|
case VK_RIGHT:
|
|
gmenu_left_right(TRUE);
|
|
break;
|
|
case VK_UP:
|
|
gmenu_up_down(FALSE);
|
|
break;
|
|
case VK_DOWN:
|
|
gmenu_up_down(TRUE);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void gmenu_left_right(BOOL isRight)
|
|
{
|
|
int step;
|
|
|
|
if (sgpCurrItem->dwFlags & GMENU_SLIDER) {
|
|
step = sgpCurrItem->dwFlags & 0xFFF;
|
|
if (isRight) {
|
|
if (step == (int)(sgpCurrItem->dwFlags & 0xFFF000) >> 12)
|
|
return;
|
|
step++;
|
|
} else {
|
|
if (!step)
|
|
return;
|
|
step--;
|
|
}
|
|
sgpCurrItem->dwFlags &= 0xFFFFF000;
|
|
sgpCurrItem->dwFlags |= step;
|
|
sgpCurrItem->fnMenu(FALSE);
|
|
}
|
|
}
|
|
|
|
BOOL gmenu_on_mouse_move()
|
|
{
|
|
int step, nSteps;
|
|
|
|
if (!mouseNavigation)
|
|
return FALSE;
|
|
gmenu_valid_mouse_pos(&step);
|
|
nSteps = (int)(sgpCurrItem->dwFlags & 0xFFF000) >> 12;
|
|
step *= nSteps;
|
|
step /= 256;
|
|
|
|
sgpCurrItem->dwFlags &= 0xFFFFF000;
|
|
sgpCurrItem->dwFlags |= step;
|
|
sgpCurrItem->fnMenu(FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN gmenu_valid_mouse_pos(int *plOffset)
|
|
{
|
|
*plOffset = 282;
|
|
if (MouseX < 282 + PANEL_LEFT) {
|
|
*plOffset = 0;
|
|
return FALSE;
|
|
}
|
|
if (MouseX > 538 + PANEL_LEFT) {
|
|
*plOffset = 256;
|
|
return FALSE;
|
|
}
|
|
*plOffset = MouseX - 282 - PANEL_LEFT;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL gmenu_left_mouse(BOOL isDown)
|
|
{
|
|
TMenuItem *pItem;
|
|
DWORD i, w;
|
|
int dummy;
|
|
|
|
if (!isDown) {
|
|
if (mouseNavigation) {
|
|
mouseNavigation = FALSE;
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (!sgpCurrentMenu) {
|
|
return FALSE;
|
|
}
|
|
if (MouseY >= PANEL_TOP) {
|
|
return FALSE;
|
|
}
|
|
if (MouseY - 117 < 0) {
|
|
return TRUE;
|
|
}
|
|
i = (MouseY - 117) / 45;
|
|
if (i >= sgCurrentMenuIdx) {
|
|
return TRUE;
|
|
}
|
|
pItem = &sgpCurrentMenu[i];
|
|
if (!(sgpCurrentMenu[i].dwFlags & GMENU_ENABLED)) {
|
|
return TRUE;
|
|
}
|
|
w = gmenu_get_lfont(pItem);
|
|
if (MouseX < SCREEN_WIDTH / 2 - w / 2) {
|
|
return TRUE;
|
|
}
|
|
if (MouseX > SCREEN_WIDTH / 2 + w / 2) {
|
|
return TRUE;
|
|
}
|
|
sgpCurrItem = pItem;
|
|
PlaySFX(IS_TITLEMOV);
|
|
if (pItem->dwFlags & GMENU_SLIDER) {
|
|
mouseNavigation = gmenu_valid_mouse_pos(&dummy);
|
|
gmenu_on_mouse_move();
|
|
} else {
|
|
sgpCurrItem->fnMenu(TRUE);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void gmenu_enable(TMenuItem *pMenuItem, BOOL enable)
|
|
{
|
|
if (enable)
|
|
pMenuItem->dwFlags |= GMENU_ENABLED;
|
|
else
|
|
pMenuItem->dwFlags &= ~GMENU_ENABLED;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the TMenuItem slider position based on the given value
|
|
*/
|
|
void gmenu_slider_set(TMenuItem *pItem, int min, int max, int value)
|
|
{
|
|
int nSteps;
|
|
|
|
/// ASSERT: assertassert(pItem, "gmenu.cpp", 445);
|
|
nSteps = (int)(pItem->dwFlags & 0xFFF000) >> 12;
|
|
if (nSteps < 2)
|
|
nSteps = 2;
|
|
pItem->dwFlags &= 0xFFFFF000;
|
|
pItem->dwFlags |= ((max - min - 1) / 2 + (value - min) * nSteps) / (max - min);
|
|
}
|
|
|
|
/**
|
|
* @brief Get the current value for the slider
|
|
*/
|
|
int gmenu_slider_get(TMenuItem *pItem, int min, int max)
|
|
{
|
|
int nSteps, step;
|
|
|
|
step = pItem->dwFlags & 0xFFF;
|
|
nSteps = (int)(pItem->dwFlags & 0xFFF000) >> 12;
|
|
if (nSteps < 2)
|
|
nSteps = 2;
|
|
return min + (step * (max - min) + (nSteps - 1) / 2) / nSteps;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the number of steps for the slider
|
|
*/
|
|
void gmenu_slider_steps(TMenuItem *pItem, int steps)
|
|
{
|
|
pItem->dwFlags &= 0xFF000FFF;
|
|
pItem->dwFlags |= (steps << 12) & 0xFFF000;
|
|
}
|