
There's no evidence Tags.h contained these variables (if anything, it appears that Pixel manually declared them in every file that used them). gg Pixel
781 lines
14 KiB
C++
781 lines
14 KiB
C++
#include "Main.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <shlwapi.h>
|
|
|
|
#include "WindowsWrapper.h"
|
|
|
|
#include "CommonDefines.h"
|
|
#include "Config.h"
|
|
#include "Dialog.h"
|
|
#include "Draw.h"
|
|
#include "Game.h"
|
|
#include "Generic.h"
|
|
#include "Input.h"
|
|
#include "KeyControl.h"
|
|
#include "MyChar.h"
|
|
#include "Organya.h"
|
|
#include "Profile.h"
|
|
#include "Sound.h"
|
|
#include "Triangle.h"
|
|
|
|
LRESULT __stdcall WindowProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
char gModulePath[MAX_PATH];
|
|
char gDataPath[MAX_PATH];
|
|
|
|
int gJoystickButtonTable[8];
|
|
|
|
HWND ghWnd;
|
|
BOOL bFullscreen;
|
|
BOOL gbUseJoystick = FALSE;
|
|
|
|
static BOOL bFps = FALSE;
|
|
static BOOL bActive = TRUE;
|
|
|
|
static HANDLE hObject;
|
|
static HANDLE hMutex;
|
|
static HINSTANCE ghInstance;
|
|
|
|
static int windowWidth;
|
|
static int windowHeight;
|
|
|
|
static const char *mutex_name = "Doukutsu";
|
|
|
|
#ifdef JAPANESE
|
|
static const char *lpWindowName = "\x93\xB4\x8C\x41\x95\xA8\x8C\xEA"; // '洞窟物語' (Cave Story) in Shift-JIS
|
|
#else
|
|
static const char *lpWindowName = "Cave Story ~ Doukutsu Monogatari";
|
|
#endif
|
|
|
|
void SetWindowName(HWND hWnd)
|
|
{
|
|
char window_name[0x100];
|
|
|
|
sprintf(window_name, "%s", lpWindowName);
|
|
SetWindowTextA(hWnd, window_name);
|
|
}
|
|
|
|
// Framerate stuff
|
|
void PutFramePerSecound(void)
|
|
{
|
|
if (bFps)
|
|
{
|
|
const unsigned long fps = GetFramePerSecound();
|
|
PutNumber4(WINDOW_WIDTH - 40, 8, fps, FALSE);
|
|
}
|
|
}
|
|
|
|
unsigned long GetFramePerSecound(void)
|
|
{
|
|
unsigned long current_tick;
|
|
static BOOL need_new_base_tick = TRUE;
|
|
static unsigned long frames_this_second;
|
|
static unsigned long current_frame;
|
|
static unsigned long base_tick;
|
|
|
|
if (need_new_base_tick)
|
|
{
|
|
base_tick = GetTickCount();
|
|
need_new_base_tick = FALSE;
|
|
}
|
|
|
|
current_tick = GetTickCount();
|
|
++current_frame;
|
|
|
|
if (base_tick + 1000 <= current_tick)
|
|
{
|
|
base_tick += 1000;
|
|
frames_this_second = current_frame;
|
|
current_frame = 0;
|
|
}
|
|
|
|
return frames_this_second;
|
|
}
|
|
|
|
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
|
{
|
|
(void)hPrevInstance;
|
|
(void)lpCmdLine;
|
|
(void)nShowCmd;
|
|
|
|
int i;
|
|
|
|
hObject = OpenMutexA(MUTEX_ALL_ACCESS, 0, mutex_name);
|
|
if (hObject != NULL)
|
|
{
|
|
CloseHandle(hObject);
|
|
return 0;
|
|
}
|
|
|
|
hMutex = CreateMutexA(NULL, FALSE, mutex_name);
|
|
|
|
ghInstance = hInstance;
|
|
|
|
// Get executable's path
|
|
GetModuleFileNameA(NULL, gModulePath, MAX_PATH);
|
|
PathRemoveFileSpecA(gModulePath);
|
|
|
|
// Get path of the data folder
|
|
strcpy(gDataPath, gModulePath);
|
|
strcat(gDataPath, "\\data");
|
|
|
|
CONFIG conf;
|
|
if (!LoadConfigData(&conf))
|
|
DefaultConfigData(&conf);
|
|
|
|
// Apply keybinds
|
|
// Swap X and Z buttons
|
|
switch (conf.attack_button_mode)
|
|
{
|
|
case 0:
|
|
gKeyJump = KEY_Z;
|
|
gKeyShot = KEY_X;
|
|
break;
|
|
|
|
case 1:
|
|
gKeyJump = KEY_X;
|
|
gKeyShot = KEY_Z;
|
|
break;
|
|
}
|
|
|
|
// Swap Okay and Cancel buttons
|
|
switch (conf.ok_button_mode)
|
|
{
|
|
case 0:
|
|
gKeyOk = gKeyJump;
|
|
gKeyCancel = gKeyShot;
|
|
break;
|
|
|
|
case 1:
|
|
gKeyOk = gKeyShot;
|
|
gKeyCancel = gKeyJump;
|
|
break;
|
|
}
|
|
|
|
// Swap left and right weapon switch keys
|
|
if (CheckFileExists("s_reverse"))
|
|
{
|
|
gKeyArms = KEY_ARMSREV;
|
|
gKeyArmsRev = KEY_ARMS;
|
|
}
|
|
|
|
// Alternate movement keys
|
|
switch (conf.move_button_mode)
|
|
{
|
|
case 0:
|
|
gKeyLeft = KEY_LEFT;
|
|
gKeyUp = KEY_UP;
|
|
gKeyRight = KEY_RIGHT;
|
|
gKeyDown = KEY_DOWN;
|
|
break;
|
|
|
|
case 1:
|
|
gKeyLeft = KEY_ALT_LEFT;
|
|
gKeyUp = KEY_ALT_UP;
|
|
gKeyRight = KEY_ALT_RIGHT;
|
|
gKeyDown = KEY_ALT_DOWN;
|
|
break;
|
|
}
|
|
|
|
// Set gamepad inputs
|
|
for (i = 0; i < 8; ++i)
|
|
{
|
|
switch (conf.joystick_button[i])
|
|
{
|
|
case 1:
|
|
gJoystickButtonTable[i] = gKeyJump;
|
|
break;
|
|
|
|
case 2:
|
|
gJoystickButtonTable[i] = gKeyShot;
|
|
break;
|
|
|
|
case 3:
|
|
gJoystickButtonTable[i] = gKeyArms;
|
|
break;
|
|
|
|
case 6:
|
|
gJoystickButtonTable[i] = gKeyArmsRev;
|
|
break;
|
|
|
|
case 4:
|
|
gJoystickButtonTable[i] = gKeyItem;
|
|
break;
|
|
|
|
case 5:
|
|
gJoystickButtonTable[i] = gKeyMap;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RECT unused_rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
|
|
|
WNDCLASSEXA wndclassex;
|
|
memset(&wndclassex, 0, sizeof(WNDCLASSEXA));
|
|
wndclassex.cbSize = sizeof(WNDCLASSEXA);
|
|
wndclassex.lpfnWndProc = WindowProcedure;
|
|
wndclassex.hInstance = hInstance;
|
|
wndclassex.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH); // This is what gives the window's undrawn regions its grey colour
|
|
wndclassex.lpszClassName = lpWindowName;
|
|
wndclassex.hCursor = LoadCursorA(hInstance, "CURSOR_NORMAL");
|
|
wndclassex.hIcon = LoadIconA(hInstance, "0");
|
|
wndclassex.hIconSm = LoadIconA(hInstance, "ICON_MINI");
|
|
|
|
HWND hWnd;
|
|
HMENU hMenu;
|
|
int nWidth;
|
|
int nHeight;
|
|
int x;
|
|
int y;
|
|
|
|
switch (conf.display_mode)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
wndclassex.lpszMenuName = "MENU_MAIN";
|
|
|
|
if (RegisterClassExA(&wndclassex) == 0)
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
return 0;
|
|
}
|
|
|
|
// Set window dimensions
|
|
if (conf.display_mode == 1)
|
|
{
|
|
windowWidth = WINDOW_WIDTH;
|
|
windowHeight = WINDOW_HEIGHT;
|
|
}
|
|
else
|
|
{
|
|
windowWidth = WINDOW_WIDTH * 2;
|
|
windowHeight = WINDOW_HEIGHT * 2;
|
|
}
|
|
|
|
nWidth = (GetSystemMetrics(SM_CXFIXEDFRAME) * 2) + windowWidth + 2;
|
|
nHeight = (GetSystemMetrics(SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU) + windowHeight + 2;
|
|
x = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2;
|
|
y = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;
|
|
|
|
SetWindowPadding(GetSystemMetrics(SM_CXFIXEDFRAME) + 1, GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU) + 1);
|
|
|
|
hWnd = CreateWindowExA(WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, lpWindowName, lpWindowName, WS_MINIMIZEBOX | WS_SYSMENU | WS_BORDER | WS_DLGFRAME | WS_VISIBLE, x, y, nWidth, nHeight, NULL, NULL, hInstance, NULL);
|
|
ghWnd = hWnd;
|
|
|
|
if (hWnd == NULL)
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
return 0;
|
|
}
|
|
|
|
hMenu = GetMenu(hWnd);
|
|
|
|
if (conf.display_mode == 1)
|
|
StartDirectDraw(hWnd, 0, 0);
|
|
else
|
|
StartDirectDraw(hWnd, 1, 0);
|
|
|
|
break;
|
|
|
|
case 0:
|
|
case 3:
|
|
case 4:
|
|
if (RegisterClassExA(&wndclassex) == 0)
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
return 0;
|
|
}
|
|
|
|
// Set window dimensions
|
|
windowWidth = WINDOW_WIDTH * 2;
|
|
windowHeight = WINDOW_HEIGHT * 2;
|
|
|
|
SetWindowPadding(0, 0);
|
|
|
|
hWnd = CreateWindowExA(WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, lpWindowName, lpWindowName, WS_SYSMENU | WS_VISIBLE | WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
|
|
ghWnd = hWnd;
|
|
|
|
if (hWnd == NULL)
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
return 0;
|
|
}
|
|
|
|
// Set colour depth
|
|
int depth;
|
|
|
|
switch (conf.display_mode)
|
|
{
|
|
case 0:
|
|
depth = 16;
|
|
break;
|
|
case 3:
|
|
depth = 24;
|
|
break;
|
|
case 4:
|
|
depth = 32;
|
|
break;
|
|
}
|
|
|
|
StartDirectDraw(hWnd, 2, depth);
|
|
bFullscreen = TRUE;
|
|
|
|
ShowCursor(FALSE);
|
|
break;
|
|
}
|
|
|
|
// Set rects
|
|
RECT rcLoading = {0, 0, 64, 8};
|
|
RECT rcFull = {0, 0, 0, 0};
|
|
rcFull.right = WINDOW_WIDTH;
|
|
rcFull.bottom = WINDOW_HEIGHT;
|
|
|
|
// Load the "LOADING" text
|
|
BOOL b = MakeSurface_File("Loading", SURFACE_ID_LOADING);
|
|
|
|
// Draw loading screen
|
|
CortBox(&rcFull, 0x000000);
|
|
PutBitmap3(&rcFull, (WINDOW_WIDTH / 2) - 32, (WINDOW_HEIGHT / 2) - 4, &rcLoading, SURFACE_ID_LOADING);
|
|
|
|
// Draw to screen
|
|
if (!Flip_SystemTask(ghWnd))
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
return 1;
|
|
}
|
|
|
|
// Initialize sound
|
|
InitDirectSound(hWnd);
|
|
|
|
// Initialize joystick
|
|
if (conf.bJoystick && InitDirectInput(hInstance, hWnd))
|
|
{
|
|
ResetJoystickStatus();
|
|
gbUseJoystick = TRUE;
|
|
}
|
|
|
|
// Initialize stuff
|
|
InitTextObject(conf.font_name);
|
|
InitTriangleTable();
|
|
|
|
// Run game code
|
|
Game(hWnd);
|
|
|
|
// End stuff
|
|
EndTextObject();
|
|
EndDirectSound();
|
|
EndDirectDraw(hWnd);
|
|
|
|
ReleaseMutex(hMutex);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void InactiveWindow(void)
|
|
{
|
|
if (bActive)
|
|
{
|
|
bActive = FALSE;
|
|
StopOrganyaMusic();
|
|
SleepNoise();
|
|
}
|
|
|
|
PlaySoundObject(7, 0);
|
|
}
|
|
|
|
void ActiveWindow(void)
|
|
{
|
|
if (!bActive)
|
|
{
|
|
bActive = TRUE;
|
|
StopOrganyaMusic();
|
|
PlayOrganyaMusic();
|
|
ResetNoise();
|
|
}
|
|
|
|
PlaySoundObject(7, -1);
|
|
}
|
|
|
|
// Turns out you could drag-and-drop a save file onto the
|
|
// window to load it, but this behavior is dummied-out.
|
|
BOOL DragAndDropHandler(HWND hWnd, WPARAM wParam)
|
|
{
|
|
char path[MAX_PATH];
|
|
HDROP hDrop = (HDROP)wParam;
|
|
|
|
if (DragQueryFileA(hDrop, 0xFFFFFFFF, NULL, 0) != 0)
|
|
{
|
|
DragQueryFileA(hDrop, 0, path, sizeof(path));
|
|
LoadProfile(path);
|
|
}
|
|
|
|
DragFinish(hDrop);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LRESULT __stdcall WindowProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL window_focus;
|
|
HMENU hMenu;
|
|
|
|
switch (Msg)
|
|
{
|
|
case WM_CREATE:
|
|
hMenu = GetMenu(hWnd);
|
|
#ifdef DEBUG_SAVE
|
|
if (!CheckFileExists("save")) // Chances are a line like this used to exist
|
|
#endif
|
|
DeleteMenu(hMenu, 40005, MF_BYCOMMAND);
|
|
DrawMenuBar(hWnd);
|
|
|
|
hMenu = GetMenu(hWnd);
|
|
if (!CheckFileExists("mute"))
|
|
DeleteMenu(hMenu, 40007, MF_BYCOMMAND);
|
|
DrawMenuBar(hWnd);
|
|
|
|
if (CheckFileExists("fps"))
|
|
bFps = TRUE;
|
|
|
|
if (!bFullscreen)
|
|
LoadWindowRect(hWnd, "window.rect", FALSE);
|
|
|
|
SetWindowName(hWnd);
|
|
|
|
#ifdef DEBUG_SAVE
|
|
DragAcceptFiles(hWnd, TRUE);
|
|
#endif
|
|
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
switch (wParam)
|
|
{
|
|
case SC_MONITORPOWER:
|
|
break;
|
|
|
|
case SC_KEYMENU:
|
|
break;
|
|
|
|
case SC_SCREENSAVE:
|
|
break;
|
|
|
|
default:
|
|
DefWindowProcA(hWnd, Msg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_IME_NOTIFY:
|
|
if (wParam == IMN_SETOPENSTATUS)
|
|
{
|
|
HIMC hImc = ImmGetContext(hWnd);
|
|
ImmSetOpenStatus(hImc, 0);
|
|
ImmReleaseContext(hWnd, hImc);
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
switch (wParam)
|
|
{
|
|
case VK_ESCAPE:
|
|
gKey |= KEY_ESCAPE;
|
|
break;
|
|
|
|
case 'W':
|
|
gKey |= KEY_MAP;
|
|
break;
|
|
|
|
case VK_LEFT:
|
|
gKey |= KEY_LEFT;
|
|
break;
|
|
|
|
case VK_RIGHT:
|
|
gKey |= KEY_RIGHT;
|
|
break;
|
|
|
|
case VK_UP:
|
|
gKey |= KEY_UP;
|
|
break;
|
|
|
|
case VK_DOWN:
|
|
gKey |= KEY_DOWN;
|
|
break;
|
|
|
|
case 'X':
|
|
gKey |= KEY_X;
|
|
break;
|
|
|
|
case 'Z':
|
|
gKey |= KEY_Z;
|
|
break;
|
|
|
|
case 'S':
|
|
gKey |= KEY_ARMS;
|
|
break;
|
|
|
|
case 'A':
|
|
gKey |= KEY_ARMSREV;
|
|
break;
|
|
|
|
case VK_SHIFT:
|
|
gKey |= KEY_SHIFT;
|
|
break;
|
|
|
|
case VK_F1:
|
|
gKey |= KEY_F1;
|
|
break;
|
|
|
|
case VK_F2:
|
|
gKey |= KEY_F2;
|
|
break;
|
|
|
|
case 'Q':
|
|
gKey |= KEY_ITEM;
|
|
break;
|
|
|
|
case VK_OEM_COMMA:
|
|
gKey |= KEY_ALT_LEFT;
|
|
break;
|
|
|
|
case VK_OEM_PERIOD:
|
|
gKey |= KEY_ALT_DOWN;
|
|
break;
|
|
|
|
case VK_OEM_2:
|
|
gKey |= KEY_ALT_RIGHT;
|
|
break;
|
|
|
|
case 'L':
|
|
gKey |= KEY_L;
|
|
break;
|
|
|
|
case VK_OEM_PLUS:
|
|
gKey |= KEY_PLUS;
|
|
break;
|
|
|
|
case VK_F5:
|
|
gbUseJoystick = FALSE;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_KEYUP:
|
|
switch (wParam)
|
|
{
|
|
case VK_ESCAPE:
|
|
gKey &= ~KEY_ESCAPE;
|
|
break;
|
|
|
|
case 'W':
|
|
gKey &= ~KEY_MAP;
|
|
break;
|
|
|
|
case VK_LEFT:
|
|
gKey &= ~KEY_LEFT;
|
|
break;
|
|
|
|
case VK_RIGHT:
|
|
gKey &= ~KEY_RIGHT;
|
|
break;
|
|
|
|
case VK_UP:
|
|
gKey &= ~KEY_UP;
|
|
break;
|
|
|
|
case VK_DOWN:
|
|
gKey &= ~KEY_DOWN;
|
|
break;
|
|
|
|
case 'X':
|
|
gKey &= ~KEY_X;
|
|
break;
|
|
|
|
case 'Z':
|
|
gKey &= ~KEY_Z;
|
|
break;
|
|
|
|
case 'S':
|
|
gKey &= ~KEY_ARMS;
|
|
break;
|
|
|
|
case 'A':
|
|
gKey &= ~KEY_ARMSREV;
|
|
break;
|
|
|
|
case VK_SHIFT:
|
|
gKey &= ~KEY_SHIFT;
|
|
break;
|
|
|
|
case VK_F1:
|
|
gKey &= ~KEY_F1;
|
|
break;
|
|
|
|
case VK_F2:
|
|
gKey &= ~KEY_F2;
|
|
break;
|
|
|
|
case 'Q':
|
|
gKey &= ~KEY_ITEM;
|
|
break;
|
|
|
|
case VK_OEM_COMMA:
|
|
gKey &= ~KEY_ALT_LEFT;
|
|
break;
|
|
|
|
case VK_OEM_PERIOD:
|
|
gKey &= ~KEY_ALT_DOWN;
|
|
break;
|
|
|
|
case VK_OEM_2:
|
|
gKey &= ~KEY_ALT_RIGHT;
|
|
break;
|
|
|
|
case 'L':
|
|
gKey &= ~KEY_L;
|
|
break;
|
|
|
|
case VK_OEM_PLUS:
|
|
gKey &= ~KEY_PLUS;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case 40001:
|
|
if (DialogBoxParamA(ghInstance, "DLG_YESNO", hWnd, QuitDialog, (LPARAM)"Quit?") == 1)
|
|
PostMessageA(hWnd, WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case 40002:
|
|
DialogBoxParamA(ghInstance, "DLG_ABOUT", hWnd, VersionDialog, 0);
|
|
break;
|
|
|
|
case 40004:
|
|
if (!OpenVolumeConfiguration(hWnd))
|
|
MessageBoxA(hWnd, "\x83\x7B\x83\x8A\x83\x85\x81\x5B\x83\x80\x90\xDD\x92\xE8\x82\xF0\x8B\x4E\x93\xAE\x82\xC5\x82\xAB\x82\xDC\x82\xB9\x82\xF1\x82\xC5\x82\xB5\x82\xBD", lpWindowName, 0); // 'ボリューム設定を起動できませんでした' (Could not launch volume configuration) in Shift-JIS
|
|
break;
|
|
|
|
case 40005:
|
|
DialogBoxParamA(ghInstance, "DLG_SAVE", hWnd, DebugSaveDialog, 0);
|
|
break;
|
|
|
|
case 40007:
|
|
DialogBoxParamA(ghInstance, "DLG_MUTE", hWnd, DebugMuteDialog, 0);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_DROPFILES:
|
|
DragAndDropHandler(hWnd, wParam);
|
|
break;
|
|
|
|
case WM_ACTIVATE:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case WA_INACTIVE:
|
|
window_focus = FALSE;
|
|
break;
|
|
|
|
case WA_ACTIVE:
|
|
case WA_CLICKACTIVE:
|
|
if (HIWORD(wParam) != 0)
|
|
window_focus = FALSE;
|
|
else
|
|
window_focus = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
if (window_focus)
|
|
ActiveWindow();
|
|
else
|
|
InactiveWindow();
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
StopOrganyaMusic();
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void JoystickProc(void);
|
|
|
|
BOOL SystemTask(void)
|
|
{
|
|
MSG Msg;
|
|
|
|
while (PeekMessageA(&Msg, NULL, 0, 0, PM_NOREMOVE) || !bActive)
|
|
{
|
|
if (!GetMessageA(&Msg, NULL, 0, 0))
|
|
return FALSE;
|
|
|
|
TranslateMessage(&Msg);
|
|
DispatchMessageA(&Msg);
|
|
}
|
|
|
|
// Run joystick code
|
|
if (gbUseJoystick)
|
|
JoystickProc();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void JoystickProc(void)
|
|
{
|
|
int i;
|
|
JOYSTICK_STATUS status;
|
|
|
|
if (!GetJoystickStatus(&status))
|
|
return;
|
|
|
|
gKey &= (KEY_ESCAPE | KEY_F2 | KEY_F1);
|
|
|
|
// Set movement buttons
|
|
if (status.bLeft)
|
|
gKey |= gKeyLeft;
|
|
else
|
|
gKey &= ~gKeyLeft;
|
|
|
|
if (status.bRight)
|
|
gKey |= gKeyRight;
|
|
else
|
|
gKey &= ~gKeyRight;
|
|
|
|
if (status.bUp)
|
|
gKey |= gKeyUp;
|
|
else
|
|
gKey &= ~gKeyUp;
|
|
|
|
if (status.bDown)
|
|
gKey |= gKeyDown;
|
|
else
|
|
gKey &= ~gKeyDown;
|
|
|
|
// Clear held buttons
|
|
for (i = 0; i < 8; ++i)
|
|
gKey &= ~gJoystickButtonTable[i];
|
|
|
|
// Set held buttons
|
|
for (i = 0; i < 8; ++i)
|
|
if (status.bButton[i])
|
|
gKey |= gJoystickButtonTable[i];
|
|
}
|