diff options
-rw-r--r-- | src/Frontend.cpp | 1475 | ||||
-rw-r--r-- | src/Frontend.h | 177 | ||||
-rw-r--r-- | src/PCSave.cpp | 5 | ||||
-rw-r--r-- | src/PCSave.h | 9 | ||||
-rw-r--r-- | src/Radar.cpp | 1068 | ||||
-rw-r--r-- | src/Radar.h | 55 | ||||
-rw-r--r-- | src/audio/DMAudio.cpp | 2 | ||||
-rw-r--r-- | src/audio/DMAudio.h | 2 | ||||
-rw-r--r-- | src/audio/MusicManager.cpp | 2 | ||||
-rw-r--r-- | src/audio/MusicManager.h | 1 | ||||
-rw-r--r-- | src/config.h | 1 | ||||
-rw-r--r-- | src/control/Garages.cpp | 14 | ||||
-rw-r--r-- | src/control/Replay.cpp | 20 | ||||
-rw-r--r-- | src/main.cpp | 22 | ||||
-rw-r--r-- | src/render/Font.h | 24 | ||||
-rw-r--r-- | src/render/Hud.cpp | 43 | ||||
-rw-r--r-- | src/render/Hud.h | 6 | ||||
-rw-r--r-- | src/skel/win/win.cpp | 6 | ||||
-rw-r--r-- | src/skel/win/win.h | 2 |
19 files changed, 2436 insertions, 498 deletions
diff --git a/src/Frontend.cpp b/src/Frontend.cpp index b8ee10f4..9b0e185d 100644 --- a/src/Frontend.cpp +++ b/src/Frontend.cpp @@ -1,6 +1,24 @@ +#define DIRECTINPUT_VERSION 0x0800 +#include <dinput.h> #include "common.h" #include "patcher.h" +#include "win.h" #include "Frontend.h" +#include "Font.h" +#include "Pad.h" +#include "Text.h" +#include "main.h" +#include "Timer.h" +#include "Game.h" +#include "DMAudio.h" +#include "MusicManager.h" +#include "FileMgr.h" +#include "Streaming.h" +#include "TxdStore.h" +#include "General.h" +#include "PCSave.h" +#include "Script.h" +#include "Camera.h" int32 &CMenuManager::OS_Language = *(int32*)0x5F2F78; int8 &CMenuManager::m_PrefsUseVibration = *(int8*)0x95CD92; @@ -17,6 +35,7 @@ int8 &CMenuManager::m_PrefsLanguage = *(int8*)0x941238; bool &CMenuManager::m_PrefsAllowNastyGame = *(bool*)0x5F2E64; bool &CMenuManager::m_bStartUpFrontEndRequested = *(bool*)0x95CCF4; +bool &CMenuManager::m_bShutDownFrontEndRequested = *(bool*)0x95CD6A; int8 &CMenuManager::m_PrefsUseWideScreen = *(int8*)0x95CD23; int8 &CMenuManager::m_PrefsRadioStation = *(int8*)0x95CDA4; @@ -29,14 +48,1135 @@ int32 &CMenuManager::m_PrefsSfxVolume = *(int32*)0x5F2E48; CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8; -WRAPPER void CMenuManager::Process(void) { EAXJMP(0x485100); } +const CMenuScreen aScreens[] = { + // MENU_PAGE_NONE = 0 + { "", -1, -1, 1, 0, 0, }, + + // MENU_PAGE_STATS = 1 + { "FET_STA", 0, 0, 0, 5, 2, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_NEW_GAME = 2 + { "FET_SGA", 0, 0, 0, 0, 1, + 2, "FES_SNG", 0, 10, + 22, "GMLOAD", 0, 8, + 2, "FES_DGA", 0, 9, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_BRIEFS = 3 + { "FET_BRE", 0, 0, 0, 6, 3, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_CONTROLLER_SETTINGS = 4 + { "FET_CON", 41, 41, 41, 0, 0, + + }, + + // MENU_PAGE_SOUND_SETTINGS = 5 + { "FET_AUD", 41, 41, 41, 1, 1, + 13, "FEA_MUS", 0, 5, + 14, "FEA_SFX", 0, 5, + 95, "FEA_3DH", 0, 5, + 96, "FEA_SPK", 0, 5, + 100, "FET_DAM", 0, 5, + 16, "FEA_RSS", 0, 5, + 98, "FET_DEF", 0, 5, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_GRAPHICS_SETTINGS = 6 + { "FET_DIS", 41, 41, 41, 2, 2, + 11, "FED_BRI", 0, 6, + 12, "FEM_LOD", 0, 6, + 6, "FEM_VSC", 0, 6, + 7, "FEM_FRM", 0, 6, + 8, "FED_TRA", 0, 6, + 9, "FED_SUB", 0, 6, + 10, "FED_WIS", 0, 6, + 94, "FED_RES", 0, 6, + 98, "FET_DEF", 0, 6, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_LANGUAGE_SETTINGS = 7 + { "FET_LAN", 41, 41, 41, 3, 3, + 17, "FEL_ENG", 0, 7, + 18, "FEL_FRE", 0, 7, + 19, "FEL_GER", 0, 7, + 20, "FEL_ITA", 0, 7, + 21, "FEL_SPA", 0, 7, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_CHOOSE_LOAD_SLOT = 8 + { "FET_LG", 2, 2, 2, 1, 1, + 2, "FESZ_CA", 0, 2, + 23, "FEM_SL1", 2, 11, + 23, "FEM_SL2", 3, 11, + 23, "FEM_SL3", 4, 11, + 23, "FEM_SL4", 5, 11, + 23, "FEM_SL5", 6, 11, + 23, "FEM_SL6", 7, 11, + 23, "FEM_SL7", 8, 11, + 23, "FEM_SL8", 9, 11, + }, + + // MENU_PAGE_CHOOSE_DELETE_SLOT = 9 + { "FET_DG", 2, 2, 2, 2, 2, + 2, "FESZ_CA", 0, 2, + 2, "FEM_SL1", 2, 12, + 2, "FEM_SL2", 3, 12, + 2, "FEM_SL3", 4, 12, + 2, "FEM_SL4", 5, 12, + 2, "FEM_SL5", 6, 12, + 2, "FEM_SL6", 7, 12, + 2, "FEM_SL7", 8, 12, + 2, "FEM_SL8", 9, 12, + }, + + // MENU_PAGE_NEW_GAME_RELOAD = 10 + { "FET_NG", 2, 2, 2, 0, 0, + 1, "FESZ_QR", 0, 0, + 2, "FEM_NO", 0, 2, + 25, "FEM_YES", 0, 10, + }, + + // MENU_PAGE_LOAD_SLOT_CONFIRM = 11 + { "FET_LG", 8, 8, 8, 0, 0, + 1, "FESZ_QL", 0, 0, + 2, "FEM_NO", 0, 8, + 2, "FEM_YES", 0, 14, + }, + + // MENU_PAGE_DELETE_SLOT_CONFIRM = 12 + { "FET_DG", 9, 9, 9, 0, 0, + 1, "FESZ_QD", 0, 0, + 2, "FEM_NO", 0, 9, + 2, "FEM_YES", 0, 45, + }, + + // MENU_PAGE_13 = 13 + { "FES_NOC", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_LOADING_IN_PROGRESS = 14 + { "FET_LG", -1, -1, -1, 0, 0, + 1, "FED_LDW", 0, 11, + }, + + // MENU_PAGE_DELETING_IN_PROGRESS = 15 + { "FET_DG", -1, -1, -1, 0, 0, + 1, "FEDL_WR", 0, 0, + }, + + // MENU_PAGE_16 = 16 + { "FET_LG", -1, -1, -1, 0, 0, + 1, "FES_LOE", 0, 0, + }, + + // MENU_PAGE_DELETE_FAILED = 17 + { "FET_DG", -1, -1, -1, 0, 0, + 1, "FES_DEE", 0, 0, + 2, "FEC_OKK", 0, 9, + }, + + // MENU_PAGE_DEBUG_MENU = 18 + { "FED_DBG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MEMORY_CARD_1 = 19 + { "FEM_MCM", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MEMORY_CARD_2 = 20 + { "FEM_MC2", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_MAIN = 21 + { "FET_MP", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_SAVE_FAILED_1 = 22 + { "MCDNSP", -1, -1, -1, 0, 0, + 48, "JAILB_U", 0, 0, + }, + + // MENU_PAGE_SAVE_FAILED_2 = 23 + { "MCGNSP", -1, -1, -1, 0, 0, + 48, "JAILB_U", 0, 0, + }, + + // MENU_PAGE_SAVE = 24 + { "FET_SG", -1, -1, -1, 0, 0, + 1, "FES_SCG", 0, 0, + 22, "GMSAVE", 0, 26, + 49, "FESZ_CA", 0, 0, + }, + + // MENU_PAGE_NO_MEMORY_CARD = 25 + { "FES_NOC", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CHOOSE_SAVE_SLOT = 26 + { "FET_SG", -1, -1, -1, 0, 0, + 49, "FESZ_CA", 0, 0, + 2, "FEM_SL1", 2, 27, + 2, "FEM_SL2", 3, 27, + 2, "FEM_SL3", 4, 27, + 2, "FEM_SL4", 5, 27, + 2, "FEM_SL5", 6, 27, + 2, "FEM_SL6", 7, 27, + 2, "FEM_SL7", 8, 27, + 2, "FEM_SL8", 9, 27, + }, + + // MENU_PAGE_SAVE_OVERWRITE_CONFIRM = 27 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FESZ_QO", 0, 0, + 2, "FEM_YES", 0, 43, + 2, "FEM_NO", 0, 26, + }, + + // MENU_PAGE_MULTIPLAYER_MAP = 28 + { "FET_MAP", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_CONNECTION = 29 + { "FET_CON", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_FIND_GAME = 30 + { "FET_FG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_MODE = 31 + { "FET_GT", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_CREATE = 32 + { "FET_HG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_START = 33 + { "FEN_STA", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_SKIN_SELECT_OLD = 34 + { "FET_PS", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC = 35 + { "FET_CTL", 41, 41, 41, 0, 0, + 99, "FET_CME", 0, 35, + 72, "FET_RDK", 0, 55, + 2, "FET_AMS", 0, 56, + 98, "FET_DEF", 0, 35, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_CONTROLLER_PC_OLD1 = 36 + { "FET_CTL", 35, 35, 35, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC_OLD2 = 37 + { "FET_CTL", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC_OLD3 = 38 + { "FET_CTL", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC_OLD4 = 39 + { "FET_CTL", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_DEBUG = 40 + { "FEC_DBG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_OPTIONS = 41 + { "FET_OPT", 0, 0, 0, 1, 4, + 2, "FET_CTL", 0, 35, + 101, "FET_AUD", 0, 5, + 2, "FET_DIS", 0, 6, + 2, "FET_LAN", 0, 7, + 97, "FET_PSU", 0, 54, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_EXIT = 42 + { "FET_QG", 0, 0, 0, 2, 5, + 1, "FEQ_SRE", 0, 0, + 93, "FEM_NO", 0, 0, + 82, "FEM_YES", 0, 0, + }, + + // MENU_PAGE_SAVING_IN_PROGRESS = 43 + { "", 26, 26, 26, 0, 0, + 1, "FES_WAR", 0, 0, + }, + + // MENU_PAGE_SAVE_SUCCESSFUL = 44 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FES_SSC", 36, 0, + 49, "FEC_OKK", 0, 26, + }, + + // MENU_PAGE_DELETING = 45 + { "FET_DG", 9, 9, 9, 0, 0, + 1, "FED_DLW", 0, 0, + }, + + // MENU_PAGE_DELETE_SUCCESS = 46 + { "FET_DG", 9, 9, 9, 0, 0, + 1, "DEL_FNM", 0, 0, + 2, "FEC_OKK", 0, 9, + }, + + // MENU_PAGE_SAVE_FAILED = 47 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FEC_SVU", 0, 0, + 2, "FEC_OKK", 0, 26, + }, + + // MENU_PAGE_LOAD_FAILED = 48 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FEC_SVU", 0, 0, + }, + + // MENU_PAGE_LOAD_FAILED_2 = 49 + { "FET_LG", 26, 26, 26, 0, 0, + 1, "FEC_LUN", 0, 0, + 2, "FEDS_TB", 0, 8, + }, + + // MENU_PAGE_FILTER_GAME = 50 + { "FIL_FLT", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_START_MENU = 51 + { "FEM_MM", -1, -1, -1, 0, 0, + 2, "FEN_STA", 0, 2, + 2, "FET_OPT", 0, 41, + 2, "FEM_QT", 0, 42 + }, + + // MENU_PAGE_PAUSE_MENU = 52 + { "FET_PAU", -1, -1, -1, 0, 0, + 92, "FEM_RES", 0, 0, + 2, "FEN_STA", 0, 2, + 2, "FEP_STA", 0, 1, + 2, "FEP_BRI", 0, 3, + 2, "FET_OPT", 0, 41, + 2, "FEM_QT", 0, 42, + }, + + // MENU_PAGE_CHOOSE_MODE = 53 + { "FEN_STA", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_SKIN_SELECT = 54 + { "FET_PSU", 41, 41, 41, 4, 4, + 35, "FEDS_TB", 0, 21, + }, + + // MENU_PAGE_KEYBOARD_CONTROLS = 55 + { "FET_STI", 35, 35, 35, 1, 1, + 35, "FEDS_TB", 0, 35, + }, + + // MENU_PAGE_MOUSE_CONTROLS = 56 + { "FET_MTI", 35, 35, 35, 2, 2, + 84, "FEC_MSH", 0, 35, + 81, "FEC_IVV", 0, 35, + 102, "FET_MST", 0, 35, + 2 , "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_57 = 57 + { "", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_58 = 58 + { "", -1, -1, -1, 0, 0, + + }, +}; + +char *FrontendFilenames[] = { + "fe2_mainpanel_ul", + "fe2_mainpanel_ur", + "fe2_mainpanel_dl", + "fe2_mainpanel_dr", + "fe2_mainpanel_dr2", + "fe2_tabactive", + "fe_iconbrief", + "fe_iconstats", + "fe_iconcontrols", + "fe_iconsave", + "fe_iconaudio", + "fe_icondisplay", + "fe_iconlanguage", + "fe_controller", + "fe_controllersh", + "fe_arrows1", + "fe_arrows2", + "fe_arrows3", + "fe_arrows4", + "fe_radio1", // HEAD_RADIO + "fe_radio2", // DOUBLE_CLEF + "fe_radio5", // JAH_RADIO + "fe_radio7", // RISE_FM + "fe_radio8", // LIPS_106 + "fe_radio3", // GAME_FM + "fe_radio4", // MSX_FM + "fe_radio6", // FLASHBACK + "fe_radio9", // CHATTERBOX +}; + +char *MenuFilenames[] = { + "connection24", + "findgame24", + "hostgame24", + "mainmenu24", + "playersetup24", + "singleplayer24", + "multiplayer24", + "dmalogo128", + "gtaLogo128", + "rockstarLogo128", + "gamespy256", + "mouse", + "mousetimer", + "mp3logo", + "downOFF", + "upOFF", + "downON", + "upON", + "gta3logo256", +}; + +#if 1 +WRAPPER void CMenuManager::BuildStatLine(char *, void *, uint16, void *) { EAXJMP(0x483870); } +#else +void CMenuManager::BuildStatLine(char *, void *, uint16, void *) +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::CentreMousePointer() { EAXJMP(0x48ACE0); } +#else +void CMenuManager::CentreMousePointer() +{ + tagPOINT Point; + + if (SCREENW * 0.5f == 0.0f && 0.0f == SCREENH * 0.5f) { + Point.x = SCREEN_WIDTH / 2; + Point.y = SCREEN_HEIGHT / 2; + ClientToScreen(PSGLOBAL(window), &Point); + SetCursorPos(Point.x, Point.y); + + PSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2; + PSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2; + } +} +#endif + +#if 1 +WRAPPER void CMenuManager::CheckCodesForControls(int, int) { EAXJMP(0x48A950); } +#else +void CMenuManager::CheckCodesForControls() +{ + +} +#endif + +#if 0 +WRAPPER bool CMenuManager::CheckHover(int, int, int, int) { EAXJMP(0x48ACA0); } +#else +bool CMenuManager::CheckHover(int x1, int x2, int y1, int y2) +{ + if (m_nMousePosX > x1 && m_nMousePosX < x2) { + if (m_nMousePosY > y1 && m_nMousePosY < y2) + return true; + } + return false; +} +#endif + +#if 1 +WRAPPER int CMenuManager::CostructStatLine(int) { EAXJMP(0x482800); } +#else +int CMenuManager::CostructStatLine(int) +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::DisplayHelperText() { EAXJMP(0x48B490); } +#else +void CMenuManager::DisplayHelperText() +{ + wchar *str = nullptr; + switch (m_nHelperTextMsgId) { + case 0: + str = TheText.Get("FET_MIG"); + break; + case 1: + str = TheText.Get("FET_APP"); + break; + case 2: + str = TheText.Get("FET_HRD"); + break; + case 3: + str = TheText.Get("FET_RSO"); + break; + case 4: + str = TheText.Get("FET_RSC"); + break; + default: + break; + }; + + CFont::SetAlignment(ALIGN_CENTER); + CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetDropColor(CRGBA(0, 0, 0, DROP_COLOR_A)); + CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_FROM_BOTTOM(120.0f), str); +} +#endif + +#if 0 +WRAPPER float CMenuManager::DisplaySlider(float, float, float, float, float, float) { EAXJMP(0x488420); } +#else +float CMenuManager::DisplaySlider(float x, float y, float leftSize, float rightSize, float rectSize, float progress) +{ + CRGBA color; + float sizeRange; + + float input = 0.0f; + int rects = 16; + for (int i = 0; i < rects; i++) { + input = i * rectSize * 0.0625f + x; + + if (i * 0.0625f + 0.03125f < progress) + color = CRGBA(255, 217, 106, FadeIn(255)); + else + color = CRGBA(185, 120, 0, FadeIn(255)); + + if (leftSize <= rightSize) + sizeRange = rightSize; + else + sizeRange = leftSize; + + float _x = i * rectSize * 0.0625f + x; + float _y = y + sizeRange - ((rects - i) * leftSize + i * rightSize) * 0.0625f; + float _w = SCREEN_SCALE_X(10.0f) + i * rectSize * 0.0625f + x; + float _h = y + sizeRange; + float _s = SCREEN_SCALE_X(2.0f); + CSprite2d::DrawRect(CRect(_x + _s, _y + _s, _w + _s, _h + _s), CRGBA(0, 0, 0, FadeIn(255))); // Shadow + CSprite2d::DrawRect(CRect(i * rectSize * 0.0625f + x, y + sizeRange - ((rects - i) * leftSize + i * rightSize) * 0.0625f, SCREEN_SCALE_X(10.0f) + i * rectSize * 0.0625f + x, y + sizeRange), color); + }; + return input; +} +#endif + +#if 1 +WRAPPER void CMenuManager::DoSettingsBeforeStartingAGame() { EAXJMP(0x48AB40); } +#else +WRAPPER void CMenuManager::DoSettingsBeforeStartingAGame() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::Draw() { EAXJMP(0x47AE00); } +#else +void CMenuManager::Draw() +{ + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetCentreOff(); + CFont::SetJustifyOn(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f)); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + + switch (m_nCurrScreen) { + case MENU_STATS: + PrintStats(); + break; + case MENU_BRIEFS: + PrintBriefs(); + break; + case MENU_CONTROLLER_DEBUG: + DrawControllerScreenExtraText(0, 350, 20); + break; + } + + // Header. + if (aScreens[m_nCurrScreen].m_ScreenName[0]) { + CFont::SetDropShadowPosition(0); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetRightJustifyOn(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetScale(SCREEN_SCALE_X(HEADER_WIDTH), SCREEN_SCALE_Y(HEADER_HEIGHT)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(HEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + } + + // Action text. + wchar *str; + if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == 1) { + switch (m_nCurrScreen) { + case MENU_LOAD_SLOT_CONFIRM: + if (m_bGameNotLoaded) + str = TheText.Get("FES_LCG"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + case MENU_SAVE_OVERWRITE_CONFIRM: + if (Slots[m_nCurrSaveSlot] == 1) + str = TheText.Get("FESZ_QZ"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + case MENU_EXIT: + if (m_bGameNotLoaded) + str = TheText.Get("FEQ_SRW"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + default: + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + }; + + CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetFontStyle(FONT_BANK); + CFont::SetScale(SCREEN_SCALE_X(ACTION_WIDTH), SCREEN_SCALE_Y(ACTION_HEIGHT)); + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_X(ACTION_POS_X), SCREEN_SCALE_Y(ACTION_POS_Y), str); + } + + for (int i = 0; i < 18; ++i) { + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != 1 && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0]) { + wchar *columnToPrint[COLUMNS] = { nullptr, nullptr }; + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot >= MENU_ACTION_SAVE_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot <= MENU_ACTION_SAVE_8) { + columnToPrint[L] = GetNameOfSavedGame(i - 1); + columnToPrint[R] = GetSavedGameDateAndTime(i - 1); + + if (!columnToPrint[L][0]) { + sprintf(gString, "FEM_SL%d", i); + columnToPrint[L] = TheText.Get(gString); + } + } + else { + columnToPrint[L] = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); + } + + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case 3: + break; + case 4: + switch (CPad::GetPad(0)->Mode) { + case 0: + columnToPrint[R] = TheText.Get("FEC_CF1"); + break; + case 1: + columnToPrint[R] = TheText.Get("FEC_CF2"); + break; + case 2: + columnToPrint[R] = TheText.Get("FEC_CF3"); + break; + case 3: + columnToPrint[R] = TheText.Get("FEC_CF4"); + break; + }; + break; + case 5: + break; + case 6: + columnToPrint[R] = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); + break; + case 7: + columnToPrint[R] = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); + break; + case 8: + columnToPrint[R] = TheText.Get(BlurOn ? "FEM_ON" : "FEM_OFF"); + break; + case 9: + columnToPrint[R] = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); + break; + case 10: + columnToPrint[R] = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); + break; + case 16: + sprintf(gString, "FEA_FM%d", m_PrefsRadioStation); + columnToPrint[R] = TheText.Get(gString); + break; + case 28: + columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); + break; + case 29: + columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); + break; + case 81: + columnToPrint[R] = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_ON" : "FEM_OFF"); + break; + case 94: + { + char *res = _psGetVideoModeList()[m_nDisplayVideoMode]; + + if (!res) + res = ""; + + AsciiToUnicode(res, gUString); + columnToPrint[R] = gUString; + } + break; + case 95: + if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) + columnToPrint[R] = TheText.Get("FEA_NAH"); + else { + char *provider = MusicManager.Get3DProviderName(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); + AsciiToUnicode(provider, gUString); + columnToPrint[R] = gUString; + } + break; + case 96: + if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) + columnToPrint[R] = TheText.Get("FEA_NAH"); + else { + switch (m_PrefsSpeakers) { + case 0: + columnToPrint[R] = TheText.Get("FEA_2SP"); + break; + case 1: + columnToPrint[R] = TheText.Get("FEA_EAR"); + break; + case 2: + columnToPrint[R] = TheText.Get("FEA_4SP"); + break; + }; + } + break; + case 99: + switch (m_ControlMethod) { + case 0: + columnToPrint[L] = TheText.Get("FET_SCN"); + break; + case 1: + columnToPrint[L] = TheText.Get("FET_CCN"); + break; + }; + break; + case 100: + columnToPrint[R] = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); + break; + case 102: + columnToPrint[R] = TheText.Get(m_bDisableMouseSteering ? "FEM_ON" : "FEM_OFF"); + break; + }; + + CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetRightJustifyWrap(-SCREEN_WIDTH); + + // Set alignment. + CVector2D vecPositions = { 0.0f, 0.0f }; + float fVerticalSpacing; + float fBarSize; + + int SavePageSlot = + m_nCurrScreen == MENU_CHOOSE_LOAD_SLOT || + m_nCurrScreen == MENU_CHOOSE_DELETE_SLOT || + m_nCurrScreen == MENU_CHOOSE_SAVE_SLOT; + + if (SavePageSlot) { + CFont::SetFontStyle(FONT_BANK); + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.7f)); + fVerticalSpacing = COLUMN_SPACING_MIN; + fBarSize = SELECT_BOX_MIN; + + vecPositions.x = SCREEN_SCALE_X(COLUMN_SAVE_X); + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_SAVE_Y); + } + else { + CFont::SetFontStyle(FONT_HEADING); + + int LeftColumn = + m_nCurrScreen == MENU_SOUND_SETTINGS || + m_nCurrScreen == MENU_GRAPHICS_SETTINGS || + m_nCurrScreen == MENU_MOUSE_CONTROLS; + + if (LeftColumn) { + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.8f)); + fVerticalSpacing = COLUMN_SPACING_MIN; + fBarSize = SELECT_BOX_MIN; + } + else { + CFont::SetAlignment(ALIGN_CENTER); + CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(0.9f)); + fVerticalSpacing = COLUMN_SPACING_MAX; + fBarSize = SELECT_BOX_MAX; + } + + // Set positions. + if (CFont::GetDetails().centre) + vecPositions.x = SCREEN_WIDTH / 2; + else + vecPositions.x = SCREEN_SCALE_X(COLUMN_POS_X); + + switch (m_nCurrScreen) { + case MENU_BRIEFS: + case MENU_STATS: + vecPositions.y = SCREEN_SCALE_FROM_BOTTOM(COLUMN_FEDS); + break; + case MENU_SOUND_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MAX_Y); + + if (i > 5) + vecPositions.y += SCREEN_SCALE_Y(FE_RADIO_ICON_H * 1.16f); + break; + case MENU_LANGUAGE_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MIN_Y); + break; + case MENU_GRAPHICS_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MAX_Y); + break; + case MENU_OPTIONS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + break; + case MENU_PAUSE_MENU: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_PAUSE_Y); + break; + case MENU_NEW_GAME: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + break; + case MENU_START_MENU: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_START_Y); + break; + default: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + break; + }; + } + + if (i > 0) + vecPositions.y += SCREEN_SCALE_Y(fVerticalSpacing * i); + + // Set color and draw selection bar. + if (i == m_nCurrOption && m_nMenuFadeAlpha >= 255) { + CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(11.0f), vecPositions.y - SCREEN_STRETCH_Y(fBarSize * 0.13f), SCREEN_STRETCH_FROM_RIGHT(11.0f), vecPositions.y + SCREEN_STRETCH_Y(fBarSize)), CRGBA(100, 200, 50, 50)); + } + else + CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + + // Draw + if (columnToPrint[L]) + CFont::PrintString(vecPositions.x, vecPositions.y, columnToPrint[L]); + + if (columnToPrint[R]) { + CFont::SetAlignment(ALIGN_RIGHT); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SavePageSlot ? COLUMN_SAVE_X : COLUMN_POS_X), vecPositions.y, columnToPrint[R]); + } + + // Mouse support. + bool bIsMouseInPosition = false; + if (m_nMenuFadeAlpha >= 255) { + CVector2D vecInputSize = { SCREEN_SCALE_X(20.0f), SCREEN_SCALE_FROM_RIGHT(20.0f) }; + if (m_bShowMouse && + ((CheckHover(vecInputSize.x, vecInputSize.y, vecPositions.y, vecPositions.y + SCREEN_STRETCH_Y(20.0f))))) + bIsMouseInPosition = true; + else + bIsMouseInPosition = false; + + if (bIsMouseInPosition) { + if (m_nCurrOption != i) { + m_nCurrOption = i; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + } + + m_nCurrentInput = m_nCurrOption; + + if (CPad::GetPad(0)->NewMouseControllerState.LMB && !CPad::GetPad(0)->OldMouseControllerState.LMB) + m_nHoverOption = IGNORE_OPTION; + else + m_nHoverOption = ACTIVATE_OPTION; + } + } + + // Sliders + // TODO: CheckHover + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case 11: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsBrightness * 0.001953125); + break; + case 12: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), (m_PrefsLOD - 0.80000001) * 1.0000001); + break; + case 13: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsMusicVolume * 0.0078125); + break; + case 14: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsSfxVolume * 0.0078125); + break; + case 84: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), TheCamera.m_fMouseAccelHorzntl * 200.0); + break; + }; + + // Radio icons. + float fIconSpacing = 59.52f; + if (m_nCurrScreen == MENU_SOUND_SETTINGS) { + for (int i = 0; i < POLICE_RADIO; i++) { + + if (i > 5 && i < 7) + fIconSpacing -= 1.5f; + + if (i < USERTRACK) + m_aFrontEndSprites[i + FE_RADIO1].Draw(SCREEN_STRETCH_X(FE_RADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(FE_RADIO_ICON_Y), SCREEN_SCALE_X(FE_RADIO_ICON_W), SCREEN_SCALE_Y(FE_RADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); + if (i > CHATTERBOX) + m_aMenuSprites[MENU_MP3LOGO].Draw(SCREEN_STRETCH_X(FE_RADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(FE_RADIO_ICON_Y), SCREEN_SCALE_X(FE_RADIO_ICON_W), SCREEN_SCALE_Y(FE_RADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, DMAudio.IsMP3RadioChannelAvailable() ? 170 : 25)); + } + } + + // Helpers + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) { + if (m_nDisplayVideoMode == m_nPrefsVideoMode) { + if (m_nHelperTextMsgId == 1) + ResetHelperText(); + } + else + SetHelperText(1); + } + else { + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + m_nDisplayVideoMode = m_nPrefsVideoMode; + SetHelperText(3); + } + } + + switch (m_nCurrScreen) { + case MENU_CONTROLLER_SETTINGS: + case MENU_SOUND_SETTINGS: + case MENU_GRAPHICS_SETTINGS: + case MENU_SKIN_SELECT: + case MENU_CONTROLLER_PC: + case MENU_MOUSE_CONTROLS: + DisplayHelperText(); + break; + }; + } + }; +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawControllerBound(int, int, int, uint8) { EAXJMP(0x489710); } +#else +void CMenuManager::DrawControllerBound(int, int, int, uint8) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawControllerScreenExtraText(int, int, int) { EAXJMP(0x4892F0); } +#else +void CMenuManager::DrawControllerScreenExtraText(int, int, int) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawControllerSetupScreen() { EAXJMP(0x481210); } +#else +void CMenuManager::DrawControllerSetupScreen() +{ + +} +#endif + +#if 0 WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); } -WRAPPER void CMenuManager::UnloadTextures(void) { EAXJMP(0x47A440); } -WRAPPER void CMenuManager::LoadAllTextures(void) { EAXJMP(0x47A230); } -WRAPPER void CMenuManager::LoadSettings(void) { EAXJMP(0x488EE0); } -WRAPPER void CMenuManager::WaitForUserCD(void) { EAXJMP(0x48ADD0); } +#else +void CMenuManager::DrawFrontEnd() +{ + CFont::SetAlphaFade(255.0f); + + if (!m_nCurrScreen) { + if (m_bGameNotLoaded) + m_nCurrScreen = MENU_START_MENU; + else + m_nCurrScreen = MENU_PAUSE_MENU; + } + + if (!m_nCurrOption && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == 1) + m_nCurrOption = 1; + + CMenuManager::DrawFrontEndNormal(); + CMenuManager::PrintErrorMessage(); +} +#endif + +#if 0 +WRAPPER void CMenuManager::DrawFrontEndNormal(void) { EAXJMP(0x47A5B0); } +#else +void CMenuManager::DrawFrontEndNormal() +{ + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSCLAMP); + + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); -int CMenuManager::FadeIn(int alpha) { + eMenuSprites currentSprite = MENU_CONNECTION; + switch (m_nPrevScreen) { + case MENU_STATS: + case MENU_START_MENU: + case MENU_PAUSE_MENU: + currentSprite = MENU_MAINMENU; + break; + case MENU_NEW_GAME: + case MENU_CHOOSE_LOAD_SLOT: + case MENU_CHOOSE_DELETE_SLOT: + case MENU_NEW_GAME_RELOAD: + case MENU_LOAD_SLOT_CONFIRM: + case MENU_DELETE_SLOT_CONFIRM: + case MENU_EXIT: + currentSprite = MENU_SINGLEPLAYER; + break; + case MENU_MULTIPLAYER_MAIN: + currentSprite = MENU_MULTIPLAYER; + break; + case MENU_MULTIPLAYER_MAP: + case MENU_MULTIPLAYER_FIND_GAME: + case MENU_SKIN_SELECT: + case MENU_KEYBOARD_CONTROLS: + case MENU_MOUSE_CONTROLS: + currentSprite = MENU_FINDGAME; + break; + case MENU_MULTIPLAYER_CONNECTION: + case MENU_MULTIPLAYER_MODE: + currentSprite = MENU_CONNECTION; + break; + case MENU_MULTIPLAYER_CREATE: + currentSprite = MENU_HOSTGAME; + break; + case MENU_SKIN_SELECT_OLD: + case MENU_OPTIONS: + currentSprite = MENU_PLAYERSET; + break; + }; + + //CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(0, 0, 0, 255)); + + uint32 savedShade; + uint32 savedAlpha; + RwRenderStateGet(rwRENDERSTATESHADEMODE, &savedShade); + RwRenderStateSet(rwRENDERSTATESHADEMODE, reinterpret_cast<void *>(rwSHADEMODEGOURAUD)); + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &savedAlpha); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void *>(TRUE)); + if (m_nMenuFadeAlpha >= 255) + m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, 255)); + else { + if (m_nMenuFadeAlpha != 255) + m_nMenuFadeAlpha += 0.1f * 255.0f; + + m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); + } + + // GTA LOGO + if (m_nCurrScreen == 51 || m_nCurrScreen == 52) { + if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) + m_aMenuSprites[MENU_GTA3LOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(70.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); + else + m_aMenuSprites[MENU_GTALOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(40.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); + } + RwRenderStateSet(rwRENDERSTATESHADEMODE, reinterpret_cast<void *>(savedShade)); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void *>(savedAlpha)); + + switch (m_nCurrScreen) { + case MENU_SKIN_SELECT: + CMenuManager::DrawPlayerSetupScreen(); + break; + case MENU_KEYBOARD_CONTROLS: + CMenuManager::DrawControllerSetupScreen(); + break; + default: + CMenuManager::Draw(); + break; + }; + + CFont::DrawFonts(); + + // Draw mouse + if (m_bShowMouse) + m_aMenuSprites[MENU_MOUSE].Draw(m_nMousePosX, m_nMousePosY, SCREEN_SCALE_X(60.0f), SCREEN_SCALE_Y(60.0f), CRGBA(255, 255, 255, 255)); +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawPlayerSetupScreen() { EAXJMP(0x47F2B0); } +#else +void CMenuManager::DrawPlayerSetupScreen() +{ + +} +#endif + +#if 0 +WRAPPER int CMenuManager::FadeIn(int alpha) { EAXJMP(0x48AC60); } +#else +int CMenuManager::FadeIn(int alpha) +{ if (m_nCurrScreen == MENU_LOADING_IN_PROGRESS || m_nCurrScreen == MENU_SAVING_IN_PROGRESS || m_nCurrScreen == MENU_DELETING) @@ -47,7 +1187,328 @@ int CMenuManager::FadeIn(int alpha) { return m_nMenuFadeAlpha; } +#endif + +#if 1 +WRAPPER void CMenuManager::FilterOutColorMarkersFromString(uint16, CRGBA &) { EAXJMP(0x4889C0); } +#else +void CMenuManager::FilterOutColorMarkersFromString(uint16, CRGBA &) +{ + +} +#endif + +#if 1 +WRAPPER int CMenuManager::GetStartOptionsCntrlConfigScreens() { EAXJMP(0x489270); } +#else +int CMenuManager::GetStartOptionsCntrlConfigScreens() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::InitialiseChangedLanguageSettings() { EAXJMP(0x47A4D0); } +#else +void CMenuManager::InitialiseChangedLanguageSettings() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::LoadAllTextures() { EAXJMP(0x47A230); } +#else +void CMenuManager::LoadAllTextures() +{ + if (!m_bSpritesLoaded) { + CMenuManager::CentreMousePointer(); + DMAudio.ChangeMusicMode(0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + m_nCurrOption = 0; + m_PrefsRadioStation = DMAudio.GetRadioInCar(); + + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (CMenuManager::m_PrefsRadioStation > USERTRACK) + CMenuManager::m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; + } + else if (CMenuManager::m_PrefsRadioStation > CHATTERBOX) + CMenuManager::m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; + + CFileMgr::SetDir(""); + CTimer::Stop(); + CStreaming::MakeSpaceFor(716800); + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); + + int frontend = CTxdStore::AddTxdSlot("frontend"); + CTxdStore::LoadTxd(frontend, "MODELS/FRONTEND.TXD"); + CTxdStore::AddRef(frontend); + CTxdStore::SetCurrentTxd(frontend); + CStreaming::IHaveUsedStreamingMemory(); + CTimer::Update(); + + debug("LOAD frontend\n"); + for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + }; + + CTxdStore::PopCurrentTxd(); + + int menu = CTxdStore::AddTxdSlot("menu"); + CTxdStore::LoadTxd(menu, "MODELS/MENU.TXD"); + CTxdStore::AddRef(menu); + CTxdStore::SetCurrentTxd(menu); + + debug("LOAD sprite\n"); + for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) { + m_aMenuSprites[i].SetTexture(MenuFilenames[i]); + m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + }; + + CTxdStore::PopCurrentTxd(); + + m_bSpritesLoaded = true; + } +} +#endif + +#if 1 +WRAPPER void CMenuManager::LoadSettings() { EAXJMP(0x488EE0); } +#else +void CMenuManager::LoadSettings() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::MessageScreen(char *) { EAXJMP(0x48B7E0); } +#else +void CMenuManager::MessageScreen(char *) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::PickNewPlayerColour() { EAXJMP(0x488C40); } +#else +void CMenuManager::PickNewPlayerColour() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::PrintBriefs() { EAXJMP(0x484D60); } +#else +void CMenuManager::PrintBriefs() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::PrintErrorMessage() { EAXJMP(0x484F70); } +#else +void CMenuManager::PrintErrorMessage() +{ + if (!CPad::bDisplayNoControllerMessage && !CPad::bObsoleteControllerMessage) + return; + + CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(140.0f), SCREEN_WIDTH - SCREEN_SCALE_X(20.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(140.0f)), CRGBA(64, 16, 16, 224)); + CFont::SetFontStyle(FONT_BANK); + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetCentreOff(); + CFont::SetJustifyOn(); + CFont::SetRightJustifyOff(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetWrapx(SCREEN_WIDTH - 40.0f); + CFont::SetColor(CRGBA(165, 165, 165, 255)); + CFont::SetScale(SCREEN_SCALE_X(0.9f), SCREEN_SCALE_Y(0.9f)); + CFont::PrintString(SCREEN_SCALE_X(40.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(60.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); + CFont::DrawFonts(); +} +#endif + +#if 1 +WRAPPER void CMenuManager::PrintStats() { EAXJMP(0x482100); } +#else +void CMenuManager::PrintStats() +{ + +} +#endif + + +#if 1 +WRAPPER void CMenuManager::Process(void) { EAXJMP(0x485100); } +#else +void CMenuManager::Process(void) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::ProcessButtonPresses() { EAXJMP(0x4856F0); } +#else +void CMenuManager::ProcessButtonPresses() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::ProcessOnOffMenuOptions() { EAXJMP(0x48AE60); } +#else +void CMenuManager::ProcessOnOffMenuOptions() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::RequestFrontEndShutdown() { EAXJMP(0x488750); } +#else +void CMenuManager::RequestFrontEndShutdown() +{ + m_bShutDownFrontEndRequested = true; + DMAudio.ChangeMusicMode(1); +} +#endif + +#if 0 +WRAPPER void CMenuManager::RequestFrontEndStartUp() { EAXJMP(0x488770); } +#else +void CMenuManager::RequestFrontEndStartUp() +{ + m_bStartUpFrontEndRequested = 1; +} +#endif + +#if 0 +WRAPPER void CMenuManager::ResetHelperText() { EAXJMP(0x48B470); } +#else +void CMenuManager::ResetHelperText() +{ + m_nHelperTextMsgId = 0; + m_nHelperTextAlpha = 300; +} +#endif + +#if 1 +WRAPPER void CMenuManager::SaveLoadFileError_SetUpErrorScreen() { EAXJMP(0x488930); } +#else +void CMenuManager::SaveLoadFileError_SetUpErrorScreen() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::SetHelperText() { EAXJMP(0x48B450); } +#else +void CMenuManager::SetHelperText(int text) +{ + m_nHelperTextMsgId = text; + m_nHelperTextAlpha = 300; +} +#endif + +#if 1 +WRAPPER void CMenuManager::SaveSettings() { EAXJMP(0x488CC0); } +#else +void CMenuManager::SaveSettings() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::ShutdownJustMenu() { EAXJMP(0x488920); } +#else +void CMenuManager::ShutdownJustMenu() +{ + m_bMenuActive = false; + CTimer::EndUserPause(); +} +#endif + +#if 0 +WRAPPER float CMenuManager::StretchX(float) { EAXJMP(0x48ABE0); } +#else +float CMenuManager::StretchX(float x) +{ + if (SCREENW == 640) + return x; + else + return SCREENW * x * 0.0015625f; +} +#endif + +#if 0 +WRAPPER float CMenuManager::StretchY(float) { EAXJMP(0x48AC20); } +#else +float CMenuManager::StretchY(float y) +{ + if (SCREENH == 448) + return y; + else + return SCREENH * y * 0.002232143f; +} +#endif + +#if 0 +WRAPPER void CMenuManager::SwitchMenuOnAndOff() { EAXJMP(0x488790); } +#else +void CMenuManager::SwitchMenuOnAndOff() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::UnloadTextures() { EAXJMP(0x47A440); } +#else +void CMenuManager::UnloadTextures() +{ + if (m_bSpritesLoaded) { + debug("Remove frontend\n"); + for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i) + m_aFrontEndSprites[i].Delete(); + + int frontend = CTxdStore::FindTxdSlot("frontend"); + CTxdStore::RemoveTxdSlot(frontend); + + debug("Remove menu textures\n"); + for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i) + m_aMenuSprites[i].Delete(); + + int menu = CTxdStore::FindTxdSlot("menu"); + CTxdStore::RemoveTxdSlot(menu); + + m_bSpritesLoaded = false; + } +} +#endif + +#if 1 +WRAPPER void CMenuManager::WaitForUserCD(void) { EAXJMP(0x48ADD0); } +#else +void CMenuManager::WaitForUserCD() +{ + +} +#endif STARTPATCHES - InjectHook(0x48AC60, &CMenuManager::FadeIn, PATCH_JUMP); + InjectHook(0x47A230, &CMenuManager::LoadAllTextures, PATCH_JUMP); + InjectHook(0x47A440, &CMenuManager::UnloadTextures, PATCH_JUMP); + + for (int i = 1; i < ARRAY_SIZE(aScreens); i++) + Patch(0x611930 + sizeof(CMenuScreen) * i, aScreens[i]); ENDPATCHES
\ No newline at end of file diff --git a/src/Frontend.h b/src/Frontend.h index 2e95d582..2f68fdcd 100644 --- a/src/Frontend.h +++ b/src/Frontend.h @@ -2,6 +2,43 @@ #include "Sprite2d.h" +#define HEADER_POS_X 35.0f +#define HEADER_POS_Y 93.0f +#define HEADER_WIDTH 0.84f +#define HEADER_HEIGHT 1.6f + +#define ACTION_POS_X 20.0f +#define ACTION_POS_Y 37.5f +#define ACTION_WIDTH 0.675f +#define ACTION_HEIGHT 0.81f + +#define COLUMN_POS_X HEADER_POS_X + 16.0f +#define COLUMN_MAX_Y 149.0f +#define COLUMN_MID_Y 100.0f +#define COLUMN_MIN_Y 110.0f +#define COLUMN_PAUSE_Y 25.0f +#define COLUMN_START_Y 9.0f +#define COLUMN_FEDS 139.0f + +#define COLUMN_SAVE_X 121.0f +#define COLUMN_SAVE_Y 111.0f + +#define COLUMN_SPACING_MAX 24.0f +#define COLUMN_SPACING_MIN 20.0f + +#define SELECT_BOX_MAX 20.5f +#define SELECT_BOX_MIN 17.0f + +#define FE_RADIO_ICON_X 31.5f +#define FE_RADIO_ICON_Y 29.5f +#define FE_RADIO_ICON_W 60.0f +#define FE_RADIO_ICON_H 60.0f + +#define DROP_COLOR_A 150 +#define DROP_COLOR_SIZE -1 + +#define SLIDER_X 306.0f + enum { LANGUAGE_AMERICAN, LANGUAGE_FRENCH, @@ -10,6 +47,70 @@ enum { LANGUAGE_SPANISH, }; +enum eFrontendSprites { + FE2_MAINPANEL_UL, + FE2_MAINPANEL_UR, + FE2_MAINPANEL_DL, + FE2_MAINPANEL_DR, + FE2_MAINPANEL_DR2, + FE2_TABACTIVE, + FE_ICONBRIEF, + FE_ICONSTATS, + FE_ICONCONTROLS, + FE_ICONSAVE, + FE_ICONAUDIO, + FE_ICONDISPLAY, + FE_ICONLANGUAGE, + FE_CONTROLLER, + FE_CONTROLLERSH, + FE_ARROWS1, + FE_ARROWS2, + FE_ARROWS3, + FE_ARROWS4, + FE_RADIO1, + FE_RADIO2, + FE_RADIO3, + FE_RADIO4, + FE_RADIO5, + FE_RADIO6, + FE_RADIO7, + FE_RADIO8, + FE_RADIO9, +}; + +enum eMenuSprites { + MENU_CONNECTION, + MENU_FINDGAME, + MENU_HOSTGAME, + MENU_MAINMENU, + MENU_PLAYERSET, + MENU_SINGLEPLAYER, + MENU_MULTIPLAYER, + MENU_DMALOGO, + MENU_GTALOGO, + MENU_RSTARLOGO, + MENU_GAMESPY, + MENU_MOUSE, + MENU_MOUSET, + MENU_MP3LOGO, + MENU_DOWNOFF, + MENU_UPOFF, + MENU_DOWNON, + MENU_UPON, + MENU_GTA3LOGO, +}; + +enum eMenuActions { + MENU_ACTION_SAVE_1 = 1, + MENU_ACTION_SAVE_2, + MENU_ACTION_SAVE_3, + MENU_ACTION_SAVE_4, + MENU_ACTION_SAVE_5, + MENU_ACTION_SAVE_6, + MENU_ACTION_SAVE_7, + MENU_ACTION_SAVE_8, +}; + enum eMenuScreen { MENU_NONE = 0, MENU_STATS = 1, @@ -72,6 +173,11 @@ enum eMenuScreen { MENU_58 = 58, }; +enum eCheckHover { + ACTIVATE_OPTION = 2, + IGNORE_OPTION = 42, +}; + struct tSkinInfo { int field_0; @@ -81,6 +187,20 @@ struct tSkinInfo int field_304; }; +struct CMenuScreen { + char m_ScreenName[8]; + int32 m_PreviousPage[3]; // + int32 m_ParentEntry[2]; + + struct CMenuEntry + { + int32 m_Action; + char m_EntryName[8]; + int32 m_ActionSlot; + int32 m_TargetMenu; + } m_aEntries[18]; +}; + class CMenuManager { public: @@ -136,10 +256,10 @@ public: int m_nHelperTextAlpha; int m_nMouseOldPosX; int m_nMouseOldPosY; - int field_544; + int m_nHoverOption; int m_nCurrScreen; int m_nCurrOption; - int field_550; + int m_nCurrentInput; int m_nPrevScreen; int field_558; int m_nCurrSaveSlot; @@ -165,17 +285,56 @@ public: static int8 &m_bFrontEnd_ReloadObrTxtGxt; static int32 &m_PrefsMusicVolume; static int32 &m_PrefsSfxVolume; + static bool &m_bStartUpFrontEndRequested; + static bool &m_bShutDownFrontEndRequested; static bool &m_PrefsAllowNastyGame; - static bool &m_bStartUpFrontEndRequested; - void Process(void); - void DrawFrontEnd(void); - void UnloadTextures(void); - void LoadAllTextures(void); - void LoadSettings(void); - void WaitForUserCD(void); +private: + enum eColumns { L, R, COLUMNS, }; + +public: + void BuildStatLine(char *, void *, uint16, void *); + static void CentreMousePointer(); + void CheckCodesForControls(int, int); + bool CheckHover(int x1, int x2, int y1, int y2); + int CostructStatLine(int); + void DisplayHelperText(); + float DisplaySlider(float, float, float, float, float, float); + void DoSettingsBeforeStartingAGame(); + void Draw(); + void DrawControllerBound(int, int, int, uint8); + void DrawControllerScreenExtraText(int, int, int); + void DrawControllerSetupScreen(); + void DrawFrontEnd(); + void DrawFrontEndNormal(); + void DrawPlayerSetupScreen(); int FadeIn(int alpha); + void FilterOutColorMarkersFromString(uint16, CRGBA &); + int GetStartOptionsCntrlConfigScreens(); + static void InitialiseChangedLanguageSettings(); + void LoadAllTextures(); + void LoadSettings(); + static void MessageScreen(char *); + static void PickNewPlayerColour(); + void PrintBriefs(); + static void PrintErrorMessage(); + void PrintStats(); + void Process(); + void ProcessButtonPresses(); + void ProcessOnOffMenuOptions(); + static void RequestFrontEndShutdown(); + static void RequestFrontEndStartUp(); + void ResetHelperText(); + void SaveLoadFileError_SetUpErrorScreen(); + void SaveSettings(); + void SetHelperText(int text); + void ShutdownJustMenu(); + static float StretchX(float); + static float StretchY(float ); + void SwitchMenuOnAndOff(); + void UnloadTextures(); + void WaitForUserCD(); }; static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error"); diff --git a/src/PCSave.cpp b/src/PCSave.cpp index 2d49b23f..ae5e43b0 100644 --- a/src/PCSave.cpp +++ b/src/PCSave.cpp @@ -4,4 +4,9 @@ #include "PCSave.h" WRAPPER void C_PcSave::SetSaveDirectory(const char *path) { EAXJMP(0x591EA0); } +WRAPPER wchar *GetNameOfSavedGame(int counter) { EAXJMP(0x591B60); } +WRAPPER wchar *GetSavedGameDateAndTime(int counter) { EAXJMP(0x591B50); } +int *Slots = (int*)0x728040; +int *SlotFileName = (int*)0x6F07C8; +int *SlotSaveDate = (int*)0x72B858; diff --git a/src/PCSave.h b/src/PCSave.h index 324a3421..79202bc9 100644 --- a/src/PCSave.h +++ b/src/PCSave.h @@ -4,4 +4,11 @@ class C_PcSave { public: static void SetSaveDirectory(const char *path); -};
\ No newline at end of file +}; + +extern wchar *GetNameOfSavedGame(int counter); +extern wchar *GetSavedGameDateAndTime(int counter); + +extern int *Slots; +extern int *SlotFileName; +extern int *SlotSaveDate; diff --git a/src/Radar.cpp b/src/Radar.cpp index 90d27af2..3c2f24d3 100644 --- a/src/Radar.cpp +++ b/src/Radar.cpp @@ -14,8 +14,6 @@ #include "World.h" #include "Streaming.h" -WRAPPER void CRadar::Draw3dMarkers() { EAXJMP(0x4A4C70); } - float &CRadar::m_RadarRange = *(float*)0x8E281C; CBlip *CRadar::ms_RadarTrace = (CBlip*)0x6ED5E0; @@ -77,107 +75,69 @@ static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not #define RADAR_MAX_SPEED (0.9f) #if 0 -WRAPPER void CRadar::DrawMap () { EAXJMP(0x4A4200); } +WRAPPER void CRadar::CalculateBlipAlpha(float) { EAXJMP(0x4A4F90); } #else -void CRadar::DrawMap() +int CRadar::CalculateBlipAlpha(float dist) { - if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { - if (FindPlayerVehicle()) { - float speed = FindPlayerSpeed().Magnitude(); - if (speed < RADAR_MIN_SPEED) - m_RadarRange = RADAR_MIN_RANGE; - else if (speed < RADAR_MAX_SPEED) - m_RadarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE; - else - m_RadarRange = RADAR_MAX_RANGE; - } - else - m_RadarRange = RADAR_MIN_RANGE; + if (dist <= 1.0f) + return 255; - vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); - DrawRadarMap(); - } + if (dist <= 5.0f) + return (((1.0f - ((dist * 0.25f) - 0.25f)) * 255.0f) + (((dist * 0.25f) - 0.25f) * 128.0f)); + + return 128; } -#endif +#endif -#if 0 -WRAPPER void CRadar::DrawRadarMask() { EAXJMP(0x4A69C0); } +#if 1 +WRAPPER void CRadar::ChangeBlipBrightness(int32, int32) { EAXJMP(0x4A57A0); } #else -void CRadar::DrawRadarMask() -{ - CVector2D corners[4] = { - CVector2D(1.0f, -1.0f), - CVector2D(1.0f, 1.0f), - CVector2D(-1.0f, 1.0f), - CVector2D(-1.0, -1.0f) - }; - - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONALWAYS); +void CRadar::ChangeBlipBrightness(int32 i, int32 bright) +{ - CVector2D out[8]; - CVector2D in; +} +#endif - // Draw the shape we want to mask out from the radar in four segments - for (int i = 0; i < 4; i++) { - // First point is always the corner itself - in.x = corners[i].x; - in.y = corners[i].y; - TransformRadarPointToScreenSpace(out[0], in); +#if 1 +WRAPPER void CRadar::ChangeBlipColour(int32) { EAXJMP(0x4A5770); } +#else +void CRadar::ChangeBlipColour(int32 i) +{ - // Then generate a quarter of the circle - for (int j = 0; j < 7; j++) { - in.x = corners[i].x * cos(j * (PI / 2.0f / 6.0f)); - in.y = corners[i].y * sin(j * (PI / 2.0f / 6.0f)); - TransformRadarPointToScreenSpace(out[j + 1], in); - }; +} +#endif - CSprite2d::SetMaskVertices(8, (float *)out); - RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8); - }; +#if 1 +WRAPPER void CRadar::ChangeBlipDisplay(int32, int16) { EAXJMP(0x4A5810); } +#else +void CRadar::ChangeBlipDisplay(int32 i, int16 flag) +{ - RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONGREATER); } #endif -#if 0 -WRAPPER void CRadar::SetRadarMarkerState(int counter, int flag) { EAXJMP(0x4A5C60); } +#if 1 +WRAPPER void CRadar::ChangeBlipScale(int32, int16) { EAXJMP(0x4A57E0); } #else -void CRadar::SetRadarMarkerState(int counter, int flag) +void CRadar::ChangeBlipScale(int32 i, int16 scale) { - CEntity *e; - switch (ms_RadarTrace[counter].m_eBlipType) { - case BLIP_CAR: - e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); - break; - case BLIP_CHAR: - e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); - break; - case BLIP_OBJECT: - e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); - break; - default: - return; - } - if (e) - e->bHasBlip = flag; +} +#endif + +#if 1 +WRAPPER void CRadar::ClearBlip(int32) { EAXJMP(0x4A5720); } +#else +void CRadar::ClearBlip(int32 i) +{ } #endif #if 0 -WRAPPER void CRadar::ClearBlipForEntity(eBlipType type, int32 id) { EAXJMP(0x4A56C0); } +WRAPPER void CRadar::ClearBlipForEntity(int16, int32) { EAXJMP(0x4A56C0); } #else -void CRadar::ClearBlipForEntity(eBlipType type, int32 id) +void CRadar::ClearBlipForEntity(int16 type, int32 id) { for (int i = 0; i < NUMRADARBLIPS; i++) { if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) { @@ -191,87 +151,6 @@ void CRadar::ClearBlipForEntity(eBlipType type, int32 id) } #endif -bool -IsPointInsideRadar(const CVector2D &point) -{ - if(point.x < -1.0f || point.x > 1.0f) return false; - if(point.y < -1.0f || point.y > 1.0f) return false; - return true; -} - -// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1 -int -LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2) -{ - float d1, d2; - float t; - float x, y; - float shortest = 1.0f; - int edge = -1; - - // clip against left edge, x = -1.0 - d1 = -1.0f - p1.x; - d2 = -1.0f - p2.x; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - y = (p2.y - p1.y)*t + p1.y; - if(y >= -1.0f && y <= 1.0f && t <= shortest){ - out.x = -1.0f; - out.y = y; - edge = 3; - shortest = t; - } - } - - // clip against right edge, x = 1.0 - d1 = p1.x - 1.0f; - d2 = p2.x - 1.0f; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - y = (p2.y - p1.y)*t + p1.y; - if(y >= -1.0f && y <= 1.0f && t <= shortest){ - out.x = 1.0f; - out.y = y; - edge = 1; - shortest = t; - } - } - - // clip against top edge, y = -1.0 - d1 = -1.0f - p1.y; - d2 = -1.0f - p2.y; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - x = (p2.x - p1.x)*t + p1.x; - if(x >= -1.0f && x <= 1.0f && t <= shortest){ - out.y = -1.0f; - out.x = x; - edge = 0; - shortest = t; - } - } - - // clip against bottom edge, y = 1.0 - d1 = p1.y - 1.0f; - d2 = p2.y - 1.0f; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - x = (p2.x - p1.x)*t + p1.x; - if(x >= -1.0f && x <= 1.0f && t <= shortest){ - out.y = 1.0f; - out.x = x; - edge = 2; - shortest = t; - } - } - - return edge; -} - #if 0 WRAPPER int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *in) { EAXJMP(0x4A64A0); } #else @@ -289,36 +168,37 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) int laste, e, e1, e2;; bool inside[4]; - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) inside[i] = IsPointInsideRadar(rect[i]); laste = -1; n = 0; - for(i = 0; i < 4; i++) - if(inside[i]){ + for (i = 0; i < 4; i++) + if (inside[i]) { // point is inside, just add poly[n++] = rect[i]; - }else{ + } + else { // point is outside but line to this point might be clipped - e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i+4-1) % 4]); - if(e1 != -1){ + e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]); + if (e1 != -1) { laste = e1; n++; } // and line from this point might be clipped as well - e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i+1) % 4]); - if(e2 != -1){ - if(e1 == -1){ + e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]); + if (e2 != -1) { + if (e1 == -1) { // if other line wasn't clipped, i.e. it was complete outside, // we may have to insert another vertex if last clipped line // was on a different edge // find the last intersection if we haven't seen it yet - if(laste == -1) - for(j = 3; j >= i; j--){ + if (laste == -1) + for (j = 3; j >= i; j--) { // game uses an if here for j == 0 - e = LineRadarBoxCollision(tmp, rect[j], rect[(j+4-1) % 4]); - if(e != -1){ + e = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]); + if (e != -1) { laste = e; break; } @@ -327,7 +207,7 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) // insert corners that were skipped tmp = poly[n]; - for(e = laste; e != e2; e = (e+1) % 4) + for (e = laste; e != e2; e = (e + 1) % 4) poly[n++] = corners[e]; poly[n] = tmp; } @@ -335,13 +215,13 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) } } - if(n == 0){ + if (n == 0) { // If no points, either the rectangle is completely outside or completely surrounds the radar // no idea what's going on here... float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x); - if((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f){ + if ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) { m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x); - if((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f){ + if ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) { poly[0] = corners[0]; poly[1] = corners[1]; poly[2] = corners[2]; @@ -355,147 +235,27 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) } #endif -#if 0 -WRAPPER void CRadar::DrawRadarSection(int x, int y) { EAXJMP(0x4A67E0); } -#else -void CRadar::DrawRadarSection(int x, int y) +bool CRadar::DisplayThisBlip(int32 counter) { - int i; - RwTexDictionary *txd; - CVector2D worldPoly[8]; - CVector2D radarCorners[4]; - CVector2D radarPoly[8]; - CVector2D texCoords[8]; - CVector2D screenPoly[8]; - int numVertices; - RwTexture *texture = nil; - - GetTextureCorners(x, y, worldPoly); - ClipRadarTileCoords(x, y); - - assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])); - txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict; - if(txd) - texture = GetFirstTexture(txd); - if(texture == nil) - return; - - for(i = 0; i < 4; i++) - TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]); - - numVertices = ClipRadarPoly(radarPoly, radarCorners); - - // FIX: can return earlier here -// if(numVertices == 0) - if(numVertices < 3) - return; - - for(i = 0; i< numVertices; i++){ - TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]); - TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y); - TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]); + switch (ms_RadarTrace[counter].m_IconID) { + case RADAR_SPRITE_BOMB: + case RADAR_SPRITE_SPRAY: + case RADAR_SPRITE_WEAPON: + return true; + default: + return false; } - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); - CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); - // check done above now -// if(numVertices > 2) - RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices); -} -#endif - -void CRadar::RequestMapSection(int x, int y) -{ - ClipRadarTileCoords(x, y); - CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_DEPENDENCY); -} - -void CRadar::RemoveMapSection(int x, int y) -{ - if (x >= 0 && x <= 7 && y >= 0 && y <= 7) - CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]); } -#if 0 -WRAPPER void CRadar::StreamRadarSections(int x, int y) { EAXJMP(0x4A6100); } -#else -void CRadar::StreamRadarSections(int x, int y) -{ - for (int i = 0; i < RADAR_NUM_TILES; ++i) { - for (int j = 0; j < RADAR_NUM_TILES; ++j) { - if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1)) - RequestMapSection(i, j); - else - RemoveMapSection(i, j); - }; - }; -} -#endif - -#if 0 -WRAPPER float CRadar::LimitRadarPoint(CVector2D &point) { EAXJMP(0x4A4F30); } +#if 1 +WRAPPER void CRadar::Draw3dMarkers() { EAXJMP(0x4A4C70); } #else -float CRadar::LimitRadarPoint(CVector2D &point) +void CRadar::Draw3dMarkers() { - float dist, invdist; - dist = point.Magnitude(); - if (dist > 1.0f) { - invdist = 1.0f / dist; - point.x *= invdist; - point.y *= invdist; - } - return dist; -} -#endif - -#if 0 -WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) { EAXJMP(0x4A5530); } -#else -void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) -{ - out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X); - out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y)); - out.x /= RADAR_TILE_SIZE; - out.y /= RADAR_TILE_SIZE; } #endif -#if 0 -WRAPPER void CRadar::DrawRadarMap() { EAXJMP(0x4A6C20); } -#else -void CRadar::DrawRadarMap() -{ - // Game calculates an unused CRect here - - DrawRadarMask(); - - // top left ist (0, 0) - int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE); - int y = ceilf((RADAR_NUM_TILES-1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE); - StreamRadarSections(x, y); - - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE); - - DrawRadarSection(x - 1, y - 1); - DrawRadarSection(x, y - 1); - DrawRadarSection(x + 1, y - 1); - DrawRadarSection(x - 1, y); - DrawRadarSection(x, y); - DrawRadarSection(x + 1, y); - DrawRadarSection(x - 1, y + 1); - DrawRadarSection(x, y + 1); - DrawRadarSection(x + 1, y + 1); -} -#endif #if 0 WRAPPER void CRadar::DrawBlips() { EAXJMP(0x4A42F0); } @@ -566,12 +326,12 @@ void CRadar::DrawBlips() int a = CalculateBlipAlpha(dist); TransformRadarPointToScreenSpace(out, in); - CRGBA col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); + int32 col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); if (ms_RadarTrace[i].m_IconID) DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, ((col >> 24)), ((col >> 16) & 0xFF), ((col >> 8)), 255); } } } @@ -596,12 +356,12 @@ void CRadar::DrawBlips() int a = CalculateBlipAlpha(dist); TransformRadarPointToScreenSpace(out, in); - CRGBA col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); + int32 col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); if (ms_RadarTrace[i].m_IconID) DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, ((col >> 24)), ((col >> 16) & 0xFF), ((col >> 8)), 255); } } } @@ -611,227 +371,579 @@ void CRadar::DrawBlips() } #endif -int CRadar::CalculateBlipAlpha(float dist) + +#if 0 +WRAPPER void CRadar::DrawMap () { EAXJMP(0x4A4200); } +#else +void CRadar::DrawMap() { - if (dist <= 1.0f) - return 255; + if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { + if (FindPlayerVehicle()) { + float speed = FindPlayerSpeed().Magnitude(); + if (speed < RADAR_MIN_SPEED) + m_RadarRange = RADAR_MIN_RANGE; + else if (speed < RADAR_MAX_SPEED) + m_RadarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE; + else + m_RadarRange = RADAR_MAX_RANGE; + } + else + m_RadarRange = RADAR_MIN_RANGE; - if (dist <= 5.0f) - return (((1.0f - ((dist * 0.25f) - 0.25f)) * 255.0f) + (((dist * 0.25f) - 0.25f) * 128.0f)); + vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); + DrawRadarMap(); + } +} +#endif - return 128; +#if 0 +WRAPPER void CRadar::DrawRadarMap() { EAXJMP(0x4A6C20); } +#else +void CRadar::DrawRadarMap() +{ + // Game calculates an unused CRect here + + DrawRadarMask(); + + // top left ist (0, 0) + int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE); + int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE); + StreamRadarSections(x, y); + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE); + + DrawRadarSection(x - 1, y - 1); + DrawRadarSection(x, y - 1); + DrawRadarSection(x + 1, y - 1); + DrawRadarSection(x - 1, y); + DrawRadarSection(x, y); + DrawRadarSection(x + 1, y); + DrawRadarSection(x - 1, y + 1); + DrawRadarSection(x, y + 1); + DrawRadarSection(x + 1, y + 1); } +#endif + +#if 0 +WRAPPER void CRadar::DrawRadarMask() { EAXJMP(0x4A69C0); } +#else +void CRadar::DrawRadarMask() +{ + CVector2D corners[4] = { + CVector2D(1.0f, -1.0f), + CVector2D(1.0f, 1.0f), + CVector2D(-1.0f, 1.0f), + CVector2D(-1.0, -1.0f) + }; -CRGBA CRadar::GetRadarTraceColour(uint32 color, bool bright) + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONALWAYS); + + CVector2D out[8]; + CVector2D in; + + // Draw the shape we want to mask out from the radar in four segments + for (int i = 0; i < 4; i++) { + // First point is always the corner itself + in.x = corners[i].x; + in.y = corners[i].y; + TransformRadarPointToScreenSpace(out[0], in); + + // Then generate a quarter of the circle + for (int j = 0; j < 7; j++) { + in.x = corners[i].x * cos(j * (PI / 2.0f / 6.0f)); + in.y = corners[i].y * sin(j * (PI / 2.0f / 6.0f)); + TransformRadarPointToScreenSpace(out[j + 1], in); + }; + + CSprite2d::SetMaskVertices(8, (float *)out); + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8); + }; + + RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONGREATER); +} +#endif + +#if 0 +WRAPPER void CRadar::DrawRadarSection(int32, int32) { EAXJMP(0x4A67E0); } +#else +void CRadar::DrawRadarSection(int32 x, int32 y) { + int i; + RwTexDictionary *txd; + CVector2D worldPoly[8]; + CVector2D radarCorners[4]; + CVector2D radarPoly[8]; + CVector2D texCoords[8]; + CVector2D screenPoly[8]; + int numVertices; + RwTexture *texture = nil; + + GetTextureCorners(x, y, worldPoly); + ClipRadarTileCoords(x, y); + + assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])); + txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict; + if (txd) + texture = GetFirstTexture(txd); + if (texture == nil) + return; + + for (i = 0; i < 4; i++) + TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]); + + numVertices = ClipRadarPoly(radarPoly, radarCorners); + + // FIX: can return earlier here +// if(numVertices == 0) + if (numVertices < 3) + return; + + for (i = 0; i < numVertices; i++) { + TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]); + TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y); + TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]); + } + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); + CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); + // check done above now +// if(numVertices > 2) + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices); +} +#endif + +#if 0 +WRAPPER void CRadar::DrawRadarSprite(int32 sprite, float x, float y, int32 alpha) { EAXJMP(0x4A5EF0); } +#else +void CRadar::DrawRadarSprite(int32 sprite, float x, float y, int32 alpha) +{ + RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); +} +#endif + +#if 0 +WRAPPER void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) { EAXJMP(0x4A5D10); } +#else +void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) +{ + CVector curPosn[4]; + CVector oldPosn[4]; + + curPosn[0].x = x - SCREEN_SCALE_X(5.6f); + curPosn[0].y = y + SCREEN_SCALE_Y(5.6f); + + curPosn[1].x = x + SCREEN_SCALE_X(5.6f); + curPosn[1].y = y + SCREEN_SCALE_Y(5.6f); + + curPosn[2].x = x - SCREEN_SCALE_X(5.6f); + curPosn[2].y = y - SCREEN_SCALE_Y(5.6f); + + curPosn[3].x = x + SCREEN_SCALE_X(5.6f); + curPosn[3].y = y - SCREEN_SCALE_Y(5.6f); + + for (uint32 i = 0; i < 4; i++) { + oldPosn[i] = curPosn[i]; + + curPosn[i].x = x + (oldPosn[i].x - x) * cosf(angle) + (oldPosn[i].y - y) * sinf(angle); + curPosn[i].y = y - (oldPosn[i].x - x) * sinf(angle) + (oldPosn[i].y - y) * cosf(angle); + } + + sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha)); +} +#endif + +#if 1 +WRAPPER int32 CRadar::GetActualBlipArray(int32) { EAXJMP(0x4A41C0); } +#else +int32 CRadar::GetActualBlipArray(int32 i) +{ + return int32(); +} +#endif + +#if 1 +WRAPPER int32 CRadar::GetNewUniqueBlipIndex(int32) { EAXJMP(0x4A4180); } +#else +int32 CRadar::GetNewUniqueBlipIndex(int32 i) +{ + return int32(); +} +#endif + +#if 0 +WRAPPER int32 CRadar::GetRadarTraceColour(int32 color, bool bright) { EAXJMP(0x4A5BB0); } +#else +int32 CRadar::GetRadarTraceColour(int32 color, bool bright) +{ + int32 c; switch (color) { case 0: if (bright) - return CRGBA(113, 43, 73, 255); + c = 0x712B49FF; else - return CRGBA(127, 0, 0, 255); + c = 0x7F0000FF; + break; case 1: if (bright) - return CRGBA(95, 160, 106, 255); + c = 0x5FA06AFF; else - return CRGBA(127, 0, 255, 255); + c = 0x7F00FF; + break; case 2: if (bright) - return CRGBA(128, 167, 243, 255); + c = 0x80A7F3FF; else - return CRGBA(0, 127, 255, 255); + c = 0x007FFF; + break; case 3: if (bright) - return CRGBA(225, 225, 225, 255); + c = 0xE1E1E1FF; else - return CRGBA(127, 127, 127, 255); + c = 0x7F7F7FFF; + break; case 4: if (bright) - return CRGBA(255, 225, 0, 255); + c = 0xFFFF00FF; else - return CRGBA(127, 127, 0, 255); + c = 0x7F7F00FF; + break; case 5: if (bright) - return CRGBA(255, 0, 255, 255); + c = 0xFF00FFFF; else - return CRGBA(127, 0, 127, 255); + c = 0x7F007FFF; + break; case 6: if (bright) - return CRGBA(255, 255, 255, 255); + c = 0xFFFFFF; else - return CRGBA(127, 127, 255, 255); + c = 0x7F7FFF; + break; default: - return CRGBA(0, 0, 0, 255); - } + c = color; + break; + }; + return c; } +#endif -// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) -void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) +#if 0 +WRAPPER void CRadar::Initialise() { EAXJMP(0x4A3EF0); } +#else +void CRadar::Initialise() { - // FIX: game doesn't scale RADAR_LEFT here - out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); - out.y = (1.0f - in.y)*0.5f*SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT); + } +#endif #if 0 -WRAPPER void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A50D0); } +WRAPPER float CRadar::LimitRadarPoint(CVector2D &point) { EAXJMP(0x4A4F30); } #else -void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) +float CRadar::LimitRadarPoint(CVector2D &point) { - float s, c; - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { - s = 0.0f; - c = 1.0f; - } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { - s = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - } else { - CVector forward; - - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); - forward.Normalise(); // a bit useless... - } else - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + float dist, invdist; - s = sin(atan2(-forward.x, forward.y)); - c = cos(atan2(-forward.x, forward.y)); + dist = point.Magnitude(); + if (dist > 1.0f) { + invdist = 1.0f / dist; + point.x *= invdist; + point.y *= invdist; } + return dist; +} +#endif - float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); - float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); +#if 0 +WRAPPER void CRadar::LoadAllRadarBlips() { EAXJMP(0x4A6F30); } +#else +void CRadar::LoadAllRadarBlips(int32) +{ - out.x = s * y + c * x; - out.y = c * y - s * x; } #endif #if 0 -WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } +WRAPPER void CRadar::LoadTextures() { EAXJMP(0x4A4030); } #else -void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) +void CRadar::LoadTextures() { - float s, c; - s = -sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); +} +#endif - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { - s = 0.0f; - c = 1.0f; - } else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { - CVector forward; +#if 0 +WRAPPER void CRadar::RemoveRadarSections() { EAXJMP(0x00); } +#else +void CRadar::RemoveRadarSections() +{ - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); - forward.Normalise(); // a bit useless... - } else - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; +} +#endif - s = -sin(atan2(-forward.x, forward.y)); - c = cos(atan2(-forward.x, forward.y)); - } +#if 0 +WRAPPER void CRadar::RemoveMapSection(int32, int32) { EAXJMP(0x00); } +#else +void CRadar::RemoveMapSection(int32 x, int32 y) +{ + if (x >= 0 && x <= 7 && y >= 0 && y <= 7) + CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]); +} +#endif - out.x = s * in.y + c * in.x; - out.y = c * in.y - s * in.x; +#if 0 +WRAPPER void CRadar::RequestMapSection(int32, int32) { EAXJMP(0x00); } +#else +void CRadar::RequestMapSection(int32 x, int32 y) +{ + ClipRadarTileCoords(x, y); + CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY); +} +#endif + +#if 0 +WRAPPER void CRadar::SaveAllRadarBlips(int32) { EAXJMP(0x00); } +#else +void CRadar::SaveAllRadarBlips(int32) +{ - out = out*m_RadarRange + vec2DRadarOrigin; } #endif #if 0 -WRAPPER void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) { EAXJMP(0x4A5EF0); } +WRAPPER void CRadar::SetBlipSprite(int32, int32) { EAXJMP(0x00); } #else -void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) +void CRadar::SetBlipSprite(int32 i, int32 icon) { - RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); + } #endif #if 0 -WRAPPER void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) { EAXJMP(0x4A5870); } +WRAPPER void CRadar::SetCoordBlip(int32, CVector, int32) { EAXJMP(0x00); } #else -void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) +int CRadar::SetCoordBlip(int32 type, CVector pos, int32 flag) { - CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha)); - CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); + return 0; +} +#endif + +#if 0 +WRAPPER void CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { EAXJMP(0x00); } +#else +int CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) +{ + return 0; } #endif #if 0 -WRAPPER void CRadar::ShowRadarMarker(CVector pos, CRGBA color, float radius) { EAXJMP(0x4A59C0); } +WRAPPER void CRadar::SetRadarMarkerState(int32, int32) { EAXJMP(0x4A5C60); } #else -void CRadar::ShowRadarMarker(CVector pos, CRGBA color, float radius) { +void CRadar::SetRadarMarkerState(int32 counter, int32 flag) +{ + CEntity *e; + switch (ms_RadarTrace[counter].m_eBlipType) { + case BLIP_CAR: + e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); + break; + case BLIP_CHAR: + e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); + break; + case BLIP_OBJECT: + e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); + break; + default: + return; + } + + if (e) + e->bHasBlip = flag; +} +#endif + +#if 0 +WRAPPER void CRadar::ShowRadarMarker(CVector pos, int16 color, float radius) { EAXJMP(0x4A59C0); } +#else +void CRadar::ShowRadarMarker(CVector pos, int16 color, float radius) { float f1 = radius * 0.5f; float f2 = radius * 1.4f; CVector p1, p2; p1 = pos + TheCamera.GetUp()*f1; p2 = pos + TheCamera.GetUp()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); p1 = pos - TheCamera.GetUp()*f1; p2 = pos - TheCamera.GetUp()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); p1 = pos + TheCamera.GetRight()*f1; p2 = pos + TheCamera.GetRight()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); p1 = pos - TheCamera.GetRight()*f1; p2 = pos - TheCamera.GetRight()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); +} +#endif + +#if 0 +WRAPPER void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) { EAXJMP(0x4A5870); } +#else +void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) +{ + CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha)); + CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); } #endif #if 0 -WRAPPER void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha) { EAXJMP(0x4A5D10); } +WRAPPER void CRadar::Shutdown() { EAXJMP(0x4A3F60); } #else -void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha) +void CRadar::Shutdown() { - CVector curPosn[4]; - CVector oldPosn[4]; - curPosn[0].x = x - SCREEN_SCALE_X(5.6f); - curPosn[0].y = y + SCREEN_SCALE_Y(5.6f); +} +#endif - curPosn[1].x = x + SCREEN_SCALE_X(5.6f); - curPosn[1].y = y + SCREEN_SCALE_Y(5.6f); +#if 0 +WRAPPER void CRadar::StreamRadarSections() { EAXJMP(0x4A6B60); } +#else +void CRadar::StreamRadarSections(CVector posn) +{ - curPosn[2].x = x - SCREEN_SCALE_X(5.6f); - curPosn[2].y = y - SCREEN_SCALE_Y(5.6f); +} +#endif - curPosn[3].x = x + SCREEN_SCALE_X(5.6f); - curPosn[3].y = y - SCREEN_SCALE_Y(5.6f); +#if 0 +WRAPPER void CRadar::StreamRadarSections(int32 x, int32 y) { EAXJMP(0x4A6100); } +#else +void CRadar::StreamRadarSections(int32 x, int32 y) +{ + for (int i = 0; i < RADAR_NUM_TILES; ++i) { + for (int j = 0; j < RADAR_NUM_TILES; ++j) { + if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1)) + RequestMapSection(i, j); + else + RemoveMapSection(i, j); + }; + }; +} +#endif - for (uint32 i = 0; i < 4; i++) { - oldPosn[i] = curPosn[i]; +#if 0 +WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y) { EAXJMP(0x4A5530); } +#else +void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y) +{ + out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X); + out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y)); + out.x /= RADAR_TILE_SIZE; + out.y /= RADAR_TILE_SIZE; +} +#endif - curPosn[i].x = x + (oldPosn[i].x - x) * cosf(angle) + (oldPosn[i].y - y) * sinf(angle); - curPosn[i].y = y - (oldPosn[i].x - x) * sinf(angle) + (oldPosn[i].y - y) * cosf(angle); - } +#if 0 +WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } +#else +void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) +{ + float s, c; - sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha)); + s = -sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { + s = 0.0f; + c = 1.0f; + } + else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { + CVector forward; + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); + forward.Normalise(); // a bit useless... + } + else + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + + s = -sin(atan2(-forward.x, forward.y)); + c = cos(atan2(-forward.x, forward.y)); + } + + out.x = s * in.y + c * in.x; + out.y = c * in.y - s * in.x; + + out = out * m_RadarRange + vec2DRadarOrigin; } -#endif +#endif -bool CRadar::DisplayThisBlip(int counter) +// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) +void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) { - switch (ms_RadarTrace[counter].m_IconID) { - case RADAR_SPRITE_BOMB: - case RADAR_SPRITE_SPRAY: - case RADAR_SPRITE_WEAPON: - return true; - default: - return false; + // FIX: game doesn't scale RADAR_LEFT here + out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); + out.y = (1.0f - in.y)*0.5f*SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT); +} + +#if 0 +WRAPPER void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A50D0); } +#else +void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) +{ + float s, c; + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { + s = 0.0f; + c = 1.0f; + } + else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { + s = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + } + else { + CVector forward; + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); + forward.Normalise(); // a bit useless... + } + else + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + + s = sin(atan2(-forward.x, forward.y)); + c = cos(atan2(-forward.x, forward.y)); } + + float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); + float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); + + out.x = s * y + c * x; + out.y = c * y - s * x; } +#endif #if 0 -WRAPPER void CRadar::GetTextureCorners(int x, int y, CVector2D *out) { EAXJMP(0x4A61C0); }; +WRAPPER void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out) { EAXJMP(0x4A61C0); }; #else // Transform from section indices to world coordinates -void CRadar::GetTextureCorners(int x, int y, CVector2D *out) +void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out) { x = x - RADAR_NUM_TILES/2; y = -(y - RADAR_NUM_TILES/2); @@ -854,7 +966,10 @@ void CRadar::GetTextureCorners(int x, int y, CVector2D *out) } #endif -void CRadar::ClipRadarTileCoords(int &x, int &y) +#if 0 +WRAPPER void CRadar::ClipRadarTileCoords(int32 &, int32 &) { EAXJMP(0x00); }; +#else +void CRadar::ClipRadarTileCoords(int32 &x, int32 &y) { if (x < 0) x = 0; @@ -865,6 +980,95 @@ void CRadar::ClipRadarTileCoords(int &x, int &y) if (y > RADAR_NUM_TILES-1) y = RADAR_NUM_TILES-1; } +#endif + + +#if 0 +WRAPPER bool CRadar::IsPointInsideRadar(const CVector2D &) { EAXJMP(0x4A6160); } +#else +bool CRadar::IsPointInsideRadar(const CVector2D &point) +{ + if (point.x < -1.0f || point.x > 1.0f) return false; + if (point.y < -1.0f || point.y > 1.0f) return false; + return true; +} +#endif + +// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1 +#if 0 +WRAPPER int CRadar::LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &) { EAXJMP(0x4A6250); } +#else +int CRadar::LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2) +{ + float d1, d2; + float t; + float x, y; + float shortest = 1.0f; + int edge = -1; + + // clip against left edge, x = -1.0 + d1 = -1.0f - p1.x; + d2 = -1.0f - p2.x; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + y = (p2.y - p1.y)*t + p1.y; + if (y >= -1.0f && y <= 1.0f && t <= shortest) { + out.x = -1.0f; + out.y = y; + edge = 3; + shortest = t; + } + } + + // clip against right edge, x = 1.0 + d1 = p1.x - 1.0f; + d2 = p2.x - 1.0f; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + y = (p2.y - p1.y)*t + p1.y; + if (y >= -1.0f && y <= 1.0f && t <= shortest) { + out.x = 1.0f; + out.y = y; + edge = 1; + shortest = t; + } + } + + // clip against top edge, y = -1.0 + d1 = -1.0f - p1.y; + d2 = -1.0f - p2.y; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + x = (p2.x - p1.x)*t + p1.x; + if (x >= -1.0f && x <= 1.0f && t <= shortest) { + out.y = -1.0f; + out.x = x; + edge = 0; + shortest = t; + } + } + + // clip against bottom edge, y = 1.0 + d1 = p1.y - 1.0f; + d2 = p2.y - 1.0f; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + x = (p2.x - p1.x)*t + p1.x; + if (x >= -1.0f && x <= 1.0f && t <= shortest) { + out.y = 1.0f; + out.x = x; + edge = 2; + shortest = t; + } + } + + return edge; +} +#endif STARTPATCHES // InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP); @@ -892,12 +1096,12 @@ STARTPATCHES // InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP); InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP); InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP); - InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP); + //InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP); InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP); InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP); InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP); // InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP); - InjectHook(0x4A6100, CRadar::StreamRadarSections, PATCH_JUMP); +// InjectHook(0x4A6100, CRadar::StreamRadarSections, PATCH_JUMP); InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP); InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP); InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP); @@ -907,6 +1111,6 @@ STARTPATCHES // InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP); InjectHook(0x4A61C0, CRadar::GetTextureCorners, PATCH_JUMP); - InjectHook(0x4A6160, IsPointInsideRadar, PATCH_JUMP); - InjectHook(0x4A6250, LineRadarBoxCollision, PATCH_JUMP); + InjectHook(0x4A6160, CRadar::IsPointInsideRadar, PATCH_JUMP); + InjectHook(0x4A6250, CRadar::LineRadarBoxCollision, PATCH_JUMP); ENDPATCHES diff --git a/src/Radar.h b/src/Radar.h index dec07667..5943498f 100644 --- a/src/Radar.h +++ b/src/Radar.h @@ -96,32 +96,51 @@ public: static CSprite2d *RadarSprites[21]; public: - static void ClearBlipForEntity(eBlipType type, int32 id); - static void Draw3dMarkers(); - static void DrawMap(); - static void StreamRadarSections(int x, int y); + static int CalculateBlipAlpha(float dist); + static void ChangeBlipBrightness(int32 i, int32 bright); + static void ChangeBlipColour(int32 i); + static void ChangeBlipDisplay(int32 i, int16 flag); + static void ChangeBlipScale(int32 i, int16 scale); + static void ClearBlip(int32 i); + static void ClearBlipForEntity(int16 type, int32 id); static int ClipRadarPoly(CVector2D *out, const CVector2D *in); - static void DrawRadarSection(int x, int y); - static void RequestMapSection(int x, int y); - static void RemoveMapSection(int x, int y); + static bool DisplayThisBlip(int32 i); + static void Draw3dMarkers(); static void DrawBlips(); - static int CalculateBlipAlpha(float dist); - static CRGBA GetRadarTraceColour(uint32 color, bool bright); + static void DrawMap(); static void DrawRadarMap(); - static void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha); + static void DrawRadarMask(); + static void DrawRadarSection(int32 x, int32 y); + static void DrawRadarSprite(int32 sprite, float x, float y, int32 alpha); + static void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha); + static int32 GetActualBlipArray(int32 i); + static int32 GetNewUniqueBlipIndex(int32 i); + static int32 GetRadarTraceColour(int32 color, bool bright); + static void Initialise(); static float LimitRadarPoint(CVector2D &point); - static void DrawRadarSprite(int sprite, float x, float y, int alpha); - static void ShowRadarMarker(CVector pos, CRGBA color, float radius); + static void LoadAllRadarBlips(int32); + static void LoadTextures(); + static void RemoveRadarSections(); + static void RemoveMapSection(int32 x, int32 y); + static void RequestMapSection(int32 x, int32 y); + static void SaveAllRadarBlips(int32); + static void SetBlipSprite(int32 i, int32 icon); + static int SetCoordBlip(int32 type, CVector pos, int32 flag); + static int SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag); + static void SetRadarMarkerState(int32 i, int32 flag); + static void ShowRadarMarker(CVector pos, int16 color, float radius); static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha); - static void DrawRadarMask(); - static void SetRadarMarkerState(int counter, int flag); - static bool DisplayThisBlip(int counter); - static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y); + static void Shutdown(); + static void StreamRadarSections(CVector posn); + static void StreamRadarSections(int32 x, int32 y); + static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y); static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in); static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in); static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in); // no in CRadar in the game: - static void GetTextureCorners(int x, int y, CVector2D *out); - static void ClipRadarTileCoords(int &x, int &y); + static void GetTextureCorners(int32 x, int32 y, CVector2D *out); + static void ClipRadarTileCoords(int32 &x, int32 &y); + static bool IsPointInsideRadar(const CVector2D &); + static int LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &); }; diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index c320ea94..b96bee01 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -18,3 +18,5 @@ WRAPPER void cDMAudio::ChangeMusicMode(uint8 mode) { EAXJMP(0x57CCF0); } WRAPPER void cDMAudio::PlayFrontEndSound(uint32, uint32) { EAXJMP(0x57CC20); } WRAPPER void cDMAudio::PlayOneShot(int, uint16, float) { EAXJMP(0x57C840); } +WRAPPER int cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); } +WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); }
\ No newline at end of file diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 3ebeaad8..ad67cf13 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -189,5 +189,7 @@ public: void ChangeMusicMode(uint8 mode); void PlayFrontEndSound(uint32, uint32); void PlayOneShot(int, uint16, float); + int GetRadioInCar(); + uint8 IsMP3RadioChannelAvailable(); }; extern cDMAudio &DMAudio; diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index f9c02739..6f2d3d86 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -16,6 +16,8 @@ int32 &gNumRetunePresses = *(int32*)0x650B80; wchar *pCurrentStation = (wchar*)0x650B9C; uint8 &cDisplay = *(uint8*)0x650BA1; +WRAPPER char* cMusicManager::Get3DProviderName(char) { EAXJMP(0x57A8C0); } + bool cMusicManager::PlayerInCar() { if (!FindPlayerVehicle()) diff --git a/src/audio/MusicManager.h b/src/audio/MusicManager.h index 644c3df3..dcb34daf 100644 --- a/src/audio/MusicManager.h +++ b/src/audio/MusicManager.h @@ -264,6 +264,7 @@ public: uint8 field_2395; public: + char *Get3DProviderName(char); bool PlayerInCar(); void DisplayRadioStationName(); }; diff --git a/src/config.h b/src/config.h index 7c228e60..1cd532ee 100644 --- a/src/config.h +++ b/src/config.h @@ -69,3 +69,4 @@ enum Config { //#define NO_CDCHECK #define NO_MOVIES //#define USE_MY_DOCUMENTS +#define NASTY_GAME
\ No newline at end of file diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 70a15476..d601db8e 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -68,7 +68,7 @@ WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); } #else void CGarages::PrintMessages() { - if (CTimer::GetTimeInMilliseconds() > CGarages::MessageStartTime && CTimer::GetTimeInMilliseconds() < CGarages::MessageEndTime) { + if (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) { CFont::SetScale(SCREEN_SCALE_X(1.2f / 2), SCREEN_SCALE_Y(1.5f / 2)); // BUG: game doesn't use macro here. CFont::SetPropOn(); CFont::SetJustifyOff(); @@ -77,16 +77,16 @@ void CGarages::PrintMessages() CFont::SetCentreOn(); CFont::SetFontStyle(FONT_BANK); - if (CGarages::MessageNumberInString2 < 0) { - if (CGarages::MessageNumberInString < 0) { + if (MessageNumberInString2 < 0) { + if (MessageNumberInString < 0) { CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString((SCREEN_WIDTH/ 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(CGarages::MessageIDString)); + CFont::PrintString((SCREEN_WIDTH/ 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(MessageIDString)); CFont::SetColor(CRGBA(89, 115, 150, 255)); - CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(CGarages::MessageIDString)); + CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(MessageIDString)); } else { - CMessages::InsertNumberInString(TheText.Get(CGarages::MessageIDString), CGarages::MessageNumberInString, -1, -1, -1, -1, -1, gUString); + CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f + 2.0 - 40.0f), gUString); @@ -96,7 +96,7 @@ void CGarages::PrintMessages() } } else { - CMessages::InsertNumberInString(TheText.Get(CGarages::MessageIDString), CGarages::MessageNumberInString2, -1, -1, -1, -1, -1, gUString); + CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f + 2.0 - 40.0f), gUString); diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index a8d87302..a3d8ff1b 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -11,6 +11,8 @@ #include "CutsceneMgr.h" #include "Timer.h" #include "Weather.h" +#include "Font.h" +#include "Text.h" uint8 &CReplay::Mode = *(uint8*)0x95CD5B; CAddressInReplayBuffer &CReplay::Record = *(CAddressInReplayBuffer*)0x942F7C; @@ -223,7 +225,6 @@ WRAPPER bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buf WRAPPER void CReplay::FinishPlayback(void) { EAXJMP(0x595B20); } WRAPPER void CReplay::Shutdown(void) { EAXJMP(0x595BD0); } WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); } -WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } WRAPPER void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) { EAXJMP(0x596030); } WRAPPER void CReplay::StoreStuffInMem(void) { EAXJMP(0x5961F0); } WRAPPER void CReplay::RestoreStuffFromMem(void) { EAXJMP(0x5966E0); } @@ -238,6 +239,23 @@ WRAPPER bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); } WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); } +#if 0 +WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } +#else +void CReplay::Display() +{ + if (CReplay::IsPlayingBack() && CTimer::GetFrameCounter() + 1 & 0x20) { + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetColor(CRGBA(255, 255, 200, 200)); + CFont::SetFontStyle(FONT_BANK); + CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY")); + } +} +#endif + STARTPATCHES InjectHook(0x592FC0, PrintElementsInPtrList, PATCH_JUMP); InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP); diff --git a/src/main.cpp b/src/main.cpp index f9ede02d..0dadc131 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,6 +85,7 @@ extern void (*DebugMenuProcess)(void); extern void (*DebugMenuRender)(void); void DebugMenuInit(void); +void PrintGameVersion(); RwRGBA gColourTop; @@ -154,6 +155,7 @@ Idle(void *arg) } RenderMenus(); + PrintGameVersion(); DoFade(); Render2dStuffAfterFade(); CCredits::Render(); @@ -186,6 +188,7 @@ FrontendIdle(void) DefinedState(); RenderMenus(); + PrintGameVersion(); DoFade(); Render2dStuffAfterFade(); CFont::DrawFonts(); @@ -772,6 +775,25 @@ AppEventHandler(RsEvent event, void *param) } } +void PrintGameVersion() +{ + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.5f)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_BANK); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetDropShadowPosition(0); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(CRGBA(235, 170, 50, 255)); + + strcpy(gString, "RE3"); + AsciiToUnicode(gString, gUString); + CFont::PrintString(SCREEN_SCALE_X(10.5f), SCREEN_SCALE_Y(8.0f), gUString); +} + STARTPATCHES InjectHook(0x48E480, Idle, PATCH_JUMP); InjectHook(0x48E700, FrontendIdle, PATCH_JUMP); diff --git a/src/render/Font.h b/src/render/Font.h index 2e698533..11c0f8ec 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -33,6 +33,12 @@ enum { FONT_HEADING, }; +enum { + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT, +}; + class CFont { static CFontDetails &Details; @@ -56,6 +62,7 @@ public: static void DrawFonts(void); static uint16 character_code(uint8 c); + static CFontDetails GetDetails() { return Details; } static void SetScale(float x, float y) { Details.scaleX = x; Details.scaleY = y; } static void SetSlantRefPoint(float x, float y) { Details.slantRefX = x; Details.slantRefY = y; } static void SetSlant(float s) { Details.slant = s; } @@ -86,6 +93,23 @@ public: static void SetCentreOff(void) { Details.centre = false; } + static void SetAlignment(uint8 alignment) { + if (alignment == ALIGN_LEFT) { + CFont::Details.justify = true; + CFont::Details.centre = false; + CFont::Details.rightJustify = false; + } + else if (alignment == ALIGN_CENTER) { + CFont::Details.justify = false; + CFont::Details.centre = true; + CFont::Details.rightJustify = false; + } + else if (alignment == ALIGN_RIGHT) { + CFont::Details.justify = false; + CFont::Details.centre = false; + CFont::Details.rightJustify = true; + } + } static void SetWrapx(float x) { Details.wrapX = x; } static void SetCentreSize(float s) { Details.centreSize = s; } static void SetBackgroundOn(void) { Details.background = true; } diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index a17d5c2c..9243bc3a 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -53,9 +53,9 @@ wchar *CHud::m_PagerMessage = (wchar*)0x878840; bool &CHud::m_Wants_To_Draw_Hud = *(bool*)0x95CD89; bool &CHud::m_Wants_To_Draw_3dMarkers = *(bool*)0x95CD62; wchar(*CHud::m_BigMessage)[128] = (wchar(*)[128])0x664CE0; -float *CHud::BigMessageInUse = (float*)0x862140; -float *CHud::BigMessageAlpha = (float*)0x862108; -float *CHud::BigMessageX = (float*)0x773248; +float CHud::BigMessageInUse[6]; +float CHud::BigMessageAlpha[6]; +float CHud::BigMessageX[6]; float &CHud::OddJob2OffTimer = *(float*)0x942FA0; int8 &CHud::CounterOnLastFrame = *(int8*)0x95CD67; @@ -231,8 +231,8 @@ void CHud::Draw() CRect rect; float fWidescreenOffset[2] = { 0.0f, 0.0f }; - - if (CMenuManager::m_PrefsUseWideScreen) { + + if (FrontEndMenuManager.m_PrefsUseWideScreen) { fWidescreenOffset[0] = 0.0f; fWidescreenOffset[1] = SCREEN_SCALE_Y(18.0f); } @@ -362,25 +362,32 @@ void CHud::Draw() /* DrawAmmo */ + int16 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition; int32 AmmoInClip = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoInClip; int32 TotalAmmo = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal; + int32 Ammo, Clip; - if (AmmoInClip <= 1 || AmmoInClip >= 1000) { + if (AmmoAmount <= 1 || AmmoAmount >= 1000) sprintf(sTemp, "%d", TotalAmmo); - } else { if (WeaponType == WEAPONTYPE_FLAMETHROWER) { - int tot_min_clip_div_10 = (TotalAmmo - AmmoInClip) / 10; - if (tot_min_clip_div_10 > 9999) - tot_min_clip_div_10 = 9999; + Clip = AmmoInClip / 10; - sprintf(sTemp, "%d-%d", tot_min_clip_div_10, AmmoInClip / 10); + if ((TotalAmmo - AmmoInClip) / 10 <= 9999) + Ammo = (TotalAmmo - AmmoInClip) / 10; + else + Ammo = 9999; } else { - if (AmmoInClip > 9999) - AmmoInClip = 9999; - sprintf(sTemp, "%d-%d", (TotalAmmo - AmmoInClip), AmmoInClip); + Clip = AmmoInClip; + + if (TotalAmmo - AmmoInClip > 9999) + Ammo = 9999; + else + Ammo = TotalAmmo - AmmoInClip; } + + sprintf(sTemp, "%d-%d", Ammo, Clip); } AsciiToUnicode(sTemp, sPrint); @@ -580,7 +587,7 @@ void CHud::Draw() CFont::SetPropOn(); CFont::SetBackgroundOff(); - if (CMenuManager::m_PrefsLanguage == 4) + if (FrontEndMenuManager.m_PrefsLanguage == 4) CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.8f), SCREEN_SCALE_Y(1.2f)); else CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); @@ -676,7 +683,7 @@ void CHud::Draw() CFont::SetPropOn(); CFont::SetBackgroundOff(); - if (CMenuManager::m_PrefsLanguage != 3 && CMenuManager::m_PrefsLanguage != 4) + if (FrontEndMenuManager.m_PrefsLanguage != 3 && FrontEndMenuManager.m_PrefsLanguage != 4) CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); else CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f)); @@ -976,7 +983,7 @@ void CHud::Draw() DrawBigMessage */ // MissionCompleteFailedText - if (CHud::m_BigMessage[0][0]) { + if (m_BigMessage[0][0]) { if (BigMessageInUse[0] != 0.0f) { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); @@ -1251,7 +1258,7 @@ void CHud::DrawAfterFade() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - if (CGame::frenchGame || CMenuManager::m_PrefsLanguage == 4) + if (CGame::frenchGame || FrontEndMenuManager.m_PrefsLanguage == 4) CFont::SetScale(SCREEN_SCALE_X(0.884f), SCREEN_SCALE_Y(1.36f)); else CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); diff --git a/src/render/Hud.h b/src/render/Hud.h index 8f4b6fb6..260e5312 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -62,9 +62,9 @@ public: static bool &m_Wants_To_Draw_Hud; static bool &m_Wants_To_Draw_3dMarkers; static wchar(*m_BigMessage)[128]; - static float *BigMessageInUse; - static float *BigMessageAlpha; - static float *BigMessageX; + static float BigMessageInUse[6]; + static float BigMessageAlpha[6]; + static float BigMessageX[6]; static float &OddJob2OffTimer; static int8 &CounterOnLastFrame; static float &OddJob2XOffset; diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index a8abe1dd..814cac84 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -633,8 +633,10 @@ psInitialise(void) C_PcSave::SetSaveDirectory(_psGetUserFilesFolder()); - InitialiseLanguage(); - +#ifndef NASTY_GAME + InitialiseLanguage(); +#endif + FrontEndMenuManager.LoadSettings(); gGameState = GS_START_UP; diff --git a/src/skel/win/win.h b/src/skel/win/win.h index d3b0169f..371b9e44 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -78,6 +78,8 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode); void CenterVideo(void); void CloseClip(void); +RwChar **_psGetVideoModeList(); + #ifdef __cplusplus } #endif /* __cplusplus */ |