Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/boflib/error.h"
#include "bagel/boflib/misc.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
/*
THE PICTURE OF DORIAN GRAY
4,13,19,6,5,22,20,11,12,21,15,18,14,7,9,8,16,17,1,2,10,3
THE PICTURE OF DORIAN GRAY
4,13,19,6,5,22,20,11,12,21,15,18,14,7,9,8,16,17,1,2,10,3
*/
#define MAX_PLENGTH 25
#define MAX_PLENGTH_S 30
typedef struct {
CHAR text[MAX_PLENGTH_S + 1];
UBYTE order[MAX_PLENGTH];
} PHRASES;
INT StrLenNoSpaces(const CHAR *);
ERROR_CODE ValidatePhrase(PHRASES *);
PHRASES curPhrase;
void main(int argc, char *argv[]) {
char *p, buf[256];
FILE *infile, *outfile;
int i, n;
if (argc > 1) {
if ((infile = fopen(argv[1], "ra")) != NULL) {
printf("\nConverting %s...", argv[1]);
if ((outfile = fopen("OUT.DAT", "wb")) != NULL) {
while (!feof(infile)) {
fgets(buf, 255, infile);
StrReplaceChar(buf, '\n', '\0');
StrReplaceChar(buf, '\r', '\0');
printf("\nFound: (%s)\n", buf);
n = strlen(buf);
if (n > MAX_PLENGTH_S || n <= 3)
printf("\nPhrase: (%s) is not valid. Skipping...\n", buf);
else {
memset(&curPhrase, 0, sizeof(PHRASES));
strcpy(curPhrase.text, buf);
fgets(buf, 255, infile);
StrReplaceChar(buf, '\n', '\0');
n = StrLenNoSpaces(curPhrase.text);
p = buf;
StrReplaceChar(p, ',', '\0');
for (i = 0; i < n; i++) {
curPhrase.order[i] = atoi(p);
printf("%d ", curPhrase.order[i]);
while (*p++ != '\0')
;
}
ValidatePhrase(&curPhrase);
fwrite(&curPhrase, sizeof(PHRASES), 1, outfile);
}
}
fclose(outfile);
} else {
printf("\nCould not open OUT.DAT");
}
fclose(infile);
} else {
printf("\nCould not open %s", argv[1]);
}
}
}
INT StrLenNoSpaces(const CHAR *str) {
INT len;
len = 0;
while (*str) {
if (*str++ != ' ') {
len++;
}
}
return (len);
}
ERROR_CODE ValidatePhrase(PHRASES *phrase) {
bool bList[MAX_PLENGTH];
INT i, n, order;
CHAR c;
ERROR_CODE errCode;
assert(phrase != NULL);
ErrorLog("DEBUG.LOG", "Validating %s", phrase->text);
/* set all entries to FALSE */
memset(bList, 0, sizeof(bool)*MAX_PLENGTH);
/* assume no error */
errCode = ERR_NONE;
if ((n = strlen(phrase->text)) > MAX_PLENGTH_S) {
ErrorLog("DEBUG.LOG", "Phrase too Long: strlen(%s)=%d > %d", phrase->text, n, MAX_PLENGTH_S);
errCode = ERR_FTYPE;
} else {
for (i = 0; i < n; i++) {
c = phrase->text[i];
/*
* verify that all characters in this phrase are valid.
* valid chars are are '\0', ' ' or a letter
*/
if ((c != 0) && (c != 32) && !isalpha(c)) {
ErrorLog("DEBUG.LOG", "Invalid Char in (%s) %c", phrase->text, c);
errCode = ERR_FTYPE;
break;
}
}
/*
* continues as long as there was no error
*/
if (errCode == ERR_NONE) {
if ((n = StrLenNoSpaces(phrase->text)) > MAX_PLENGTH) {
ErrorLog("DEBUG.LOG", "StrLenNoSpace(%s)=%d > %d", phrase->text, n, MAX_PLENGTH);
errCode = ERR_FTYPE;
} else {
/*
* check to make sure that the indexing order values are valid
*/
for (i = 0; i < n; i++) {
order = (INT)phrase->order[i] - 1;
if ((order >= n) || (order < 0) || bList[order]) {
ErrorLog("DEBUG.LOG", "Invalid Indexing in %s: %d", phrase->text, phrase->order[i]);
errCode = ERR_FTYPE;
break;
}
bList[order] = TRUE;
}
}
}
}
return errCode;
}
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HODJNPODJ_PDQ_GAME_H
#define HODJNPODJ_PDQ_GAME_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/boflib/error.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
#define MAX_PLENGTH 25
#define MAX_PLENGTH_S 30
#define MAX_TURNS 3 // Max Turn Count when playing the metagame
// Easter Egg info:
#define BIRD_X 43
#define BIRD_Y 241
#define BIRD_DX 94
#define BIRD_DY 44
#define NUM_BIRD_CELS 20
#define BIRD_SLEEP 40
#define HORSE1_X 158
#define HORSE1_Y 146
#define HORSE1_DX 85
#define HORSE1_DY 126
#define NUM_HORSE1_CELS 16
#define HORSE1_SLEEP 100
#define HORSE2_X 240
#define HORSE2_Y 188
#define HORSE2_DX 127
#define HORSE2_DY 249
#define NUM_HORSE2_CELS 14
#define HORSE2_SLEEP 100
#define FLOWER_X 578
#define FLOWER_Y 246
#define FLOWER_DX 47
#define FLOWER_DY 64
#define NUM_FLOWER_CELS 21
#define FLOWER_SLEEP 200
#define BIRD_ANIM ".\\ART\\BIRD.BMP"
#define HORSE1_ANIM ".\\ART\\HORSE1.BMP"
#define HORSE2_ANIM ".\\ART\\HORSE2.BMP"
#define FLOWER_ANIM ".\\ART\\FLOWER.BMP"
#define WAV_REVEAL ".\\SOUND\\REVEAL.WAV"
#define WAV_BADGUESS ".\\SOUND\\BADGUESS.WAV"
#define WAV_GAMEOVER ".\\SOUND\\GAMEOVER.WAV"
#define WAV_YOUWIN ".\\SOUND\\YOUWIN.WAV"
#define WAV_HORSE1 ".\\SOUND\\HORSE1.WAV"
#define WAV_HORSE2 ".\\SOUND\\HORSE2.WAV"
#define WAV_BIRD ".\\SOUND\\BIRD.WAV"
#define WAV_FLOWER ".\\SOUND\\WEIRD.WAV"
#define MID_SOUNDTRACK ".\\SOUND\\THGESNG.MID"
/*
* prototypes
*/
extern ERROR_CODE InitGame(HWND, CDC *);
extern ERROR_CODE StartGame(CDC *);
extern void GameStopTimer();
extern ERROR_CODE GameStartTimer();
extern void GamePauseTimer();
extern void GameResumeTimer();
extern ERROR_CODE EndGame(CDC *);
extern void WinGame();
extern ERROR_CODE RepaintSpriteList(CDC *);
extern bool CheckUserGuess(const char *);
extern void CALLBACK GetGameParams(CWnd *);
extern void GameGetScore(unsigned int *, unsigned int *, unsigned int *, unsigned int *);
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,111 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/bitmaps.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/pdq/main.h"
#include "bagel/hodjnpodj/pdq/guess.h"
#include "bagel/hodjnpodj/pdq/game.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
#define IDC_EDIT 101
/////////////////////////////////////////////////////////////////////////////
// CGuessDlg dialog
CGuessDlg::CGuessDlg(CWnd *pParent, CPalette *pPalette)
: CBmpDialog(pParent, pPalette, IDD_GUESS_DLG, ".\\ART\\GUESS.BMP", 36, 48) {
}
void CGuessDlg::DoDataExchange(CDataExchange* pDX) {
CBmpDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT, text);
}
bool CGuessDlg::OnInitDialog() {
CEdit *pEdit;
CBmpDialog::OnInitDialog();
pEdit = (CEdit *)GetDlgItem(IDC_EDIT);
pEdit->LimitText(MAX_PLENGTH_S + 1);
SetTimer(10, 50, nullptr);
return true;
}
void CGuessDlg::OnTimer(uintptr nEventID) {
char buf[MAX_PLENGTH_S + 2];
CEdit *pEdit;
KillTimer(nEventID);
pEdit = (CEdit *)GetDlgItem(IDC_EDIT);
pEdit->SetFocus();
pEdit->GetWindowText(buf, MAX_PLENGTH + 1);
pEdit->SetSel(-1, strlen(buf), true);
}
void CGuessDlg::OnPaint() {
CBmpDialog::OnPaint();
}
void CGuessDlg::OnSetFocus(CWnd *) {
SetTimer(10, 50, nullptr);
}
void CGuessDlg::OnActivate(unsigned int nState, CWnd *, bool bMinimized) {
CEdit *pEdit;
pEdit = (CEdit *)GetDlgItem(IDC_EDIT);
if (!bMinimized) {
switch (nState) {
case WA_ACTIVE:
case WA_CLICKACTIVE:
pEdit->SetSel(-1, 0, true);
InvalidateRect(nullptr, false);
break;
}
}
}
bool CGuessDlg::OnEraseBkgnd(CDC *) {
return true;
}
BEGIN_MESSAGE_MAP(CGuessDlg, CBmpDialog)
ON_WM_TIMER()
ON_WM_PAINT()
ON_WM_ACTIVATE()
ON_WM_SETFOCUS()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,60 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HODJNPODJ_PDQ_GUESS_H
#define HODJNPODJ_PDQ_GUESS_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
#define IDD_GUESS_DLG 102
/////////////////////////////////////////////////////////////////////////////
// CGuessDlg dialog
class CGuessDlg : public CBmpDialog {
public:
CGuessDlg(CWnd *, CPalette *); // standard constructor
CString text;
protected:
virtual void DoDataExchange(CDataExchange *) override; // DDX/DDV support
bool OnInitDialog() override;
void OnTimer(uintptr);
void OnPaint();
void OnSetFocus(CWnd *);
void OnActivate(unsigned int, CWnd *, bool) override;
bool OnEraseBkgnd(CDC *);
DECLARE_MESSAGE_MAP()
};
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,98 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/hodjnpodj/pdq/main.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
HINSTANCE hDLLInst;
HINSTANCE hExeInst;
extern LPGAMESTRUCT pGameParams;
// global the pointer to the your game's main window
HWND ghParentWnd;
/////////////////////////////////////////////////////////////////////////////
// Public C interface
/*****************************************************************
*
* RunTGG
*
* FUNCTIONAL DESCRIPTION:
*
* This is the API function for the DLL. It is what the calling app
* calls to invoke poker
*
* FORMAL PARAMETERS:
*
* hParentWnd, lpGameInfo
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
HWND FAR PASCAL RunTGG(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CMainWindow *pMain;
pGameParams = lpGameInfo;
// invoke your game here by creating a pGame for your main window
// look at the InitInstance for your game for this
ghParentWnd = hParentWnd;
if ((pMain = new CMainWindow) != nullptr) {
pMain->ShowWindow(SW_SHOWNORMAL);
pMain->UpdateWindow();
pMain->SetActiveWindow();
if (pGameParams->bPlayingMetagame)
pMain->PlayGame();
}
// these must be set in this function
hDLLInst = (HINSTANCE)GetWindowWord(pMain->m_hWnd, GWW_HINSTANCE);
hExeInst = (HINSTANCE)GetWindowWord(hParentWnd, GWW_HINSTANCE);
return pMain->m_hWnd; // return the m_hWnd of your main game window
}
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,35 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HODJNPODJ_PDQ_GAMEDLL_H
#define HODJNPODJ_PDQ_GAMEDLL_H
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
extern HWND FAR PASCAL RunTGG(HWND hParentWnd, LPGAMESTRUCT lpGameInfo);
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,973 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/dibdoc.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/hodjnpodj/hnplibs/mainmenu.h"
#include "bagel/hodjnpodj/hnplibs/cmessbox.h"
#include "bagel/hodjnpodj/hnplibs/rules.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/boflib/misc.h"
#include "bagel/hodjnpodj/pdq/main.h"
#include "bagel/hodjnpodj/pdq/game.h"
#include "bagel/hodjnpodj/pdq/guess.h"
#include "bagel/metaengine.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
//
// This mini-game's main screen bitmap
//
#define MINI_GAME_MAP ".\\ART\\CORRAL.BMP"
//
// Button ID constants
//
#define IDC_MENU 100
#define WAV_NARRATION ".\\SOUND\\TGG.WAV"
STATIC const char *pszCategoryBitmaps[N_CATEGORIES] = {
".\\ART\\PERSON.BMP",
".\\ART\\PLACE.BMP",
".\\ART\\PHRASE.BMP",
".\\ART\\TITLE.BMP"
};
//
// Edit control ID constants
//
#define IDE_GUESS 101
#define IDE_SCORE 102
#define IDE_SCOREAVG 103
#define KEY_ENTER 0x000D
#define KEY_ESC 0x001B
/*
* Local prototypes
*/
void UpdateScore(unsigned int, unsigned int, unsigned int, unsigned int);
/*
* Globals
*/
CPalette *pMyGamePalette;
CMainWindow *gMain;
bool bInGame;
CText *txtScore, *txtTotalScore, *txtTitle;
LPGAMESTRUCT pGameParams;
extern HWND ghParentWnd;
CMainWindow::CMainWindow() {
CString WndClass;
CRect tmpRect;
CDC *pDC;
CDibDoc *pDibDoc;
ERROR_CODE errCode;
bool bSuccess;
// the game structure must be valid
assert(pGameParams != nullptr);
// assume no error
errCode = ERR_NONE;
// Inits
//
pMyGamePalette = nullptr;
m_pScrollSprite = nullptr;
m_pSoundTrack = nullptr;
m_bInGuess = false;
m_bInMenu = false;
m_iLastType = -1;
gMain = this;
pGameParams->lScore = 0;
// Set the coordinates for the "Start New Game" button
//
m_rNewGameButton.SetRect(15, 4, 233, 20);
// Define a special window class which traps double-clicks, is byte aligned
// to maximize BITBLT performance, and creates "owned" DCs rather than sharing
// the five system defined DCs which are not guaranteed to be available;
// this adds a bit to our app size but avoids hangs/freezes/lockups.
WndClass = AfxRegisterWndClass(CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_OWNDC, nullptr, nullptr, nullptr);
// Acquire the shared palette for our game from the splash screen art
if ((pDibDoc = new CDibDoc()) != nullptr) {
if (pDibDoc->OpenDocument(MINI_GAME_MAP) != false)
pMyGamePalette = pDibDoc->DetachPalette();
else
errCode = ERR_FFIND;
delete pDibDoc;
} else {
errCode = ERR_MEMORY;
}
// Center our window on the screen
//
tmpRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
#ifndef DEBUG
if ((pDC = GetDC()) != nullptr) {
tmpRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) >> 1;
tmpRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) >> 1;
tmpRect.right = tmpRect.left + GAME_WIDTH;
tmpRect.bottom = tmpRect.top + GAME_HEIGHT;
ReleaseDC(pDC);
}
#endif
// Create the window as a POPUP so no boarders, title, or menu are present;
// this is because the game's background art will fill the entire 640x480 area.
Create(WndClass, "Boffo Games -- ThGesngGme", WS_POPUP, tmpRect, nullptr, 0);
BeginWaitCursor();
ShowWindow(SW_SHOWNORMAL);
PaintScreen();
EndWaitCursor();
if ((pDC = GetDC()) != nullptr) {
//
// build our main menu button
//
if ((m_pScrollSprite = new CSprite) != nullptr) {
m_pScrollSprite->SharePalette(pMyGamePalette);
bSuccess = m_pScrollSprite->LoadResourceSprite(pDC, IDB_SCROLBTN);
assert(bSuccess);
m_pScrollSprite->SetMasked(true);
m_pScrollSprite->SetMobile(true);
}
//
// set up the score controls
//
tmpRect.SetRect(401, 143, 585, 163);
if ((txtTitle = new CText) != nullptr)
txtTitle->SetupText(pDC, pMyGamePalette, &tmpRect, JUSTIFY_LEFT);
tmpRect.SetRect(383, 162, 493, 187);
if ((txtScore = new CText) != nullptr)
txtScore->SetupText(pDC, pMyGamePalette, &tmpRect, JUSTIFY_CENTER);
tmpRect.SetRect(515, 162, 555, 187);
if ((txtTotalScore = new CText) != nullptr)
txtTotalScore->SetupText(pDC, pMyGamePalette, &tmpRect, JUSTIFY_CENTER);
ReleaseDC(pDC);
} else {
errCode = ERR_MEMORY;
}
BeginWaitCursor();
if (pGameParams->bMusicEnabled) {
if ((m_pSoundTrack = new CSound) != nullptr) {
m_pSoundTrack->initialize(this, MID_SOUNDTRACK, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END);
m_pSoundTrack->midiLoopPlaySegment(1580, 32600, 0, FMT_MILLISEC);
}
} // end if m_pSoundTrack
LoadCategoryNames();
EndWaitCursor();
SetFocus();
// if we are not playing from the metagame
//
if (!pGameParams->bPlayingMetagame) {
// Automatically bring up the main menu
//
PostMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
} else {
m_nTurnCount = 0; // Count up to three turns in meta-game mode
}
HandleError(errCode);
}
ERROR_CODE CMainWindow::LoadCategoryNames() {
CDC *pDC;
int i;
ERROR_CODE errCode;
// assume no error
errCode = ERR_NONE;
if ((pDC = GetDC()) != nullptr) {
for (i = 0; i < N_CATEGORIES; i++) {
if ((m_pCategories[i] = new CSprite) != nullptr) {
if (m_pCategories[i]->LoadSprite(pDC, pszCategoryBitmaps[i]) != false) {
m_pCategories[i]->SharePalette(pMyGamePalette);
m_pCategories[i]->SetMasked(true);
m_pCategories[i]->SetMobile(true);
} else {
errCode = ERR_UNKNOWN;
}
} else {
errCode = ERR_MEMORY;
}
}
} else {
errCode = ERR_MEMORY;
}
return errCode;
}
void CMainWindow::ReleaseCategoryNames() {
int i;
for (i = N_CATEGORIES - 1; i >= 0; i--) {
if (m_pCategories[i] != nullptr) {
delete m_pCategories[i];
m_pCategories[i] = nullptr;
}
}
}
void CMainWindow::PaintCategory(int iType) {
CDC *pDC;
assert((iType >= 0) && (iType < N_CATEGORIES));
// save this ID for later (EraseCategory)
m_iLastType = iType;
m_pCategories[iType]->LinkSprite();
pDC = GetDC();
m_pCategories[iType]->PaintSprite(pDC, (GAME_WIDTH - m_pCategories[iType]->GetSize().cx) / 2, 76);
ReleaseDC(pDC);
}
void CMainWindow::EraseCategory() {
CDC *pDC;
assert((m_iLastType >= 0) && (m_iLastType < N_CATEGORIES));
pDC = GetDC();
m_pCategories[m_iLastType]->EraseSprite(pDC);
ReleaseDC(pDC);
m_pCategories[m_iLastType]->UnlinkSprite();
m_iLastType = -1;
}
void CMainWindow::HandleError(ERROR_CODE errCode) {
//
// Exit this application on fatal errors
//
if (errCode != ERR_NONE) {
// pause the current game (if any)
GamePauseTimer();
// Display Error Message to the user
MessageBox(errList[errCode], "Fatal Error!", MB_OK | MB_ICONSTOP);
// Force this application to terminate
PostMessage(WM_CLOSE, 0, 0);
// Don't allow a repaint (remove all WM_PAINT messages)
ValidateRect(nullptr);
}
}
// OnPaint:
// This is called whenever Windows sends a WM_PAINT message.
// Note that creating a CPaintDC automatically does a BeginPaint and
// an EndPaint call is done when it is destroyed at the end of this
// function. CPaintDC's constructor needs the window (this).
//
void CMainWindow::OnPaint() {
PAINTSTRUCT lpPaint;
Invalidate(false);
BeginPaint(&lpPaint);
PaintScreen();
EndPaint(&lpPaint);
}
// Paint the background art and upadate any sprites
// called by OnPaint
void CMainWindow::PaintScreen() {
CRect rcDest;
CRect rcDIB;
CDC *pDC;
CDibDoc myDoc;
HDIB hDIB;
unsigned int nLeft, nTotal, nLeftAvg, nTotalAvg;
bool bSuccess;
myDoc.OpenDocument(MINI_GAME_MAP);
hDIB = myDoc.GetHDIB();
pDC = GetDC();
if (pDC && hDIB) {
GetClientRect(rcDest);
rcDIB.top = rcDIB.left = 0;
rcDIB.right = (int) DIBWidth(hDIB);
rcDIB.bottom = (int) DIBHeight(hDIB);
PaintDIB(pDC->m_hDC, &rcDest, hDIB, &rcDIB, pMyGamePalette);
}
if (!m_bInMenu) {
if (m_pScrollSprite != nullptr) {
bSuccess = m_pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
assert(bSuccess);
}
}
/* update the on-screen sprites */
RepaintSpriteList(pDC);
if (txtTitle != nullptr)
txtTitle->DisplayString(pDC, "Score Total Score", 21, FW_BOLD, RGB(0, 0, 0));
GameGetScore(&nLeft, &nTotal, &nLeftAvg, &nTotalAvg);
UpdateScore(nLeft, nTotal, nLeftAvg, nTotalAvg);
ReleaseDC(pDC);
}
// OnCommand
// This function is called when a WM_COMMAND message is issued,
// typically in order to process control related activities.
//
bool CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) {
CMainMenu COptionsWind((CWnd *)this,
pMyGamePalette,
(pGameParams->bPlayingMetagame ? (NO_NEWGAME | NO_OPTIONS) : 0) | (bInGame ? 0 : NO_RETURN),
GetGameParams, "tggrules.txt", (pGameParams->bSoundEffectsEnabled ? WAV_NARRATION : nullptr), pGameParams);
CDC *pDC;
bool bSuccess;
if (HIWORD(lParam) == BN_CLICKED) {
switch (wParam) {
/*
* must bring up our menu of controls
*/
case IDC_MENU:
GamePauseTimer();
// indicate a state of being in the command menu
m_bInMenu = true;
pDC = GetDC();
assert(m_pScrollSprite != nullptr);
if (m_pScrollSprite != nullptr) {
bSuccess = m_pScrollSprite->EraseSprite(pDC);
assert(bSuccess);
}
//PaintScreen();
CSound::waitWaveSounds();
switch (COptionsWind.DoModal()) {
case IDC_OPTIONS_NEWGAME:
PlayGame();
break;
case IDC_OPTIONS_QUIT:
pGameParams->lScore = 0;
PostMessage(WM_CLOSE, 0, 0);
break;
default:
break;
}
assert(m_pScrollSprite != nullptr);
if (m_pScrollSprite != nullptr) {
bSuccess = m_pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
assert(bSuccess);
}
ReleaseDC(pDC);
SetFocus();
// not in command menu any more
m_bInMenu = false;
if (!pGameParams->bMusicEnabled && (m_pSoundTrack != nullptr)) {
m_pSoundTrack->stop();
delete m_pSoundTrack;
m_pSoundTrack = nullptr;
} else if (pGameParams->bMusicEnabled && (m_pSoundTrack == nullptr)) {
if ((m_pSoundTrack = new CSound) != nullptr) {
m_pSoundTrack->initialize(this, MID_SOUNDTRACK, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END);
m_pSoundTrack->midiLoopPlaySegment(1580, 32600, 0, FMT_MILLISEC);
}
}
GameResumeTimer();
return true;
}
}
return false;
}
void CMainWindow::PlayGame() {
CDC *pDC;
unsigned int nLeft, nTotal, nLeftAvg, nTotalAvg;
ERROR_CODE errCode;
pDC = GetDC();
bInGame = false;
if ((errCode = InitGame(m_hWnd, pDC)) == ERR_NONE) {
bInGame = true;
if (pGameParams->bPlayingMetagame)
m_nTurnCount++;
/* erase current score */
GameGetScore(&nLeft, &nTotal, &nLeftAvg, &nTotalAvg);
UpdateScore(nLeft, nTotal, nLeftAvg, nTotalAvg);
if ((errCode = StartGame(pDC)) != ERR_NONE) {
/* cleanup on error */
EndGame(pDC);
bInGame = false;
}
}
HandleError(errCode);
ReleaseDC(pDC);
}
void CMainWindow::OnMouseMove(unsigned int, CPoint) {
SetCursor(LoadCursor(nullptr, IDC_ARROW));
}
//
// Hooked when we get a WM_QUIT (or WM_CLOSE ?) message
//
void CMainWindow::OnClose() {
CBrush myBrush;
CRect myRect;
CDC *pDC;
ReleaseCategoryNames();
// delete the game theme song
//
if (m_pSoundTrack != nullptr) {
assert(pGameParams->bMusicEnabled);
delete m_pSoundTrack;
m_pSoundTrack = nullptr;
}
CSound::clearSounds();
if ((pDC = GetDC()) != nullptr) {
if (bInGame) {
EndGame(pDC);
bInGame = false;
}
ReleaseDC(pDC);
}
assert(txtTotalScore != nullptr);
if (txtTotalScore != nullptr) {
delete txtTotalScore;
txtTotalScore = nullptr;
}
assert(txtScore != nullptr);
if (txtScore != nullptr) {
delete txtScore;
txtScore = nullptr;
}
assert(txtTitle != nullptr);
if (txtTitle != nullptr) {
delete txtTitle;
txtTitle = nullptr;
}
//
// de-allocate any controls that we used
//
assert(m_pScrollSprite != nullptr);
if (m_pScrollSprite != nullptr) {
delete m_pScrollSprite;
m_pScrollSprite = nullptr;
}
//
// need to de-allocate the game palette
//
assert(pMyGamePalette != nullptr);
if (pMyGamePalette != nullptr) {
pMyGamePalette->DeleteObject();
delete pMyGamePalette;
pMyGamePalette = nullptr;
}
if ((pDC = GetDC()) != nullptr) { // paint black
myRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
myBrush.CreateStockObject(BLACK_BRUSH);
pDC->FillRect(&myRect, &myBrush);
ReleaseDC(pDC);
}
CFrameWnd::OnClose();
MFC::PostMessage(ghParentWnd, WM_PARENTNOTIFY, WM_DESTROY, 0L);
}
void CMainWindow::OnSysChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// terminate app on ALT_Q
//
if ((nChar == 'q') && (nFlags & 0x2000)) {
pGameParams->lScore = 0;
PostMessage(WM_CLOSE, 0, 0);
} else {
// default action
CFrameWnd ::OnSysChar(nChar, nRepCnt, nFlags);
}
}
void CMainWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
switch (nChar) {
// User has hit ALT_F4 so close down this App
//
case VK_F4:
pGameParams->lScore = 0;
PostMessage(WM_CLOSE, 0, 0);
break;
default:
CFrameWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
break;
}
}
void CMainWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
CDC *pDC;
unsigned int nLeft, nTotal, nLeftAvg, nTotalAvg;
// Handle keyboard input
//
switch (nChar) {
//
// Bring up the Rules
//
case VK_F1: {
GamePauseTimer();
CSound::waitWaveSounds();
CRules RulesDlg(this, "tggrules.txt", pMyGamePalette, (pGameParams->bSoundEffectsEnabled ? WAV_NARRATION : nullptr));
RulesDlg.DoModal();
SetFocus();
GameResumeTimer();
}
break;
//
// Bring up the options menu
//
case VK_F2:
SendMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
break;
default:
if (bInGame && ((nChar == KEY_ENTER) || (toupper(nChar) >= 'A' && toupper(nChar) <= 'Z'))) {
m_pDlgGuess = new CGuessDlg(this, pMyGamePalette);
assert(m_pDlgGuess);
GamePauseTimer();
m_pDlgGuess->text = "";
if (nChar != KEY_ENTER)
m_pDlgGuess->text = CString((char)nChar);
m_bInGuess = true;
m_pDlgGuess->DoModal();
m_bInGuess = false;
SetFocus();
// Check user's guess with the actual phrase
if (CheckUserGuess(m_pDlgGuess->text)) {
// User WON - now we need to shut off the timer
GameStopTimer();
WinGame();
/*
* Calculate score
*/
GameGetScore(&nLeft, &nTotal, &nLeftAvg, &nTotalAvg);
UpdateScore(nLeft, nTotal, nLeftAvg, nTotalAvg);
if (pGameParams->bSoundEffectsEnabled)
sndPlaySound(WAV_YOUWIN, SND_ASYNC);
CMessageBox dlgYouWin((CWnd *)this, pMyGamePalette, "You are correct!", "You have won.");
SetFocus();
pDC = gMain->GetDC();
EndGame(pDC);
gMain->ReleaseDC(pDC);
bInGame = false;
pGameParams->lScore += (100 * nLeft) / nTotal;
// if in metagame then close dll when game is ended
//
if ((pGameParams->bPlayingMetagame) && (m_nTurnCount == MAX_TURNS)) {
PostMessage(WM_CLOSE, 0, 0);
} else {
// start a new game instantly
PlayGame();
}
} else {
// User guessed incorrectly
if (pGameParams->bSoundEffectsEnabled)
sndPlaySound(WAV_BADGUESS, SND_ASYNC);
}
delete m_pDlgGuess;
m_pDlgGuess = nullptr;
GameResumeTimer();
} else {
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
break;
}
}
void CMainWindow::OnChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
CWnd::OnChar(nChar, nRepCnt, nFlags);
}
void UpdateScore(unsigned int nLeft, unsigned int nTotal, unsigned int nLeftAvg, unsigned int nTotalAvg) {
char buf[40];
CDC *pDC;
if ((pDC = gMain->GetDC()) != nullptr) {
if ((txtScore != nullptr) && (txtTotalScore != nullptr)) {
/*
* update the current score
*/
if (nTotal == 0)
Common::sprintf_s(buf, "%d/%d = %d%%", nLeft, nTotal, 0);
else
Common::sprintf_s(buf, "%d/%d = %d%%", nLeft, nTotal, (100 * nLeft) / nTotal);
txtScore->DisplayString(pDC, buf, 21, FW_BOLD, RGB(0, 0, 0));
/*
* update the cumulative score
*/
if (nTotalAvg == 0)
Common::sprintf_s(buf, "0%%");
else
Common::sprintf_s(buf, "%d%%", (100 * nLeftAvg) / nTotalAvg);
txtTotalScore->DisplayString(pDC, buf, 21, FW_BOLD, RGB(0, 0, 0));
}
gMain->ReleaseDC(pDC);
}
}
void CMainWindow::OnLButtonDown(unsigned int nFlags, CPoint point) {
CDC *pDC;
CSprite *pSprite = nullptr;
CSound *pEffect = nullptr;
CRect tmpRect,
birdRect,
horse1Rect,
horse2Rect,
flowerRect;
bool bSuccess;
int i;
birdRect.SetRect(BIRD_X, BIRD_Y, BIRD_X + BIRD_DX, BIRD_Y + BIRD_DY);
horse1Rect.SetRect(HORSE1_X, HORSE1_Y, HORSE1_X + HORSE1_DX, HORSE1_Y + HORSE1_DY);
horse2Rect.SetRect(HORSE2_X, HORSE2_Y, HORSE2_X + HORSE2_DX, HORSE2_Y + HORSE2_DY);
flowerRect.SetRect(FLOWER_X, FLOWER_Y, FLOWER_X + FLOWER_DX, FLOWER_Y + FLOWER_DY);
tmpRect = m_pScrollSprite->GetRect();
CSound::waitWaveSounds();
if (tmpRect.PtInRect(point)) {
PostMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
// User clicked on the Title - NewGame button
//
} else if (m_rNewGameButton.PtInRect(point)) {
// if we are not playing from the metagame
//
if (!pGameParams->bPlayingMetagame) {
// start a new game
PlayGame();
}
} else if (birdRect.PtInRect(point)) {
pDC = GetDC();
pSprite = new CSprite;
(*pSprite).SharePalette(pMyGamePalette);
bSuccess = (*pSprite).LoadCels(pDC, BIRD_ANIM, NUM_BIRD_CELS);
if (!bSuccess) {
delete pSprite;
ReleaseDC(pDC);
return;
}
(*pSprite).SetMasked(false);
(*pSprite).SetMobile(false);
if ((*pGameParams).bSoundEffectsEnabled) {
if ((pEffect = new CSound((CWnd *)this, WAV_BIRD, SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE | SOUND_QUEUE)) != nullptr) {
pEffect->play();
}
}
(*pSprite).SetCel(NUM_BIRD_CELS);
for (i = 0; i < NUM_BIRD_CELS; i++) {
(*pSprite).PaintSprite(pDC, BIRD_X, BIRD_Y);
CSound::handleMessages();
Sleep(BIRD_SLEEP);
}
delete pSprite;
ReleaseDC(pDC);
} else if (horse1Rect.PtInRect(point)) {
pDC = GetDC();
pSprite = new CSprite;
(*pSprite).SharePalette(pMyGamePalette);
bSuccess = (*pSprite).LoadCels(pDC, HORSE1_ANIM, NUM_HORSE1_CELS);
if (!bSuccess) {
delete pSprite;
ReleaseDC(pDC);
return;
}
(*pSprite).SetMasked(false);
(*pSprite).SetMobile(false);
if ((*pGameParams).bSoundEffectsEnabled) {
if ((pEffect = new CSound((CWnd *)this, WAV_HORSE1, SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE | SOUND_QUEUE)) != nullptr) {
pEffect->play();
}
}
(*pSprite).SetCel(NUM_HORSE1_CELS);
for (i = 0; i < NUM_HORSE1_CELS; i++) {
(*pSprite).PaintSprite(pDC, HORSE1_X, HORSE1_Y);
CSound::handleMessages();
Sleep(HORSE1_SLEEP);
}
if (pSprite != nullptr)
delete pSprite;
ReleaseDC(pDC);
} else if (horse2Rect.PtInRect(point)) {
pDC = GetDC();
pSprite = new CSprite;
(*pSprite).SharePalette(pMyGamePalette);
bSuccess = (*pSprite).LoadCels(pDC, HORSE2_ANIM, NUM_HORSE2_CELS);
if (!bSuccess) {
delete pSprite;
ReleaseDC(pDC);
return;
}
(*pSprite).SetMasked(false);
(*pSprite).SetMobile(false);
if ((*pGameParams).bSoundEffectsEnabled) {
if ((pEffect = new CSound((CWnd *)this, WAV_HORSE2, SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE | SOUND_QUEUE)) != nullptr) {
pEffect->play();
}
}
(*pSprite).SetCel(NUM_HORSE2_CELS);
for (i = 0; i < NUM_HORSE2_CELS; i++) {
(*pSprite).PaintSprite(pDC, HORSE2_X, HORSE2_Y);
CSound::handleMessages();
Sleep(HORSE2_SLEEP);
}
if (pSprite != nullptr)
delete pSprite;
ReleaseDC(pDC);
} else if (flowerRect.PtInRect(point)) {
pDC = GetDC();
pSprite = new CSprite;
(*pSprite).SharePalette(pMyGamePalette);
bSuccess = (*pSprite).LoadCels(pDC, FLOWER_ANIM, NUM_FLOWER_CELS);
if (!bSuccess) {
delete pSprite;
ReleaseDC(pDC);
return;
}
(*pSprite).SetMasked(false);
(*pSprite).SetMobile(false);
if ((*pGameParams).bSoundEffectsEnabled) {
if ((pEffect = new CSound((CWnd *)this, WAV_FLOWER, SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE | SOUND_QUEUE)) != nullptr) {
pEffect->play();
}
}
(*pSprite).SetCel(NUM_FLOWER_CELS);
for (i = 0; i < NUM_FLOWER_CELS; i++) {
(*pSprite).PaintSprite(pDC, FLOWER_X, FLOWER_Y);
CSound::handleMessages();
Sleep(FLOWER_SLEEP);
}
if (pSprite != nullptr)
delete pSprite;
ReleaseDC(pDC);
} else {
CFrameWnd::OnLButtonDown(nFlags, point);
}
}
void CMainWindow::OnSetFocus(CWnd *) {
if (m_bInGuess)
m_pDlgGuess->SetFocus();
else {
SetFocus();
}
}
void CMainWindow::OnActivate(unsigned int nState, CWnd *, bool bMinimized) {
if (!bMinimized) {
switch (nState) {
case WA_ACTIVE:
case WA_CLICKACTIVE:
// Restrict the keybinding to minimal
BagelMetaEngine::setKeybindingMode(KBMODE_MINIMAL);
break;
case WA_INACTIVE:
BagelMetaEngine::setKeybindingMode(KBMODE_NORMAL);
break;
default:
break;
}
}
}
//////////// Additional Sound Notify routines //////////////
LRESULT CMainWindow::OnMCINotify(WPARAM wParam, LPARAM lParam) {
CSound *pSound;
pSound = CSound::OnMCIStopped(wParam, lParam);
if (pSound != nullptr)
OnSoundNotify(pSound);
return 0;
}
LRESULT CMainWindow::OnMMIONotify(WPARAM wParam, LPARAM lParam) {
CSound *pSound;
pSound = CSound::OnMMIOStopped(wParam, lParam);
if (pSound != nullptr)
OnSoundNotify(pSound);
return 0;
}
void CMainWindow::OnSoundNotify(CSound *) {
//
// Add your code to process explicit notification of a sound "done" event here.
// pSound is a pointer to a CSound object for which you requested SOUND_NOTIFY.
//
}
//
// CMainWindow message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_PAINT()
ON_WM_CHAR()
ON_WM_SYSCHAR()
ON_WM_KEYDOWN()
ON_WM_SYSKEYDOWN()
ON_WM_CLOSE()
ON_WM_MOUSEMOVE()
ON_WM_SETFOCUS()
ON_WM_LBUTTONDOWN()
ON_WM_ACTIVATE()
ON_MESSAGE(MM_MCINOTIFY, CMainWindow::OnMCINotify)
ON_MESSAGE(MM_WOM_DONE, CMainWindow::OnMMIONotify)
END_MESSAGE_MAP()
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,88 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HODJNPODJ_PDQ_MAIN_H
#define HODJNPODJ_PDQ_MAIN_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/boflib/error.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/boflib/sound.h"
#include "bagel/hodjnpodj/pdq/guess.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
#define N_CATEGORIES 4
class CMainWindow : public CFrameWnd {
public:
CMainWindow();
~CMainWindow() override {}
void PlayGame();
void PaintScreen();
void PaintCategory(int);
void EraseCategory();
int m_nTurnCount = 0;
protected:
ERROR_CODE LoadCategoryNames();
void ReleaseCategoryNames();
virtual bool OnCommand(WPARAM wParam, LPARAM lParam) override;
void HandleError(ERROR_CODE);
void OnSoundNotify(CSound *pSound);
void OnPaint();
void OnChar(unsigned int, unsigned int, unsigned int);
void OnSysChar(unsigned int, unsigned int, unsigned int);
void OnKeyDown(unsigned int, unsigned int, unsigned int);
void OnSysKeyDown(unsigned int, unsigned int, unsigned int);
void OnMouseMove(unsigned int, CPoint);
void OnLButtonDown(unsigned int, CPoint);
void OnActivate(unsigned int, CWnd *, bool) override;
void OnSetFocus(CWnd *);
void OnClose();
LRESULT OnMCINotify(WPARAM, LPARAM);
LRESULT OnMMIONotify(WPARAM, LPARAM);
DECLARE_MESSAGE_MAP()
CRect m_rNewGameButton;
CSprite *m_pCategories[N_CATEGORIES] = {};
CSprite *m_pScrollSprite = nullptr;
CGuessDlg *m_pDlgGuess = nullptr;
CSound *m_pSoundTrack = nullptr;
int m_iLastType = 0;
bool m_bInMenu = false;
bool m_bInGuess = false;
};
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,502 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/menures.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/hodjnpodj/pdq/usercfg.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
#define ID_RESET 104
#define ID_GAMESPEED 105
#define ID_FIXED 106
#define ID_SPEED 112
#define ID_SHOWN 114
#define ID_NAMES 111
extern const char *INI_SECTION;
static const char *apszSpeeds[10] = {
"Molasses in Stasis",
"Frozen Molasses",
"Molasses",
"Maple Syrup",
"Oil",
"Watery Oil",
"Oily Water",
"Water",
"Quicksilver",
"Quick Quicksilver"
};
static CText *txtGameSpeed;
static CText *txtRevealed;
static CText *txtSpeed;
static CText *txtShown;
static CColorButton *pOKButton = nullptr; // OKAY button on scroll
static CColorButton *pCancelButton = nullptr; // Cancel button on scroll
static CColorButton *pDefaultsButton = nullptr; // Defaults button on scroll
static CCheckButton *pFixedButton = nullptr;
CUserCfgDlg::CUserCfgDlg(CWnd *pParent, CPalette *pPalette, unsigned int nID)
: CBmpDialog(pParent, pPalette, nID, ".\\ART\\SSCROLL.BMP") {
m_pNamesButton = nullptr;
DoModal();
}
void CUserCfgDlg::DoDataExchange(CDataExchange *pDX) {
CBmpDialog::DoDataExchange(pDX);
}
void CUserCfgDlg::PutDlgData() {
m_pSpeedScroll->SetScrollPos(m_nGameSpeed);
m_pShownScroll->SetScrollPos(m_nShown);
pFixedButton->SetCheck(!m_bRandomLetters);
m_pNamesButton->SetCheck(m_bShowNames);
}
void CUserCfgDlg::GetDlgData() {
m_nGameSpeed = m_pSpeedScroll->GetScrollPos();
m_nShown = m_pShownScroll->GetScrollPos();
m_bRandomLetters = true;
if (pFixedButton->GetCheck() == 1)
m_bRandomLetters = false;
m_bShowNames = false;
if (m_pNamesButton->GetCheck() == 1) {
m_bShowNames = true;
}
}
bool CUserCfgDlg::OnCommand(WPARAM wParam, LPARAM lParam) {
/*
* respond to user
*/
if (HIWORD(lParam) == BN_CLICKED) {
switch (wParam) {
case IDOK:
m_bShouldSave = true;
ClearDialogImage();
EndDialog(IDOK);
return false;
case IDCANCEL:
ClearDialogImage();
EndDialog(IDCANCEL);
return false;
/*
* reset params to default
*/
case ID_RESET:
m_bRandomLetters = false;
m_nShown = SHOWN_DEF;
m_nGameSpeed = SPEED_DEF;
m_bShowNames = true;
PutDlgData();
DispSpeed();
DispShown();
break;
case ID_NAMES:
m_bShowNames = !m_bShowNames;
PutDlgData();
break;
case ID_FIXED:
m_bRandomLetters = !m_bRandomLetters;
PutDlgData();
break;
default:
break;
}
}
return CBmpDialog::OnCommand(wParam, lParam);
}
void CUserCfgDlg::OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar *pScroll) {
switch (pScroll->GetDlgCtrlID()) {
case ID_SPEED:
switch (nSBCode) {
case SB_LEFT:
m_nGameSpeed = SPEED_MIN;
break;
case SB_LINELEFT:
case SB_PAGELEFT:
if (m_nGameSpeed > SPEED_MIN)
m_nGameSpeed--;
break;
case SB_RIGHT:
m_nGameSpeed = SPEED_MAX;
break;
case SB_LINERIGHT:
case SB_PAGERIGHT:
if (m_nGameSpeed < SPEED_MAX)
m_nGameSpeed++;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_nGameSpeed = nPos;
break;
default:
break;
}
assert(m_nGameSpeed >= SPEED_MIN && m_nGameSpeed <= SPEED_MAX);
if (m_nGameSpeed < SPEED_MIN)
m_nGameSpeed = SPEED_MIN;
if (m_nGameSpeed > SPEED_MAX)
m_nGameSpeed = SPEED_MAX;
/* can't access a null pointers */
assert(pScroll != nullptr);
pScroll->SetScrollPos(m_nGameSpeed);
DispSpeed();
break;
case ID_SHOWN:
switch (nSBCode) {
case SB_LEFT:
m_nShown = SHOWN_MIN;
break;
case SB_LINELEFT:
case SB_PAGELEFT:
if (m_nShown > SHOWN_MIN)
m_nShown--;
break;
case SB_RIGHT:
m_nShown = SHOWN_MAX;
break;
case SB_LINERIGHT:
case SB_PAGERIGHT:
if (m_nShown < SHOWN_MAX)
m_nShown++;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_nShown = nPos;
break;
default:
break;
}
assert(m_nShown >= SHOWN_MIN && m_nShown <= SHOWN_MAX);
if (m_nShown < SHOWN_MIN)
m_nShown = SHOWN_MIN;
if (m_nShown > SHOWN_MAX)
m_nShown = SHOWN_MAX;
/* can't access a null pointers */
assert(pScroll != nullptr);
pScroll->SetScrollPos(m_nShown);
DispShown();
break;
default:
break;
} // end Switch ID
}
bool CUserCfgDlg::OnInitDialog() {
CRect tmpRect;
char buf[10];
CDC *pDC;
CBmpDialog::OnInitDialog();
tmpRect.SetRect(22, 100, 122, 120);
m_pShownScroll = new CScrollBar;
m_pShownScroll->Create(WS_VISIBLE | WS_CHILD | SBS_HORZ | SBS_BOTTOMALIGN, tmpRect, this, ID_SHOWN);
m_pShownScroll->SetScrollRange(SHOWN_MIN, SHOWN_MAX, true);
tmpRect.SetRect(22, 138, 122, 158);
m_pSpeedScroll = new CScrollBar;
m_pSpeedScroll->Create(WS_VISIBLE | WS_CHILD | SBS_HORZ | SBS_BOTTOMALIGN, tmpRect, this, ID_SPEED);
m_pSpeedScroll->SetScrollRange(SPEED_MIN, SPEED_MAX, true);
pDC = GetDC();
tmpRect.SetRect(22, 125, 60, 140);
if ((txtGameSpeed = new CText) != nullptr) {
txtGameSpeed->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
tmpRect.SetRect(65, 125, 170, 140);
if ((txtSpeed = new CText) != nullptr) {
txtSpeed->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
tmpRect.SetRect(22, 87, 80, 102);
if ((txtRevealed = new CText) != nullptr) {
txtRevealed->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
tmpRect.SetRect(85, 87, 146, 102);
if ((txtShown = new CText) != nullptr) {
txtShown->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
ReleaseDC(pDC);
if ((pOKButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pOKButton).SetPalette(m_pPalette); // set the palette to use
(*pOKButton).SetControl(IDOK, this); // tie to the dialog control
}
if ((pCancelButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pCancelButton).SetPalette(m_pPalette); // set the palette to use
(*pCancelButton).SetControl(IDCANCEL, this); // tie to the dialog control
}
if ((pDefaultsButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pDefaultsButton).SetPalette(m_pPalette); // set the palette to use
(*pDefaultsButton).SetControl(ID_RESET, this); // tie to the dialog control
}
if ((pFixedButton = new CCheckButton) != nullptr) { // build a color QUIT button to let us exit
(*pFixedButton).SetPalette(m_pPalette); // set the palette to use
(*pFixedButton).SetControl(ID_FIXED, this); // tie to the dialog control
}
if ((m_pNamesButton = new CCheckButton) != nullptr) {
m_pNamesButton->SetPalette(m_pPalette);
m_pNamesButton->SetControl(ID_NAMES, this);
}
m_bShouldSave = false;
/*
* User can specify if he/she wants the letters to appear in a random order
* or in the predefined fixed order set by the MetaGame
*/
GetPrivateProfileString(INI_SECTION, "RandomLetters", "No", buf, 10, INI_FILENAME);
m_bRandomLetters = false;
if (!scumm_stricmp(buf, "Yes"))
m_bRandomLetters = true;
/*
* This will determine how many letters are intially displayed (default is SHOWN_DEF)
*/
m_nShown = GetPrivateProfileInt(INI_SECTION, "NumStartingLetters", SHOWN_DEF, INI_FILENAME);
if ((m_nShown < SHOWN_MIN) || (m_nShown > SHOWN_MAX))
m_nShown = SHOWN_DEF;
/*
* This will determine the speed of the letters being displayed:
* Range is 1..10 with 1 = 5000ms, 10 = 500ms
*/
m_nGameSpeed = GetPrivateProfileInt(INI_SECTION, "GameSpeed", SPEED_DEF, INI_FILENAME);
if ((m_nGameSpeed < SPEED_MIN) || (m_nGameSpeed > SPEED_MAX))
m_nGameSpeed = SPEED_DEF;
GetPrivateProfileString(INI_SECTION, "ShowCategoryNames", "Yes", buf, 10, INI_FILENAME);
assert(strlen(buf) < 10);
m_bShowNames = false;
if (!scumm_stricmp(buf, "Yes"))
m_bShowNames = true;
PutDlgData();
return true;
}
void CUserCfgDlg::OnPaint() {
CDC *pDC;
CBmpDialog::OnPaint();
pDC = GetDC();
txtGameSpeed->DisplayString(pDC, "Speed:", 14, TEXT_BOLD, RGB(0, 0, 0));
txtRevealed->DisplayString(pDC, "Revealed:", 14, TEXT_BOLD, RGB(0, 0, 0));
DispSpeed();
DispShown();
ReleaseDC(pDC);
}
BEGIN_MESSAGE_MAP(CUserCfgDlg, CBmpDialog)
ON_WM_HSCROLL()
ON_WM_PAINT()
ON_WM_DESTROY()
END_MESSAGE_MAP()
void CUserCfgDlg::OnDestroy() {
if (m_pSpeedScroll != nullptr) {
delete m_pSpeedScroll;
m_pSpeedScroll = nullptr;
}
if (m_pShownScroll != nullptr) {
delete m_pShownScroll;
m_pShownScroll = nullptr;
}
CBmpDialog::OnDestroy();
}
void CUserCfgDlg::DispSpeed() {
CDC *pDC;
if ((pDC = GetDC()) != nullptr) {
txtSpeed->DisplayString(pDC, apszSpeeds[m_nGameSpeed - 1], 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
}
}
void CUserCfgDlg::DispShown() {
CDC *pDC;
char msg[5];
Common::sprintf_s(msg, "%d", m_nShown);
if ((pDC = GetDC()) != nullptr) {
txtShown->DisplayString(pDC, msg, 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
}
}
void CUserCfgDlg::ClearDialogImage() {
CDC *pDC;
if (m_bShouldSave) {
GetDlgData();
WritePrivateProfileString(INI_SECTION, "RandomLetters",
m_bRandomLetters ? "Yes" : "No", INI_FILENAME);
WritePrivateProfileString(INI_SECTION, "NumStartingLetters",
Common::String::format("%d", m_nShown).c_str(),
INI_FILENAME);
WritePrivateProfileString(INI_SECTION, "GameSpeed",
Common::String::format("%d", m_nGameSpeed).c_str(),
INI_FILENAME);
WritePrivateProfileString(INI_SECTION, "ShowCategoryNames",
m_bShowNames ? "Yes" : "No", INI_FILENAME);
}
pDC = GetDC();
if (txtSpeed != nullptr) {
txtSpeed->RestoreBackground(pDC);
delete txtSpeed;
txtSpeed = nullptr;
}
if (txtShown != nullptr) {
txtShown->RestoreBackground(pDC);
delete txtShown;
txtShown = nullptr;
}
if (txtRevealed != nullptr) {
txtRevealed->RestoreBackground(pDC);
delete txtRevealed;
txtRevealed = nullptr;
}
if (txtGameSpeed != nullptr) {
txtGameSpeed->RestoreBackground(pDC);
delete txtGameSpeed;
txtGameSpeed = nullptr;
}
ReleaseDC(pDC);
if (pOKButton != nullptr) { // release the button
delete pOKButton;
pOKButton = nullptr;
}
if (pCancelButton != nullptr) { // release the button
delete pCancelButton;
pCancelButton = nullptr;
}
if (pDefaultsButton != nullptr) { // release the button
delete pDefaultsButton;
pDefaultsButton = nullptr;
}
if (pFixedButton != nullptr) { // release the button
delete pFixedButton;
pFixedButton = nullptr;
}
if (m_pNamesButton != nullptr) {
delete m_pNamesButton;
m_pNamesButton = nullptr;
}
ValidateRect(nullptr);
}
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,81 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HODJNPODJ_PDQ_USERCFG_H
#define HODJNPODJ_PDQ_USERCFG_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
namespace Bagel {
namespace HodjNPodj {
namespace PDQ {
#define IDD_USERCFG 100
#define SPEED_MIN 1
#define SPEED_DEF 7
#define SPEED_MAX 10
#define SHOWN_MIN 1
#define SHOWN_DEF 3
#define SHOWN_MAX 9
class CUserCfgDlg : public CBmpDialog {
public:
CUserCfgDlg(CWnd* pParent = nullptr, CPalette *pPalette = nullptr, unsigned int = IDD_USERCFG);
protected:
virtual void DoDataExchange(CDataExchange *) override;
virtual bool OnCommand(WPARAM, LPARAM) override;
virtual bool OnInitDialog() override;
void PutDlgData();
void GetDlgData();
void DispSpeed();
void DispShown();
void ClearDialogImage();
void OnHScroll(unsigned int, unsigned int, CScrollBar *);
void OnPaint();
void OnDestroy();
DECLARE_MESSAGE_MAP()
CScrollBar *m_pSpeedScroll = nullptr;
CScrollBar *m_pShownScroll = nullptr;
CCheckButton *m_pNamesButton = nullptr;
/*
* user preference data
*/
unsigned int m_nShown = 0; // initial number of letters to be revealed
unsigned int m_nGameSpeed = 0; // game speed 1..5 (1 = fast, 5 = slow)
bool m_bRandomLetters = false; // true if letters to be revealed in random order
bool m_bShowNames = false; // true if we should show category names
bool m_bShouldSave = false; // true if we should save theses values
};
} // namespace PDQ
} // namespace HodjNPodj
} // namespace Bagel
#endif