ref: 02133ba1afbdf4af9b8c509faae6b3429762528c
dir: /src/Main.cpp/
#include <stddef.h> #include "Types.h" #include "CommonDefines.h" #include <stdint.h> #include <string> #include <SDL.h> #include "WindowsWrapper.h" #include "Draw.h" #include "Input.h" #include "Profile.h" #include "Organya.h" #include "Sound.h" #include "Game.h" #include "Generic.h" #include "MyChar.h" #include "Main.h" #include "Config.h" #include "KeyControl.h" #include "Triangle.h" #include "Resource.h" char gModulePath[PATH_LENGTH]; char gDataPath[PATH_LENGTH]; int gJoystickButtonTable[8]; int gWindowWidth; int gWindowHeight; int gWindowScale; SDL_Window *gWindow; SDL_Renderer *gRenderer; bool gbUseJoystick = false; bool bFullscreen = false; bool bFps = false; bool bActive = true; #ifdef JAPANESE const char *lpWindowName = "洞窟物語エンジン2"; #else const char *lpWindowName = "Cave Story Engine 2 ~ Doukutsu Monogatari Enjin 2"; #endif void PutFramePerSecound() { if (bFps) PutNumber4(WINDOW_WIDTH - 40, 8, GetFramePerSecound(), false); } int GetFramePerSecound() { unsigned int current_tick; static bool need_new_base_tick = true; static int frames_this_second; static int current_frame; static int base_tick; if (need_new_base_tick) { base_tick = SDL_GetTicks(); need_new_base_tick = false; } current_tick = SDL_GetTicks(); ++current_frame; if ( base_tick + 1000 <= current_tick ) { base_tick += 1000; frames_this_second = current_frame; current_frame = 0; } return frames_this_second; } int main(int argc, char *argv[]) { //Get executable's path strcpy(gModulePath, SDL_GetBasePath()); if (gModulePath[strlen(gModulePath) - 1] == '/' || gModulePath[strlen(gModulePath) - 1] == '\\') gModulePath[strlen(gModulePath) - 1] = 0; //String cannot end in slash or stuff will probably break (original does this through a windows.h provided function) //Get path of the data folder strcpy(gDataPath, gModulePath); memcpy(&gDataPath[strlen(gDataPath)], "/data", 6); //Pixel didn't use a strcat //Initialize SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) >= 0) { //Load configuration CONFIG config; if (!LoadConfigData(&config)) DefaultConfigData(&config); //Apply keybinds //Swap X and Z buttons if (config.attack_button_mode) { if (config.attack_button_mode == 1) { gKeyJump = KEY_X; gKeyShot = KEY_Z; } } else { gKeyJump = KEY_Z; gKeyShot = KEY_X; } //Swap Okay and Cancel buttons if (config.ok_button_mode) { if (config.ok_button_mode == 1) { gKeyOk = gKeyShot; gKeyCancel = gKeyJump; } } else { gKeyOk = gKeyJump; gKeyCancel = gKeyShot; } //Swap left and right weapon switch keys if (CheckFileExists("s_reverse")) { gKeyArms = KEY_ARMSREV; gKeyArmsRev = KEY_ARMS; } //Alternate movement keys if (config.move_button_mode) { if (config.move_button_mode == 1) { gKeyLeft = KEY_ALT_LEFT; gKeyUp = KEY_ALT_UP; gKeyRight = KEY_ALT_RIGHT; gKeyDown = KEY_ALT_DOWN; } } else { gKeyLeft = KEY_LEFT; gKeyUp = KEY_UP; gKeyRight = KEY_RIGHT; gKeyDown = KEY_DOWN; } //Set gamepad inputs for (int i = 0; i < 8; i++) { switch (config.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; default: continue; } } RECT unused_rect = {0, 0, 320, 240}; //Get window dimensions and colour depth int colourDepth = 16; switch (config.display_mode) { case 1: case 2: //Set window dimensions if (config.display_mode == 1) { gWindowWidth = WINDOW_WIDTH; gWindowHeight = WINDOW_HEIGHT; gWindowScale = 1; } else { gWindowWidth = WINDOW_WIDTH * 2; gWindowHeight = WINDOW_HEIGHT * 2; gWindowScale = 2; } break; case 0: case 3: case 4: //Set window dimensions gWindowWidth = WINDOW_WIDTH * 2; gWindowHeight = WINDOW_HEIGHT * 2; gWindowScale = 2; //Set colour depth if (config.display_mode) { if (config.display_mode == 3) colourDepth = 24; else if (config.display_mode == 4) colourDepth = 32; } else colourDepth = 16; bFullscreen = true; SDL_ShowCursor(0); break; } //Create window gWindow = SDL_CreateWindow(lpWindowName, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, gWindowWidth, gWindowHeight, bFullscreen ? SDL_WINDOW_FULLSCREEN : 0); if (gWindow) { //Initialize rendering StartDirectDraw(); //Check debug things if (CheckFileExists("fps")) bFps = true; //Load icon SDL_RWops *fp = FindResource("ICON4"); if (fp) { SDL_Surface *iconSurf = SDL_LoadBMP_RW(fp, 1); SDL_Surface *iconConverted = SDL_ConvertSurfaceFormat(iconSurf, SDL_PIXELFORMAT_RGB888, 0); SDL_FreeSurface(iconSurf); SDL_Surface *iconSurfUpscaled = SDL_CreateRGBSurfaceWithFormat(0, 256, 256, 0, SDL_PIXELFORMAT_RGB888); SDL_LowerBlitScaled(iconConverted, NULL, iconSurfUpscaled, NULL); SDL_FreeSurface(iconConverted); SDL_SetWindowIcon(gWindow, iconSurfUpscaled); SDL_FreeSurface(iconSurfUpscaled); } else { printf("Failed to load icon"); } //Set rects RECT loading_rect = {0, 0, 64, 8}; RECT clip_rect = {0, 0, gWindowWidth, gWindowHeight}; //Load the "LOADING" text MakeSurface_File("Loading", SURFACE_ID_LOADING); //Draw loading screen CortBox(&clip_rect, 0x000000); PutBitmap3(&clip_rect, (WINDOW_WIDTH - 64) / 2, (WINDOW_HEIGHT - 8) / 2, &loading_rect, SURFACE_ID_LOADING); //Draw to screen if (Flip_SystemTask()) { //Initialize sound InitDirectSound(); //Initialize joystick if (config.bJoystick && InitDirectInput()) { ResetJoystickStatus(); gbUseJoystick = true; } //Initialize stuff InitTextObject(config.font_name); InitTriangleTable(); //Run game code Game(); //End stuff EndDirectSound(); EndTextObject(); EndDirectDraw(); SDL_Quit(); } } } else { return -1; } return 0; } void InactiveWindow() { if (bActive) { bActive = false; StopOrganyaMusic(); SleepNoise(); } PlaySoundObject(7, 0); } void ActiveWindow() { if (!bActive) { bActive = true; StopOrganyaMusic(); PlayOrganyaMusic(); ResetNoise(); } PlaySoundObject(7, -1); } void JoystickProc() { JOYSTICK_STATUS status; if (GetJoystickStatus(&status)) { //Clear held buttons gKey &= (KEY_ESCAPE | KEY_F2 | KEY_F1); //Set movement buttons if (status.bLeft) gKey |= gKeyLeft; if (status.bRight) gKey |= gKeyRight; if (status.bUp) gKey |= gKeyUp; if (status.bDown) gKey |= gKeyDown; //Set held buttons for (int i = 0; i < 8; i++) { if (status.bButton[i]) gKey |= gJoystickButtonTable[i]; } } } bool SystemTask() { //Handle window events bool focusGained = true; while (SDL_PollEvent(nullptr) || !focusGained) { SDL_Event event; SDL_WaitEvent(&event); switch (event.type) { case SDL_QUIT: return false; break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_FOCUS_GAINED: focusGained = true; ActiveWindow(); break; case SDL_WINDOWEVENT_FOCUS_LOST: focusGained = false; InactiveWindow(); break; default: break; } break; case SDL_DROPFILE: LoadProfile(event.drop.file); SDL_free(event.drop.file); break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: gKey |= KEY_ESCAPE; break; case SDLK_w: gKey |= KEY_MAP; break; case SDLK_LEFT: gKey |= KEY_LEFT; break; case SDLK_RIGHT: gKey |= KEY_RIGHT; break; case SDLK_UP: gKey |= KEY_UP; break; case SDLK_DOWN: gKey |= KEY_DOWN; break; case SDLK_x: gKey |= KEY_X; break; case SDLK_z: gKey |= KEY_Z; break; case SDLK_s: gKey |= KEY_ARMS; break; case SDLK_a: gKey |= KEY_ARMSREV; break; case SDLK_RSHIFT: case SDLK_LSHIFT: gKey |= KEY_SHIFT; break; case SDLK_F1: gKey |= KEY_F1; break; case SDLK_F2: gKey |= KEY_F2; break; case SDLK_q: gKey |= KEY_ITEM; break; case SDLK_COMMA: gKey |= KEY_ALT_LEFT; break; case SDLK_PERIOD: gKey |= KEY_ALT_DOWN; break; case SDLK_SLASH: gKey |= KEY_ALT_RIGHT; break; case SDLK_l: gKey |= KEY_ALT_UP; break; #ifdef FIX_BUGS //BUG FIX: Pixel intended for the second alternate up key to be the plus key, Japanese keyboards have the plus key where the semi-colon key is, causing errors on other keyboard layouts) case SDLK_PLUS: #else case SDLK_SEMICOLON: #endif gKey |= KEY_PLUS; break; case SDLK_F5: gbUseJoystick = false; break; default: break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_ESCAPE: gKey &= ~KEY_ESCAPE; break; case SDLK_w: gKey &= ~KEY_MAP; break; case SDLK_LEFT: gKey &= ~KEY_LEFT; break; case SDLK_RIGHT: gKey &= ~KEY_RIGHT; break; case SDLK_UP: gKey &= ~KEY_UP; break; case SDLK_DOWN: gKey &= ~KEY_DOWN; break; case SDLK_x: gKey &= ~KEY_X; break; case SDLK_z: gKey &= ~KEY_Z; break; case SDLK_s: gKey &= ~KEY_ARMS; break; case SDLK_a: gKey &= ~KEY_ARMSREV; break; case SDLK_RSHIFT: case SDLK_LSHIFT: gKey &= ~KEY_SHIFT; break; case SDLK_F1: gKey &= ~KEY_F1; break; case SDLK_F2: gKey &= ~KEY_F2; break; case SDLK_q: gKey &= ~KEY_ITEM; break; case SDLK_COMMA: gKey &= ~KEY_ALT_LEFT; break; case SDLK_PERIOD: gKey &= ~KEY_ALT_DOWN; break; case SDLK_SLASH: gKey &= ~KEY_ALT_RIGHT; break; case SDLK_l: gKey &= ~KEY_ALT_UP; break; #ifdef FIX_BUGS //BUG FIX: Pixel intended for the second alternate up key to be the plus key, Japanese keyboards have the plus key where the semi-colon key is, causing errors on other keyboard layouts) case SDLK_PLUS: #else case SDLK_SEMICOLON: #endif gKey &= ~KEY_PLUS; break; default: break; } break; } } //Run joystick code if (gbUseJoystick) JoystickProc(); return true; }