Merge pull request #294 from MatthewBeshay/cleanup/delete-in-tree-4jlibs
Some checks are pending
Publish Documentation / build (push) Waiting to run
Build (Linux, x86_64) / build-linux (push) Waiting to run
Build (Linux, x86_64) / build-linux-debug (push) Waiting to run
Clang Format / clang-format (push) Waiting to run

Delete in-tree 4J libraries after extraction
This commit is contained in:
ffqq 2026-03-20 17:31:51 +03:00 committed by GitHub
commit 2ed79e298a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 18 additions and 12248 deletions

View file

@ -4,10 +4,6 @@ on:
push:
branches: ["dev"]
paths:
- "4J.Input/**"
- "4J.Profile/**"
- "4J.Render/**"
- "4J.Storage/**"
- "Minecraft.Assets/**"
- "Minecraft.Client/**"
- "Minecraft.World/**"

6
.gitignore vendored
View file

@ -5,12 +5,6 @@
!/.devcontainer/
!/.github/
!/.github-assets/
!/4J.Input/
!/4J.Common/
!/4J.Profile/
!/4J.Render/
!/4J.Storage/
!/4jlibs/
!/docs/
!/Minecraft.Assets/
!/Minecraft.Client/

View file

@ -1,129 +0,0 @@
#pragma once
#include <cstdint>
// The extracted 4J public headers only need the generic Linux/Windows-style
// compatibility surface. Console backends still own their platform-specific
// identity/content definitions elsewhere.
#if !defined(__ORBIS__) && !defined(__PS3__) && !defined(__PSVITA__) && \
!defined(_DURANGO)
#ifndef XUSER_INDEX_ANY
inline constexpr int XUSER_INDEX_ANY = 255;
#endif
#ifndef XUSER_MAX_COUNT
inline constexpr int XUSER_MAX_COUNT = 4;
#endif
#ifndef XUSER_NAME_SIZE
inline constexpr int XUSER_NAME_SIZE = 32;
#endif
#ifndef XUSER_INDEX_FOCUS
inline constexpr int XUSER_INDEX_FOCUS = 254;
#endif
#ifndef FOURJ_COMMON_PLAYER_UID_DEFINED
#define FOURJ_COMMON_PLAYER_UID_DEFINED
using PlayerUID = unsigned long long;
using PPlayerUID = PlayerUID*;
#endif
#endif
class CXuiStringTable;
#if !defined(__ORBIS__) && !defined(__PS3__) && !defined(__PSVITA__) && \
!defined(_DURANGO)
#ifndef XCONTENT_MAX_DISPLAYNAME_LENGTH
inline constexpr int XCONTENT_MAX_DISPLAYNAME_LENGTH = 256;
#endif
#ifndef XCONTENT_MAX_FILENAME_LENGTH
inline constexpr int XCONTENT_MAX_FILENAME_LENGTH = 256;
#endif
#ifndef FOURJ_COMMON_XCONTENT_DATA_DEFINED
#define FOURJ_COMMON_XCONTENT_DATA_DEFINED
using XCONTENTDEVICEID = int;
struct XCONTENT_DATA {
XCONTENTDEVICEID DeviceID;
std::uint32_t dwContentType;
wchar_t szDisplayName[XCONTENT_MAX_DISPLAYNAME_LENGTH];
char szFileName[XCONTENT_MAX_FILENAME_LENGTH];
};
using PXCONTENT_DATA = XCONTENT_DATA*;
#endif
#ifndef XMARKETPLACE_CONTENT_ID_LEN
inline constexpr int XMARKETPLACE_CONTENT_ID_LEN = 4;
#endif
#ifndef FOURJ_COMMON_XMARKETPLACE_DEFINED
#define FOURJ_COMMON_XMARKETPLACE_DEFINED
struct XMARKETPLACE_CONTENTOFFER_INFO {
std::uint64_t qwOfferID;
std::uint64_t qwPreviewOfferID;
std::uint32_t dwOfferNameLength;
wchar_t* wszOfferName;
std::uint32_t dwOfferType;
std::uint8_t contentId[XMARKETPLACE_CONTENT_ID_LEN];
bool fIsUnrestrictedLicense;
std::uint32_t dwLicenseMask;
std::uint32_t dwTitleID;
std::uint32_t dwContentCategory;
std::uint32_t dwTitleNameLength;
wchar_t* wszTitleName;
bool fUserHasPurchased;
std::uint32_t dwPackageSize;
std::uint32_t dwInstallSize;
std::uint32_t dwSellTextLength;
wchar_t* wszSellText;
std::uint32_t dwAssetID;
std::uint32_t dwPurchaseQuantity;
std::uint32_t dwPointsPrice;
};
using PXMARKETPLACE_CONTENTOFFER_INFO = XMARKETPLACE_CONTENTOFFER_INFO*;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_CONTENT
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_CONTENT =
0x00000002;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_GAME_DEMO
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_GAME_DEMO =
0x00000020;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_GAME_TRAILER
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_GAME_TRAILER =
0x00000040;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_THEME
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_THEME = 0x00000080;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_TILE
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_TILE = 0x00000800;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_ARCADE
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_ARCADE = 0x00002000;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_VIDEO
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_VIDEO = 0x00004000;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_CONSUMABLE
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_CONSUMABLE =
0x00010000;
#endif
#ifndef XMARKETPLACE_OFFERING_TYPE_AVATARITEM
inline constexpr std::uint32_t XMARKETPLACE_OFFERING_TYPE_AVATARITEM =
0x00100000;
#endif
#endif

View file

@ -1,59 +0,0 @@
#pragma once
enum EControllerActions {
ACTION_MENU_A,
ACTION_MENU_B,
ACTION_MENU_X,
ACTION_MENU_Y,
ACTION_MENU_UP,
ACTION_MENU_DOWN,
ACTION_MENU_RIGHT,
ACTION_MENU_LEFT,
ACTION_MENU_PAGEUP,
ACTION_MENU_PAGEDOWN,
ACTION_MENU_RIGHT_SCROLL,
ACTION_MENU_LEFT_SCROLL,
ACTION_MENU_STICK_PRESS,
ACTION_MENU_OTHER_STICK_PRESS,
ACTION_MENU_OTHER_STICK_UP,
ACTION_MENU_OTHER_STICK_DOWN,
ACTION_MENU_OTHER_STICK_LEFT,
ACTION_MENU_OTHER_STICK_RIGHT,
ACTION_MENU_PAUSEMENU,
ACTION_MENU_OK,
ACTION_MENU_CANCEL,
ACTION_MAX_MENU = ACTION_MENU_CANCEL + 1,
MINECRAFT_ACTION_JUMP,
MINECRAFT_ACTION_FORWARD,
MINECRAFT_ACTION_BACKWARD,
MINECRAFT_ACTION_LEFT,
MINECRAFT_ACTION_RIGHT,
MINECRAFT_ACTION_LOOK_LEFT,
MINECRAFT_ACTION_LOOK_RIGHT,
MINECRAFT_ACTION_LOOK_UP,
MINECRAFT_ACTION_LOOK_DOWN,
MINECRAFT_ACTION_USE,
MINECRAFT_ACTION_ACTION,
MINECRAFT_ACTION_LEFT_SCROLL,
MINECRAFT_ACTION_RIGHT_SCROLL,
MINECRAFT_ACTION_INVENTORY,
MINECRAFT_ACTION_PAUSEMENU,
MINECRAFT_ACTION_DROP,
MINECRAFT_ACTION_SNEAK_TOGGLE,
MINECRAFT_ACTION_SPRINT,
MINECRAFT_ACTION_CRAFTING,
MINECRAFT_ACTION_RENDER_THIRD_PERSON,
MINECRAFT_ACTION_GAME_INFO,
MINECRAFT_ACTION_DPAD_LEFT,
MINECRAFT_ACTION_DPAD_RIGHT,
MINECRAFT_ACTION_DPAD_UP,
MINECRAFT_ACTION_DPAD_DOWN,
MINECRAFT_ACTION_MAX,
MINECRAFT_ACTION_SPAWN_CREEPER,
MINECRAFT_ACTION_CHANGE_SKIN,
MINECRAFT_ACTION_FLY_TOGGLE,
MINECRAFT_ACTION_RENDER_DEBUG
};

View file

@ -1,26 +0,0 @@
#pragma once
#include <cstdint>
inline constexpr int TUTORIAL_PROFILE_STORAGE_BITS = 512;
inline constexpr int TUTORIAL_PROFILE_STORAGE_BYTES =
TUTORIAL_PROFILE_STORAGE_BITS / 8;
inline constexpr int MAX_FAVORITE_SKINS = 10;
inline constexpr std::uint32_t GAMESETTING_CLOUDS = 0x00000001;
inline constexpr std::uint32_t GAMESETTING_ONLINE = 0x00000002;
inline constexpr std::uint32_t GAMESETTING_FRIENDSOFFRIENDS = 0x00000008;
inline constexpr std::uint32_t GAMESETTING_DISPLAYUPDATEMSG = 0x00000030;
inline constexpr std::uint32_t GAMESETTING_BEDROCKFOG = 0x00000040;
inline constexpr std::uint32_t GAMESETTING_DISPLAYHUD = 0x00000080;
inline constexpr std::uint32_t GAMESETTING_DISPLAYHAND = 0x00000100;
inline constexpr std::uint32_t GAMESETTING_CUSTOMSKINANIM = 0x00000200;
inline constexpr std::uint32_t GAMESETTING_DEATHMESSAGES = 0x00000400;
inline constexpr std::uint32_t GAMESETTING_UISIZE = 0x00001800;
inline constexpr std::uint32_t GAMESETTING_UISIZE_SPLITSCREEN = 0x00006000;
inline constexpr std::uint32_t GAMESETTING_ANIMATEDCHARACTER = 0x00008000;
inline constexpr std::uint32_t GAMESETTING_PS3EULAREAD = 0x00010000;
inline constexpr std::uint32_t GAMESETTING_PSVITANETWORKMODEADHOC = 0x00020000;
inline constexpr unsigned char MINECRAFT_LANGUAGE_DEFAULT = 0x00;

View file

@ -1,604 +0,0 @@
#include "4J_Input.h"
#include "../4J.Common/4J_InputActions.h"
#include <SDL2/SDL.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
C_4JInput InputManager;
static const int KEY_COUNT = SDL_NUM_SCANCODES;
static const int BTN_COUNT = SDL_CONTROLLER_BUTTON_MAX;
static const int AXS_COUNT = SDL_CONTROLLER_AXIS_MAX;
static const float MOUSE_SCALE = 0.015f;
// Vars
static bool s_sdlInitialized = false;
static bool s_keysCurrent[KEY_COUNT] = {};
static bool s_keysPrev[KEY_COUNT] = {};
static bool s_btnsCurrent[BTN_COUNT] = {};
static bool s_btnsPrev[BTN_COUNT] = {};
static bool s_axisCurrent[AXS_COUNT] = {};
static bool s_axisPrev[AXS_COUNT] = {};
static float axisVal[AXS_COUNT] = {};
static bool s_mouseLeftCurrent = false, s_mouseLeftPrev = false;
static bool s_mouseRightCurrent = false, s_mouseRightPrev = false;
static bool s_menuDisplayed[4] = {};
static bool s_prevMenuDisplayed = false;
static bool s_snapTaken = false;
static float s_accumRelX = 0, s_accumRelY = 0;
static float s_snapRelX = 0, s_snapRelY = 0;
static int s_mouseX = 0, s_mouseY = 0;
static int s_scrollTicksForButtonPressed = 0;
static int s_scrollTicksForGetValue = 0;
static int s_scrollTicksSnap = 0;
static bool s_scrollSnapTaken = false;
// We set all the watched keys
// I don't know if I'll need to change this if we add chat support soon.
static const int s_watchedKeys[] = {
SDL_SCANCODE_W, SDL_SCANCODE_A, SDL_SCANCODE_S,
SDL_SCANCODE_D, SDL_SCANCODE_SPACE, SDL_SCANCODE_LSHIFT,
SDL_SCANCODE_RSHIFT, SDL_SCANCODE_E, SDL_SCANCODE_Q,
SDL_SCANCODE_F, SDL_SCANCODE_C, SDL_SCANCODE_ESCAPE,
SDL_SCANCODE_RETURN, SDL_SCANCODE_F3, SDL_SCANCODE_F5,
SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT,
SDL_SCANCODE_RIGHT, SDL_SCANCODE_PAGEUP, SDL_SCANCODE_PAGEDOWN,
SDL_SCANCODE_TAB, SDL_SCANCODE_LCTRL, SDL_SCANCODE_RCTRL,
SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3,
SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6,
SDL_SCANCODE_7, SDL_SCANCODE_8, SDL_SCANCODE_9,
SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_C,
SDL_SCANCODE_V};
static const int s_watchedKeyCount =
(int)(sizeof(s_watchedKeys) / sizeof(s_watchedKeys[0]));
static inline bool KDown(int sc) {
return (sc > 0 && sc < KEY_COUNT) ? s_keysCurrent[sc] : false;
}
static inline bool KPressed(int sc) {
return (sc > 0 && sc < KEY_COUNT) ? !s_keysPrev[sc] && s_keysCurrent[sc]
: false;
}
static inline bool KReleased(int sc) {
return (sc > 0 && sc < KEY_COUNT) ? s_keysPrev[sc] && !s_keysCurrent[sc]
: false;
}
static inline bool MouseLDown() { return s_mouseLeftCurrent; }
static inline bool MouseLPressed() {
return s_mouseLeftCurrent && !s_mouseLeftPrev;
}
static inline bool MouseLReleased() {
return !s_mouseLeftCurrent && s_mouseLeftPrev;
}
static inline bool MouseRDown() { return s_mouseRightCurrent; }
static inline bool MouseRPressed() {
return s_mouseRightCurrent && !s_mouseRightPrev;
}
static inline bool MouseRReleased() {
return !s_mouseRightCurrent && s_mouseRightPrev;
}
// holds controller object
static SDL_GameController* controller = nullptr;
// Watched controller buttons set
static const SDL_GameControllerButton s_watchedBtns[] = {
SDL_CONTROLLER_BUTTON_A,
SDL_CONTROLLER_BUTTON_B,
SDL_CONTROLLER_BUTTON_X,
SDL_CONTROLLER_BUTTON_Y,
SDL_CONTROLLER_BUTTON_BACK,
SDL_CONTROLLER_BUTTON_GUIDE,
SDL_CONTROLLER_BUTTON_START,
SDL_CONTROLLER_BUTTON_LEFTSTICK,
SDL_CONTROLLER_BUTTON_RIGHTSTICK,
SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
SDL_CONTROLLER_BUTTON_DPAD_UP,
SDL_CONTROLLER_BUTTON_DPAD_DOWN,
SDL_CONTROLLER_BUTTON_DPAD_LEFT,
SDL_CONTROLLER_BUTTON_DPAD_RIGHT};
static const int s_watchedBtnsCount =
(int)(sizeof(s_watchedBtns) / sizeof(s_watchedBtns[0]));
static inline bool CDown(int cb) {
return (cb >= 0 && cb < BTN_COUNT) ? s_btnsCurrent[cb] : false;
}
static inline bool CPressed(int cb) {
return (cb >= 0 && cb < BTN_COUNT) ? !s_btnsPrev[cb] && s_btnsCurrent[cb]
: false;
}
static inline bool CReleased(int cb) {
return (cb >= 0 && cb < BTN_COUNT) ? s_btnsPrev[cb] && !s_btnsCurrent[cb]
: false;
}
// Sets controller dead zone
static int deadZone = 8000;
// Watched controller axes set
static const SDL_GameControllerAxis s_watchedAxis[] = {
SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY,
SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTY,
SDL_CONTROLLER_AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT};
static const int s_watchedAxisCount =
(int)(sizeof(s_watchedAxis) / sizeof(s_watchedAxis[0]));
static inline bool ADown(int ca) {
return (ca >= 0 && ca < AXS_COUNT) ? s_axisCurrent[ca] : false;
}
static inline bool APressed(int ca) {
return (ca >= 0 && ca < AXS_COUNT) ? !s_axisPrev[ca] && s_axisCurrent[ca]
: false;
}
static inline bool AReleased(int ca) {
return (ca >= 0 && ca < AXS_COUNT) ? s_axisPrev[ca] && !s_axisCurrent[ca]
: false;
}
// get directly into SDL events before the game queue can steal them.
// this took me a while.
static int SDLCALL EventWatcher(void*, SDL_Event* e) {
if (e->type == SDL_MOUSEWHEEL) {
int y = e->wheel.y;
if (e->wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
y = -y;
}
s_scrollTicksForGetValue += y;
s_scrollTicksForButtonPressed += y;
} else if (e->type == SDL_MOUSEBUTTONDOWN) {
if (e->button.button == 4) {
s_scrollTicksForGetValue++;
s_scrollTicksForButtonPressed++;
} else if (e->button.button == 5) {
s_scrollTicksForGetValue--;
s_scrollTicksForButtonPressed--;
}
} else if (e->type == SDL_MOUSEMOTION) {
s_accumRelX += (float)e->motion.xrel;
s_accumRelY += (float)e->motion.yrel;
} else if (e->type == SDL_CONTROLLERDEVICEADDED) { // Will search for
// controller if none
for (int i = 0; i < SDL_NumJoysticks(); i++) {
if (SDL_IsGameController(i)) {
controller = SDL_GameControllerOpen(i);
break;
}
}
} else if (controller) { // only checks when a controller exists
if (e->type == SDL_CONTROLLERDEVICEREMOVED) {
SDL_Joystick* joy = SDL_GameControllerGetJoystick(controller);
if (SDL_JoystickInstanceID(joy) == e->cdevice.which) {
SDL_GameControllerClose(controller);
controller = nullptr;
}
} else if (e->type == SDL_CONTROLLERBUTTONDOWN) {
if (e->cbutton.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) {
s_scrollTicksForGetValue++;
s_scrollTicksForButtonPressed++;
} else if (e->cbutton.button ==
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
s_scrollTicksForGetValue--;
s_scrollTicksForButtonPressed--;
}
}
}
return 1;
}
static int ScrollSnap() {
if (!s_scrollSnapTaken) {
s_scrollTicksSnap = s_scrollTicksForButtonPressed;
s_scrollTicksForButtonPressed = 0;
s_scrollSnapTaken = true;
}
return s_scrollTicksSnap;
}
static void TakeSnapIfNeeded() {
if (!s_snapTaken) {
s_snapRelX = s_accumRelX;
s_accumRelX = 0;
s_snapRelY = s_accumRelY;
s_accumRelY = 0;
s_snapTaken = true;
}
}
// We initialize the SDL input
void C_4JInput::Initialise(int, unsigned char, unsigned char, unsigned char) {
if (!s_sdlInitialized) {
if (SDL_WasInit(SDL_INIT_VIDEO) == 0) {
SDL_Init(SDL_INIT_VIDEO);
}
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0) {
SDL_Init(SDL_INIT_GAMECONTROLLER);
}
SDL_AddEventWatch(EventWatcher, NULL);
s_sdlInitialized = true;
}
memset(s_keysCurrent, 0, sizeof(s_keysCurrent));
memset(s_keysPrev, 0, sizeof(s_keysPrev));
memset(s_btnsCurrent, 0, sizeof(s_btnsCurrent));
memset(s_btnsPrev, 0, sizeof(s_btnsPrev));
memset(s_axisCurrent, 0, sizeof(s_axisCurrent));
memset(s_axisPrev, 0, sizeof(s_axisPrev));
memset(s_menuDisplayed, 0, sizeof(s_menuDisplayed));
s_mouseLeftCurrent = s_mouseLeftPrev = s_mouseRightCurrent =
s_mouseRightPrev = false;
s_accumRelX = s_accumRelY = s_snapRelX = s_snapRelY = 0;
// i really gotta name these vars better..
s_scrollTicksForButtonPressed = s_scrollTicksForGetValue =
s_scrollTicksSnap = 0;
s_snapTaken = s_scrollSnapTaken = s_prevMenuDisplayed = false;
if (s_sdlInitialized) {
SDL_SetRelativeMouseMode(SDL_TRUE);
// looks for controller
for (int i = 0; i < SDL_NumJoysticks(); i++) {
if (SDL_IsGameController(i)) {
controller = SDL_GameControllerOpen(i);
break;
}
}
}
}
// Each tick we update the input state by polling SDL, this is where we get the
// kbd and mouse state.
void C_4JInput::Tick() {
if (!s_sdlInitialized) return;
memcpy(s_keysPrev, s_keysCurrent, sizeof(s_keysCurrent));
memcpy(s_btnsPrev, s_btnsCurrent, sizeof(s_btnsCurrent));
memcpy(s_axisPrev, s_axisCurrent, sizeof(s_axisCurrent));
s_mouseLeftPrev = s_mouseLeftCurrent;
s_mouseRightPrev = s_mouseRightCurrent;
s_snapTaken = false;
s_scrollSnapTaken = false;
s_snapRelX = s_snapRelY = 0;
s_scrollTicksSnap = 0;
SDL_PumpEvents();
if (s_menuDisplayed[0]) {
s_scrollTicksForGetValue = 0;
}
const Uint8* state = SDL_GetKeyboardState(NULL);
for (int i = 0; i < s_watchedKeyCount; ++i) {
int sc = s_watchedKeys[i];
if (sc > 0 && sc < KEY_COUNT) s_keysCurrent[sc] = state[sc] != 0;
}
Uint32 btns = SDL_GetMouseState(&s_mouseX, &s_mouseY);
s_mouseLeftCurrent = (btns & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;
s_mouseRightCurrent = (btns & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
if (!SDL_GetRelativeMouseMode()) {
s_accumRelX = 0;
s_accumRelY = 0;
}
if (!SDL_GetKeyboardFocus()) {
SDL_Window* mf = SDL_GetMouseFocus();
if (mf) {
SDL_RaiseWindow(mf);
SDL_SetWindowGrab(mf, SDL_TRUE);
}
}
// If there is a controller update the buttons and sticks
if (controller) {
for (int i = 0; i < s_watchedBtnsCount; ++i) {
int cb = s_watchedBtns[i];
if (cb >= 0 && cb < BTN_COUNT)
s_btnsCurrent[cb] =
SDL_GameControllerGetButton(controller, s_watchedBtns[i]);
}
for (int i = 0; i < s_watchedAxisCount; ++i) {
int ca = s_watchedAxis[i];
if (ca >= 0 && ca < AXS_COUNT) {
int aVal =
SDL_GameControllerGetAxis(controller, s_watchedAxis[i]);
if (s_watchedAxis[i] == SDL_CONTROLLER_AXIS_TRIGGERLEFT ||
s_watchedAxis[i] == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
s_axisCurrent[ca] = aVal > deadZone;
else {
s_axisCurrent[ca] = (aVal > deadZone || aVal < -deadZone);
axisVal[ca] = aVal / 32768.0f;
}
}
}
}
}
int C_4JInput::GetHotbarSlotPressed(int iPad) {
if (iPad != 0) return -1;
constexpr size_t NUM_HOTBAR_SLOTS = 9;
static const int sc[NUM_HOTBAR_SLOTS] = {
SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3,
SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6,
SDL_SCANCODE_7, SDL_SCANCODE_8, SDL_SCANCODE_9,
};
static bool s_wasDown[NUM_HOTBAR_SLOTS] = {};
for (int i = 0; i < NUM_HOTBAR_SLOTS; ++i) {
bool down = KDown(sc[i]);
bool pressed = down && !s_wasDown[i];
s_wasDown[i] = down;
if (pressed) return i;
}
return -1;
}
// KFN = Keyboard functions, CFN = Controller functions, AFN = Axis functions
#define ACTION_CASES(KFN, CFN, AFN) \
case ACTION_MENU_UP: \
return KFN(SDL_SCANCODE_UP) || CFN(SDL_CONTROLLER_BUTTON_DPAD_UP); \
case ACTION_MENU_DOWN: \
return KFN(SDL_SCANCODE_DOWN) || CFN(SDL_CONTROLLER_BUTTON_DPAD_DOWN); \
case ACTION_MENU_LEFT: \
return KFN(SDL_SCANCODE_LEFT) || CFN(SDL_CONTROLLER_BUTTON_DPAD_LEFT); \
case ACTION_MENU_RIGHT: \
return KFN(SDL_SCANCODE_RIGHT) || \
CFN(SDL_CONTROLLER_BUTTON_DPAD_RIGHT); \
case ACTION_MENU_PAGEUP: \
return KFN(SDL_SCANCODE_PAGEUP); \
case ACTION_MENU_PAGEDOWN: \
return KFN(SDL_SCANCODE_PAGEDOWN); \
case ACTION_MENU_OK: \
return KFN(SDL_SCANCODE_RETURN) || KFN(SDL_SCANCODE_Z) || \
CFN(SDL_CONTROLLER_BUTTON_A); \
case ACTION_MENU_CANCEL: \
return KFN(SDL_SCANCODE_ESCAPE) || KFN(SDL_SCANCODE_X) || \
CFN(SDL_CONTROLLER_BUTTON_B); \
case ACTION_MENU_A: \
return KFN(SDL_SCANCODE_Z) || KFN(SDL_SCANCODE_RETURN) || \
CFN(SDL_CONTROLLER_BUTTON_A); \
case ACTION_MENU_B: \
return KFN(SDL_SCANCODE_X) || KFN(SDL_SCANCODE_ESCAPE) || \
CFN(SDL_CONTROLLER_BUTTON_B); \
case ACTION_MENU_X: \
return KFN(SDL_SCANCODE_C) || CFN(SDL_CONTROLLER_BUTTON_X); \
case ACTION_MENU_Y: \
return KFN(SDL_SCANCODE_V) || CFN(SDL_CONTROLLER_BUTTON_Y); \
case MINECRAFT_ACTION_JUMP: \
return KFN(SDL_SCANCODE_SPACE) || CFN(SDL_CONTROLLER_BUTTON_A); \
case MINECRAFT_ACTION_FORWARD: \
return KFN(SDL_SCANCODE_W) || AFN(SDL_CONTROLLER_AXIS_LEFTY); \
case MINECRAFT_ACTION_BACKWARD: \
return KFN(SDL_SCANCODE_S) || AFN(SDL_CONTROLLER_AXIS_LEFTY); \
case MINECRAFT_ACTION_LEFT: \
return KFN(SDL_SCANCODE_A) || AFN(SDL_CONTROLLER_AXIS_LEFTX); \
case MINECRAFT_ACTION_RIGHT: \
return KFN(SDL_SCANCODE_D) || AFN(SDL_CONTROLLER_AXIS_LEFTX); \
case MINECRAFT_ACTION_INVENTORY: \
return KFN(SDL_SCANCODE_E) || CFN(SDL_CONTROLLER_BUTTON_Y); \
case MINECRAFT_ACTION_PAUSEMENU: \
return KFN(SDL_SCANCODE_ESCAPE) || CFN(SDL_CONTROLLER_BUTTON_START); \
case MINECRAFT_ACTION_DROP: \
return KFN(SDL_SCANCODE_Q) || CFN(SDL_CONTROLLER_BUTTON_B); \
case MINECRAFT_ACTION_CRAFTING: \
return KFN(SDL_SCANCODE_C) || CFN(SDL_CONTROLLER_BUTTON_X); \
case MINECRAFT_ACTION_RENDER_THIRD_PERSON: \
return KFN(SDL_SCANCODE_F5) || CFN(SDL_CONTROLLER_BUTTON_LEFTSTICK); \
case MINECRAFT_ACTION_GAME_INFO: \
return KFN(SDL_SCANCODE_F3); \
case MINECRAFT_ACTION_DPAD_LEFT: \
return KFN(SDL_SCANCODE_LEFT) || CFN(SDL_CONTROLLER_BUTTON_DPAD_LEFT); \
case MINECRAFT_ACTION_DPAD_RIGHT: \
return KFN(SDL_SCANCODE_RIGHT) || \
CFN(SDL_CONTROLLER_BUTTON_DPAD_RIGHT); \
case MINECRAFT_ACTION_DPAD_UP: \
return KFN(SDL_SCANCODE_UP) || CFN(SDL_CONTROLLER_BUTTON_DPAD_UP); \
case MINECRAFT_ACTION_DPAD_DOWN: \
return KFN(SDL_SCANCODE_DOWN) || CFN(SDL_CONTROLLER_BUTTON_DPAD_DOWN); \
default: \
return false;
bool C_4JInput::ButtonDown(int iPad, unsigned char ucAction) {
if (iPad != 0) return false;
if (ucAction == 255) {
for (int i = 0; i < s_watchedKeyCount; ++i)
if (s_keysCurrent[s_watchedKeys[i]]) return true;
return s_mouseLeftCurrent || s_mouseRightCurrent;
}
switch (ucAction) {
case MINECRAFT_ACTION_ACTION:
return MouseLDown() || KDown(SDL_SCANCODE_RETURN) ||
ADown(SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
case MINECRAFT_ACTION_USE:
return MouseRDown() || KDown(SDL_SCANCODE_F) ||
ADown(SDL_CONTROLLER_AXIS_TRIGGERLEFT);
case MINECRAFT_ACTION_SNEAK_TOGGLE:
return KDown(SDL_SCANCODE_LSHIFT) || KDown(SDL_SCANCODE_RSHIFT) ||
CDown(SDL_CONTROLLER_BUTTON_RIGHTSTICK);
case MINECRAFT_ACTION_SPRINT:
return KDown(SDL_SCANCODE_LCTRL) || KDown(SDL_SCANCODE_RCTRL);
case MINECRAFT_ACTION_LEFT_SCROLL:
case ACTION_MENU_LEFT_SCROLL:
return ScrollSnap() > 0;
case MINECRAFT_ACTION_RIGHT_SCROLL:
case ACTION_MENU_RIGHT_SCROLL:
return ScrollSnap() < 0;
ACTION_CASES(KDown, CDown, ADown)
}
}
// The part that handles completing the action of pressing a button.
bool C_4JInput::ButtonPressed(int iPad, unsigned char ucAction) {
if (iPad != 0 || ucAction == 255) return false;
switch (ucAction) {
case MINECRAFT_ACTION_ACTION:
return MouseLPressed() || KPressed(SDL_SCANCODE_RETURN) ||
APressed(SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
case MINECRAFT_ACTION_USE:
return MouseRPressed() || KPressed(SDL_SCANCODE_F) ||
APressed(SDL_CONTROLLER_AXIS_TRIGGERLEFT);
case MINECRAFT_ACTION_SNEAK_TOGGLE:
return KPressed(SDL_SCANCODE_LSHIFT) ||
KPressed(SDL_SCANCODE_RSHIFT) ||
CPressed(SDL_CONTROLLER_BUTTON_RIGHTSTICK);
case MINECRAFT_ACTION_SPRINT:
return KPressed(SDL_SCANCODE_LCTRL) || KPressed(SDL_SCANCODE_RCTRL);
case MINECRAFT_ACTION_LEFT_SCROLL:
case ACTION_MENU_LEFT_SCROLL:
return ScrollSnap() > 0;
case MINECRAFT_ACTION_RIGHT_SCROLL:
case ACTION_MENU_RIGHT_SCROLL:
return ScrollSnap() < 0;
ACTION_CASES(KPressed, CPressed, APressed)
}
}
// The part that handles Releasing a button.
bool C_4JInput::ButtonReleased(int iPad, unsigned char ucAction) {
if (iPad != 0 || ucAction == 255) return false;
switch (ucAction) {
case MINECRAFT_ACTION_ACTION:
return MouseLReleased() || KReleased(SDL_SCANCODE_RETURN) ||
AReleased(SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
case MINECRAFT_ACTION_USE:
return MouseRReleased() || KReleased(SDL_SCANCODE_F) ||
AReleased(SDL_CONTROLLER_AXIS_TRIGGERLEFT);
case MINECRAFT_ACTION_SNEAK_TOGGLE:
return KReleased(SDL_SCANCODE_LSHIFT) ||
KReleased(SDL_SCANCODE_RSHIFT) ||
CReleased(SDL_CONTROLLER_BUTTON_RIGHTSTICK);
case MINECRAFT_ACTION_SPRINT:
KReleased(SDL_SCANCODE_LCTRL) || KReleased(SDL_SCANCODE_RCTRL);
case MINECRAFT_ACTION_LEFT_SCROLL:
case ACTION_MENU_LEFT_SCROLL:
case MINECRAFT_ACTION_RIGHT_SCROLL:
case ACTION_MENU_RIGHT_SCROLL:
return false;
ACTION_CASES(KReleased, CReleased, AReleased)
}
}
unsigned int C_4JInput::GetValue(int iPad, unsigned char ucAction, bool) {
if (iPad != 0) return 0;
if (ucAction == MINECRAFT_ACTION_LEFT_SCROLL) {
if (s_scrollTicksForGetValue > 0) {
unsigned int v = (unsigned int)s_scrollTicksForGetValue;
s_scrollTicksForGetValue = 0;
return v;
}
return 0u;
}
if (ucAction == MINECRAFT_ACTION_RIGHT_SCROLL) {
if (s_scrollTicksForGetValue < 0) {
unsigned int v = (unsigned int)(-s_scrollTicksForGetValue);
s_scrollTicksForGetValue = 0;
return v;
}
return 0u;
}
return ButtonDown(iPad, ucAction) ? 1u : 0u;
}
// Left stick movement, the one that moves the player around or selects menu
// options. (Soon be tested.)
float C_4JInput::GetJoypadStick_LX(int, bool) {
if (ADown(SDL_CONTROLLER_AXIS_LEFTX))
return axisVal[SDL_CONTROLLER_AXIS_LEFTX];
return (KDown(SDL_SCANCODE_D) ? 1.f : 0.f) -
(KDown(SDL_SCANCODE_A) ? 1.f : 0.f);
}
float C_4JInput::GetJoypadStick_LY(int, bool) {
if (ADown(SDL_CONTROLLER_AXIS_LEFTY))
return -axisVal[SDL_CONTROLLER_AXIS_LEFTY];
return (KDown(SDL_SCANCODE_W) ? 1.f : 0.f) -
(KDown(SDL_SCANCODE_S) ? 1.f : 0.f);
}
// We use mouse movement and convert it into a Right Stick output using
// logarithmic scaling This is the most important mouse part. Yet it's so small.
static float MouseAxis(float raw) {
if (fabsf(raw) < 0.0001f) return 0.f; // from 4j previous code
return (raw >= 0.f ? 1.f : -1.f) * sqrtf(fabsf(raw));
}
// We apply the Stick movement on the R(Right) X(2D Position)
float C_4JInput::GetJoypadStick_RX(int, bool) {
if (ADown(SDL_CONTROLLER_AXIS_RIGHTX))
return axisVal[SDL_CONTROLLER_AXIS_RIGHTX];
if (!SDL_GetRelativeMouseMode()) return 0.f;
TakeSnapIfNeeded();
return MouseAxis(s_snapRelX * MOUSE_SCALE);
}
// Bis. but with Y(2D Position)
float C_4JInput::GetJoypadStick_RY(int, bool) {
if (ADown(SDL_CONTROLLER_AXIS_RIGHTY))
return -axisVal[SDL_CONTROLLER_AXIS_RIGHTY];
if (!SDL_GetRelativeMouseMode()) return 0.f;
TakeSnapIfNeeded();
return MouseAxis(-s_snapRelY * MOUSE_SCALE);
}
unsigned char C_4JInput::GetJoypadLTrigger(int, bool) {
return (s_mouseRightCurrent ||
s_axisCurrent[SDL_CONTROLLER_AXIS_TRIGGERLEFT])
? 255
: 0;
}
unsigned char C_4JInput::GetJoypadRTrigger(int, bool) {
return (s_mouseLeftCurrent ||
s_axisCurrent[SDL_CONTROLLER_AXIS_TRIGGERRIGHT])
? 255
: 0;
}
int C_4JInput::GetMouseX() { return s_mouseX; }
int C_4JInput::GetMouseY() { return s_mouseY; }
// We detect if a Menu is visible on the player's screen to the mouse being
// stuck.
void C_4JInput::SetMenuDisplayed(int iPad, bool bVal) {
if (iPad >= 0 && iPad < 4) s_menuDisplayed[iPad] = bVal;
if (!s_sdlInitialized || bVal == s_prevMenuDisplayed) return;
SDL_SetRelativeMouseMode(bVal ? SDL_FALSE : SDL_TRUE);
s_prevMenuDisplayed = bVal;
}
int C_4JInput::GetScrollDelta() {
int v = s_scrollTicksForButtonPressed;
s_scrollTicksForButtonPressed = 0;
return v;
}
void C_4JInput::SetDeadzoneAndMovementRange(unsigned int, unsigned int) {}
void C_4JInput::SetGameJoypadMaps(unsigned char, unsigned char, unsigned int) {}
unsigned int C_4JInput::GetGameJoypadMaps(unsigned char, unsigned char) {
return 0;
}
void C_4JInput::SetJoypadMapVal(int, unsigned char) {}
unsigned char C_4JInput::GetJoypadMapVal(int) { return 0; }
void C_4JInput::SetJoypadSensitivity(int, float) {}
void C_4JInput::SetJoypadStickAxisMap(int, unsigned int, unsigned int) {}
void C_4JInput::SetJoypadStickTriggerMap(int, unsigned int, unsigned int) {}
void C_4JInput::SetKeyRepeatRate(float, float) {}
void C_4JInput::SetDebugSequence(const char*, int (*)(void*), void*) {}
float C_4JInput::GetIdleSeconds(int) { return 0.f; }
bool C_4JInput::IsPadConnected(int iPad) { return iPad == 0; }
// Silly check, we check if we have a keyboard.
EKeyboardResult C_4JInput::RequestKeyboard(const wchar_t*, const wchar_t*, int,
unsigned int,
int (*)(void*, const bool), void*,
C_4JInput::EKeyboardMode) {
return EKeyboard_Cancelled;
}
void C_4JInput::GetText(uint16_t* s) {
if (s) s[0] = 0;
}
bool C_4JInput::VerifyStrings(wchar_t**, int,
int (*)(void*, STRING_VERIFY_RESPONSE*), void*) {
return true;
}
void C_4JInput::CancelQueuedVerifyStrings(int (*)(void*,
STRING_VERIFY_RESPONSE*),
void*) {}
void C_4JInput::CancelAllVerifyInProgress() {}

View file

@ -1,163 +0,0 @@
#pragma once
#include <cstdint>
#define MAP_STYLE_0 0
#define MAP_STYLE_1 1
#define MAP_STYLE_2 2
#define _360_JOY_BUTTON_A 0x00000001
#define _360_JOY_BUTTON_B 0x00000002
#define _360_JOY_BUTTON_X 0x00000004
#define _360_JOY_BUTTON_Y 0x00000008
#define _360_JOY_BUTTON_START 0x00000010
#define _360_JOY_BUTTON_BACK 0x00000020
#define _360_JOY_BUTTON_RB 0x00000040
#define _360_JOY_BUTTON_LB 0x00000080
#define _360_JOY_BUTTON_RTHUMB 0x00000100
#define _360_JOY_BUTTON_LTHUMB 0x00000200
#define _360_JOY_BUTTON_DPAD_UP 0x00000400
#define _360_JOY_BUTTON_DPAD_DOWN 0x00000800
#define _360_JOY_BUTTON_DPAD_LEFT 0x00001000
#define _360_JOY_BUTTON_DPAD_RIGHT 0x00002000
// fake digital versions of analog values
#define _360_JOY_BUTTON_LSTICK_RIGHT 0x00004000
#define _360_JOY_BUTTON_LSTICK_LEFT 0x00008000
#define _360_JOY_BUTTON_RSTICK_DOWN 0x00010000
#define _360_JOY_BUTTON_RSTICK_UP 0x00020000
#define _360_JOY_BUTTON_RSTICK_RIGHT 0x00040000
#define _360_JOY_BUTTON_RSTICK_LEFT 0x00080000
#define _360_JOY_BUTTON_LSTICK_DOWN 0x00100000
#define _360_JOY_BUTTON_LSTICK_UP 0x00200000
#define _360_JOY_BUTTON_RT 0x00400000
#define _360_JOY_BUTTON_LT 0x00800000
// Stick axis maps - to allow changes for SouthPaw in-game axis mapping
#define AXIS_MAP_LX 0
#define AXIS_MAP_LY 1
#define AXIS_MAP_RX 2
#define AXIS_MAP_RY 3
// Trigger map - to allow for swap triggers in-game
#define TRIGGER_MAP_0 0
#define TRIGGER_MAP_1 1
enum EKeyboardResult {
EKeyboard_Pending,
EKeyboard_Cancelled,
EKeyboard_ResultAccept,
EKeyboard_ResultDecline,
};
typedef struct _STRING_VERIFY_RESPONSE {
std::uint16_t wNumStrings;
int* pStringResult;
} STRING_VERIFY_RESPONSE;
class C_4JInput {
public:
enum EKeyboardMode {
EKeyboardMode_Default,
EKeyboardMode_Numeric,
EKeyboardMode_Password,
EKeyboardMode_Alphabet,
EKeyboardMode_Full,
EKeyboardMode_Alphabet_Extended,
EKeyboardMode_IP_Address,
EKeyboardMode_Phone
};
void Initialise(int iInputStateC, unsigned char ucMapC,
unsigned char ucActionC, unsigned char ucMenuActionC);
void Tick(void);
void SetDeadzoneAndMovementRange(unsigned int uiDeadzone,
unsigned int uiMovementRangeMax);
void SetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction,
unsigned int uiActionVal);
unsigned int GetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction);
void SetJoypadMapVal(int iPad, unsigned char ucMap);
unsigned char GetJoypadMapVal(int iPad);
void SetJoypadSensitivity(int iPad, float fSensitivity);
unsigned int GetValue(int iPad, unsigned char ucAction,
bool bRepeat = false);
bool ButtonPressed(int iPad, unsigned char ucAction = 255); // toggled
bool ButtonReleased(int iPad, unsigned char ucAction); // toggled
bool ButtonDown(int iPad,
unsigned char ucAction = 255); // button held down
// Functions to remap the axis and triggers for in-game (not menus) -
// SouthPaw, etc
void SetJoypadStickAxisMap(int iPad, unsigned int uiFrom,
unsigned int uiTo);
void SetJoypadStickTriggerMap(int iPad, unsigned int uiFrom,
unsigned int uiTo);
void SetKeyRepeatRate(float fRepeatDelaySecs, float fRepeatRateSecs);
void SetDebugSequence(const char* chSequenceA, int (*Func)(void*),
void* lpParam);
float GetIdleSeconds(int iPad);
bool IsPadConnected(int iPad);
// In-Game values which may have been remapped due to Southpaw, swap
// triggers, etc
float GetJoypadStick_LX(int iPad, bool bCheckMenuDisplay = true);
float GetJoypadStick_LY(int iPad, bool bCheckMenuDisplay = true);
float GetJoypadStick_RX(int iPad, bool bCheckMenuDisplay = true);
float GetJoypadStick_RY(int iPad, bool bCheckMenuDisplay = true);
unsigned char GetJoypadLTrigger(int iPad, bool bCheckMenuDisplay = true);
unsigned char GetJoypadRTrigger(int iPad, bool bCheckMenuDisplay = true);
void SetMenuDisplayed(int iPad, bool bVal);
int GetHotbarSlotPressed(int iPad);
int GetScrollDelta();
// Legacy keyboard request overloads with integer string-table ids used to
// live here. The remaining public API keeps the direct text/callback form.
EKeyboardResult RequestKeyboard(const wchar_t* Title, const wchar_t* Text,
int iPad, unsigned int uiMaxChars,
int (*Func)(void*, const bool),
void* lpParam,
C_4JInput::EKeyboardMode eMode);
void GetText(uint16_t* UTF16String);
// Online check strings against offensive list - TCR 92
// TCR # 092 CMTV Player Text String Verification
// Requirement Any player-entered text visible to another player on
// Xbox LIVE must be verified using the Xbox LIVE service before being
// transmitted. Text that is rejected by the Xbox LIVE service must not be
// displayed.
//
// Remarks
// This requirement applies to any player-entered string that can
// be exposed to other players on Xbox LIVE. It includes session names,
// content descriptions, text messages, tags, team names, mottos, comments,
// and so on.
//
// Games may decide to not send the text, blank it out, or use
// generic text if the text was rejected by the Xbox LIVE service.
//
// Games verify the text by calling the XStringVerify function.
//
// Exemption It is not required to use the Xbox LIVE service to
// verify real-time text communication. An example of real-time text
// communication is in-game text chat.
//
// Intent Protect players from inappropriate language.
bool VerifyStrings(wchar_t** pwStringA, int iStringC,
int (*Func)(void*, STRING_VERIFY_RESPONSE*),
void* lpParam);
void CancelQueuedVerifyStrings(int (*Func)(void*, STRING_VERIFY_RESPONSE*),
void* lpParam);
void CancelAllVerifyInProgress(void);
int GetMouseX();
int GetMouseY();
// bool InputDetected(int userIndex, wchar_t* inputText);
};
// Singleton
extern C_4JInput InputManager;

View file

View file

@ -1,25 +0,0 @@
input_sources = files(
'4J_Input.cpp',
'INP_ForceFeedback.cpp',
'INP_Keyboard.cpp',
'INP_Main.cpp',
'INP_StringCheck.cpp',
'stdafx.cpp',
)
lib_input = static_library('4J_Input',
input_sources,
include_directories : include_directories('.'),
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
# We import SDL2 but not SDL3.. which is a bit sad,
sdl_dep = dependency('sdl2', required : false)
input_dep = declare_dependency(
link_with : lib_input,
dependencies : [sdl_dep],
include_directories : include_directories('.'),
)

View file

@ -1 +0,0 @@
#include "stdafx.h"

View file

@ -1,6 +0,0 @@
#ifndef _4J_INPUT_STADAFX_H
#define _4J_INPUT_STADAFX_H
#include "../4J.Common/4J_Compat.h"
#endif //_4J_INPUT_STADAFX_H

View file

@ -1,270 +0,0 @@
#include "4J_Profile.h"
#include "../4J.Common/4J_ProfileConstants.h"
#include <cstdio>
#include <cstring>
C_4JProfile ProfileManager;
namespace {
constexpr PlayerUID kFakeXuidBase = 0xe000d45248242f2eULL;
struct ProfileGameSettings {
bool bSettingsChanged;
unsigned char ucMusicVolume;
unsigned char ucSoundFXVolume;
unsigned char ucSensitivity;
unsigned char ucGamma;
unsigned char ucPad01;
unsigned short usBitmaskValues;
unsigned int uiDebugBitmask;
union {
struct {
unsigned char ucTutorialCompletion[TUTORIAL_PROFILE_STORAGE_BYTES];
std::uint32_t dwSelectedSkin;
unsigned char ucMenuSensitivity;
unsigned char ucInterfaceOpacity;
unsigned char ucPad02;
unsigned char usPad03;
unsigned int uiBitmaskValues;
unsigned int uiSpecialTutorialBitmask;
std::uint32_t dwSelectedCape;
unsigned int uiFavoriteSkinA[MAX_FAVORITE_SKINS];
unsigned char ucCurrentFavoriteSkinPos;
unsigned int uiMashUpPackWorldsDisplay;
unsigned char ucLanguage;
};
unsigned char ucReservedSpace[192];
};
};
static_assert(sizeof(ProfileGameSettings) == 204,
"ProfileGameSettings must match GAME_SETTINGS profile storage");
void* s_profileData[XUSER_MAX_COUNT] = {};
C_4JProfile::PROFILESETTINGS s_dashboardSettings[XUSER_MAX_COUNT] = {};
char s_gamertags[XUSER_MAX_COUNT][16] = {};
std::wstring s_displayNames[XUSER_MAX_COUNT];
int s_primaryPad = 0;
int s_lockedProfile = 0;
bool s_profileIsFullVersion = true;
int (*s_defaultOptionsCallback)(void*, C_4JProfile::PROFILESETTINGS*,
const int iPad) = nullptr;
void* s_defaultOptionsCallbackParam = nullptr;
bool isValidPad(int iPad) { return iPad >= 0 && iPad < XUSER_MAX_COUNT; }
void ensureFakeIdentity(int iPad) {
if (!isValidPad(iPad) || s_gamertags[iPad][0] != '\0') {
return;
}
std::snprintf(s_gamertags[iPad], sizeof(s_gamertags[iPad]), "Player%d",
iPad + 1);
s_displayNames[iPad] = std::wstring(L"Player") + std::to_wstring(iPad + 1);
}
void initialiseDefaultGameSettings(ProfileGameSettings* gameSettings) {
gameSettings->ucMenuSensitivity = 100;
gameSettings->ucInterfaceOpacity = 80;
gameSettings->usBitmaskValues |= 0x0200;
gameSettings->usBitmaskValues |= 0x0400;
gameSettings->usBitmaskValues |= 0x1000;
gameSettings->usBitmaskValues |= 0x8000;
gameSettings->uiBitmaskValues = 0L;
gameSettings->uiBitmaskValues |= GAMESETTING_CLOUDS;
gameSettings->uiBitmaskValues |= GAMESETTING_ONLINE;
gameSettings->uiBitmaskValues |= GAMESETTING_FRIENDSOFFRIENDS;
gameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG;
gameSettings->uiBitmaskValues &= ~GAMESETTING_BEDROCKFOG;
gameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYHUD;
gameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYHAND;
gameSettings->uiBitmaskValues |= GAMESETTING_CUSTOMSKINANIM;
gameSettings->uiBitmaskValues |= GAMESETTING_DEATHMESSAGES;
gameSettings->uiBitmaskValues |= (GAMESETTING_UISIZE & 0x00000800);
gameSettings->uiBitmaskValues |=
(GAMESETTING_UISIZE_SPLITSCREEN & 0x00004000);
gameSettings->uiBitmaskValues |= GAMESETTING_ANIMATEDCHARACTER;
for (int i = 0; i < MAX_FAVORITE_SKINS; ++i) {
gameSettings->uiFavoriteSkinA[i] = 0xFFFFFFFF;
}
gameSettings->ucCurrentFavoriteSkinPos = 0;
gameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
gameSettings->uiBitmaskValues &= ~GAMESETTING_PS3EULAREAD;
gameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT;
gameSettings->uiBitmaskValues &= ~GAMESETTING_PSVITANETWORKMODEADHOC;
gameSettings->ucTutorialCompletion[0] = 0xFF;
gameSettings->ucTutorialCompletion[1] = 0xFF;
gameSettings->ucTutorialCompletion[2] = 0x0F;
gameSettings->ucTutorialCompletion[28] |= 1 << 0;
}
} // namespace
void C_4JProfile::Initialise(std::uint32_t dwTitleID,
std::uint32_t dwOfferID,
unsigned short usProfileVersion,
unsigned int uiProfileValuesC,
unsigned int uiProfileSettingsC,
std::uint32_t* pdwProfileSettingsA,
int iGameDefinedDataSizeX4,
unsigned int* puiGameDefinedDataChangedBitmask) {
s_primaryPad = 0;
s_lockedProfile = 0;
std::memset(s_dashboardSettings, 0, sizeof(s_dashboardSettings));
for (int i = 0; i < XUSER_MAX_COUNT; ++i) {
delete[] static_cast<unsigned char*>(s_profileData[i]);
s_profileData[i] = new unsigned char[iGameDefinedDataSizeX4 / 4];
std::memset(s_profileData[i], 0, iGameDefinedDataSizeX4 / 4);
initialiseDefaultGameSettings(
static_cast<ProfileGameSettings*>(s_profileData[i]));
ensureFakeIdentity(i);
}
}
void C_4JProfile::SetTrialTextStringTable(CXuiStringTable* pStringTable,
int iAccept, int iReject) {}
void C_4JProfile::SetTrialAwardText(eAwardType AwardType, int iTitle,
int iText) {}
int C_4JProfile::GetLockedProfile() { return s_lockedProfile; }
void C_4JProfile::SetLockedProfile(int iProf) { s_lockedProfile = iProf; }
bool C_4JProfile::IsSignedIn(int iQuadrant) { return iQuadrant == 0; }
bool C_4JProfile::IsSignedInLive(int iProf) { return IsSignedIn(iProf); }
bool C_4JProfile::IsGuest(int iQuadrant) { return false; }
unsigned int C_4JProfile::RequestSignInUI(
bool bFromInvite, bool bLocalGame, bool bNoGuestsAllowed,
bool bMultiplayerSignIn, bool bAddUser,
int (*Func)(void*, const bool, const int iPad), void* lpParam,
int iQuadrant) {
return 0;
}
unsigned int C_4JProfile::DisplayOfflineProfile(
int (*Func)(void*, const bool, const int iPad), void* lpParam,
int iQuadrant) {
return 0;
}
unsigned int C_4JProfile::RequestConvertOfflineToGuestUI(
int (*Func)(void*, const bool, const int iPad), void* lpParam,
int iQuadrant) {
return 0;
}
void C_4JProfile::SetPrimaryPlayerChanged(bool bVal) {}
bool C_4JProfile::QuerySigninStatus(void) { return true; }
void C_4JProfile::GetXUID(int iPad, PlayerUID* pXuid, bool bOnlineXuid) {
if (pXuid) *pXuid = kFakeXuidBase + static_cast<PlayerUID>(isValidPad(iPad) ? iPad : 0);
}
bool C_4JProfile::AreXUIDSEqual(PlayerUID xuid1, PlayerUID xuid2) {
return xuid1 == xuid2;
}
bool C_4JProfile::XUIDIsGuest(PlayerUID xuid) { return false; }
bool C_4JProfile::AllowedToPlayMultiplayer(int iProf) { return true; }
bool C_4JProfile::GetChatAndContentRestrictions(int iPad,
bool* pbChatRestricted,
bool* pbContentRestricted,
int* piAge) {
if (pbChatRestricted) *pbChatRestricted = false;
if (pbContentRestricted) *pbContentRestricted = false;
if (piAge) *piAge = 18;
return true;
}
void C_4JProfile::StartTrialGame() {}
void C_4JProfile::AllowedPlayerCreatedContent(int iPad, bool thisQuadrantOnly,
bool* allAllowed,
bool* friendsAllowed) {
if (allAllowed) *allAllowed = true;
if (friendsAllowed) *friendsAllowed = true;
}
bool C_4JProfile::CanViewPlayerCreatedContent(int iPad, bool thisQuadrantOnly,
PlayerUID* pXuids,
unsigned int xuidCount) {
return true;
}
void C_4JProfile::ShowProfileCard(int iPad, PlayerUID targetUid) {}
bool C_4JProfile::GetProfileAvatar(int iPad,
int (*Func)(void* lpParam,
std::uint8_t* thumbnailData,
unsigned int thumbnailBytes),
void* lpParam) {
return false;
}
void C_4JProfile::CancelProfileAvatarRequest() {}
int C_4JProfile::GetPrimaryPad() { return s_primaryPad; }
void C_4JProfile::SetPrimaryPad(int iPad) { s_primaryPad = iPad; }
char* C_4JProfile::GetGamertag(int iPad) {
const int resolvedPad = isValidPad(iPad) ? iPad : 0;
ensureFakeIdentity(resolvedPad);
return s_gamertags[resolvedPad];
}
std::wstring C_4JProfile::GetDisplayName(int iPad) {
const int resolvedPad = isValidPad(iPad) ? iPad : 0;
ensureFakeIdentity(resolvedPad);
return s_displayNames[resolvedPad];
}
bool C_4JProfile::IsFullVersion() { return s_profileIsFullVersion; }
void C_4JProfile::SetSignInChangeCallback(void (*Func)(void*, bool,
unsigned int),
void* lpParam) {}
void C_4JProfile::SetNotificationsCallback(void (*Func)(void*, std::uint32_t,
unsigned int),
void* lpParam) {}
bool C_4JProfile::RegionIsNorthAmerica(void) { return false; }
bool C_4JProfile::LocaleIsUSorCanada(void) { return false; }
int C_4JProfile::GetLiveConnectionStatus() { return 0; }
bool C_4JProfile::IsSystemUIDisplayed() { return false; }
void C_4JProfile::SetProfileReadErrorCallback(void (*Func)(void*),
void* lpParam) {}
int C_4JProfile::SetDefaultOptionsCallback(int (*Func)(void*, PROFILESETTINGS*,
const int iPad),
void* lpParam) {
s_defaultOptionsCallback = Func;
s_defaultOptionsCallbackParam = lpParam;
return 0;
}
int C_4JProfile::SetOldProfileVersionCallback(int (*Func)(void*, unsigned char*,
const unsigned short,
const int),
void* lpParam) {
return 0;
}
C_4JProfile::PROFILESETTINGS* C_4JProfile::GetDashboardProfileSettings(
int iPad) {
return &s_dashboardSettings[isValidPad(iPad) ? iPad : 0];
}
void C_4JProfile::WriteToProfile(int iQuadrant, bool bGameDefinedDataChanged,
bool bOverride5MinuteLimitOnProfileWrites) {}
void C_4JProfile::ForceQueuedProfileWrites(int iPad) {}
void* C_4JProfile::GetGameDefinedProfileData(int iQuadrant) {
return isValidPad(iQuadrant) ? s_profileData[iQuadrant] : nullptr;
}
void C_4JProfile::ResetProfileProcessState() {}
void C_4JProfile::Tick(void) {}
void C_4JProfile::RegisterAward(int iAwardNumber, int iGamerconfigID,
eAwardType eType, bool bLeaderboardAffected,
CXuiStringTable* pStringTable, int iTitleStr,
int iTextStr, int iAcceptStr,
char* pszThemeName, unsigned int uiThemeSize) {}
int C_4JProfile::GetAwardId(int iAwardNumber) { return 0; }
eAwardType C_4JProfile::GetAwardType(int iAwardNumber) {
return eAwardType_Achievement;
}
bool C_4JProfile::CanBeAwarded(int iQuadrant, int iAwardNumber) {
return false;
}
void C_4JProfile::Award(int iQuadrant, int iAwardNumber, bool bForce) {}
bool C_4JProfile::IsAwardsFlagSet(int iQuadrant, int iAward) { return false; }
void C_4JProfile::RichPresenceInit(int iPresenceCount, int iContextCount) {}
void C_4JProfile::RegisterRichPresenceContext(int iGameConfigContextID) {}
void C_4JProfile::SetRichPresenceContextValue(int iPad, int iContextID,
int iVal) {}
void C_4JProfile::SetCurrentGameActivity(int iPad, int iNewPresence,
bool bSetOthersToIdle) {}
void C_4JProfile::DisplayFullVersionPurchase(bool bRequired, int iQuadrant,
int iUpsellParam) {}
void C_4JProfile::SetUpsellCallback(void (*Func)(void* lpParam,
eUpsellType type,
eUpsellResponse response,
int iUserData),
void* lpParam) {}
void C_4JProfile::SetDebugFullOverride(bool bVal) { s_profileIsFullVersion = bVal; }

View file

@ -1,165 +0,0 @@
#pragma once
#include <cstdint>
#include <string>
#include "../4J.Common/4J_Compat.h"
enum eAwardType {
eAwardType_Achievement = 0,
eAwardType_GamerPic,
eAwardType_Theme,
eAwardType_AvatarItem,
};
enum eUpsellType {
eUpsellType_Custom = 0, // This is the default, and means that the upsell
// dialog was initiated in the app code
eUpsellType_Achievement,
eUpsellType_GamerPic,
eUpsellType_Theme,
eUpsellType_AvatarItem,
};
enum eUpsellResponse {
eUpsellResponse_Declined,
eUpsellResponse_Accepted_NoPurchase,
eUpsellResponse_Accepted_Purchase,
};
class C_4JProfile {
public:
struct PROFILESETTINGS {
int iYAxisInversion;
int iControllerSensitivity;
int iVibration;
bool bSwapSticks;
};
// 4 players have game defined data, puiGameDefinedDataChangedBitmask needs
// to be checked by the game side to see if there's an update needed - it'll
// have the bits set for players to be updated
void Initialise(std::uint32_t dwTitleID, std::uint32_t dwOfferID,
unsigned short usProfileVersion,
unsigned int uiProfileValuesC,
unsigned int uiProfileSettingsC,
std::uint32_t* pdwProfileSettingsA,
int iGameDefinedDataSizeX4,
unsigned int* puiGameDefinedDataChangedBitmask);
void SetTrialTextStringTable(CXuiStringTable* pStringTable, int iAccept,
int iReject);
void SetTrialAwardText(eAwardType AwardType, int iTitle,
int iText); // achievement popup in the trial game
int GetLockedProfile();
void SetLockedProfile(int iProf);
bool IsSignedIn(int iQuadrant);
bool IsSignedInLive(int iProf);
bool IsGuest(int iQuadrant);
unsigned int RequestSignInUI(bool bFromInvite, bool bLocalGame,
bool bNoGuestsAllowed,
bool bMultiplayerSignIn, bool bAddUser,
int (*Func)(void*, const bool, const int iPad),
void* lpParam,
int iQuadrant = XUSER_INDEX_ANY);
unsigned int DisplayOfflineProfile(
int (*Func)(void*, const bool, const int iPad), void* lpParam,
int iQuadrant = XUSER_INDEX_ANY);
unsigned int RequestConvertOfflineToGuestUI(
int (*Func)(void*, const bool, const int iPad), void* lpParam,
int iQuadrant = XUSER_INDEX_ANY);
void SetPrimaryPlayerChanged(bool bVal);
bool QuerySigninStatus(void);
void GetXUID(int iPad, PlayerUID* pXuid, bool bOnlineXuid);
bool AreXUIDSEqual(PlayerUID xuid1, PlayerUID xuid2);
bool XUIDIsGuest(PlayerUID xuid);
bool AllowedToPlayMultiplayer(int iProf);
bool GetChatAndContentRestrictions(int iPad, bool* pbChatRestricted,
bool* pbContentRestricted, int* piAge);
void StartTrialGame(); // disables saves and leaderboard, and change state
// to readyforgame from pregame
void AllowedPlayerCreatedContent(int iPad, bool thisQuadrantOnly,
bool* allAllowed, bool* friendsAllowed);
bool CanViewPlayerCreatedContent(int iPad, bool thisQuadrantOnly,
PlayerUID* pXuids,
unsigned int xuidCount);
void ShowProfileCard(int iPad, PlayerUID targetUid);
bool GetProfileAvatar(int iPad,
int (*Func)(void* lpParam,
std::uint8_t* thumbnailData,
unsigned int thumbnailBytes),
void* lpParam);
void CancelProfileAvatarRequest();
// SYS
int GetPrimaryPad();
void SetPrimaryPad(int iPad);
char* GetGamertag(int iPad);
std::wstring GetDisplayName(int iPad);
bool IsFullVersion();
void SetSignInChangeCallback(void (*Func)(void*, bool, unsigned int),
void* lpParam);
void SetNotificationsCallback(void (*Func)(void*, std::uint32_t,
unsigned int),
void* lpParam);
bool RegionIsNorthAmerica(void);
bool LocaleIsUSorCanada(void);
int GetLiveConnectionStatus();
bool IsSystemUIDisplayed();
void SetProfileReadErrorCallback(void (*Func)(void*), void* lpParam);
// PROFILE DATA
int SetDefaultOptionsCallback(int (*Func)(void*, PROFILESETTINGS*,
const int iPad),
void* lpParam);
int SetOldProfileVersionCallback(int (*Func)(void*, unsigned char*,
const unsigned short,
const int),
void* lpParam);
PROFILESETTINGS* GetDashboardProfileSettings(int iPad);
void WriteToProfile(int iQuadrant, bool bGameDefinedDataChanged = false,
bool bOverride5MinuteLimitOnProfileWrites = false);
void ForceQueuedProfileWrites(int iPad = XUSER_INDEX_ANY);
void* GetGameDefinedProfileData(int iQuadrant);
void ResetProfileProcessState(); // after a sign out from the primary
// player, call this
void Tick(void);
// ACHIEVEMENTS & AWARDS
void RegisterAward(int iAwardNumber, int iGamerconfigID, eAwardType eType,
bool bLeaderboardAffected = false,
CXuiStringTable* pStringTable = nullptr,
int iTitleStr = -1,
int iTextStr = -1, int iAcceptStr = -1,
char* pszThemeName = nullptr,
unsigned int uiThemeSize = 0L);
int GetAwardId(int iAwardNumber);
eAwardType GetAwardType(int iAwardNumber);
bool CanBeAwarded(int iQuadrant, int iAwardNumber);
void Award(int iQuadrant, int iAwardNumber, bool bForce = false);
bool IsAwardsFlagSet(int iQuadrant, int iAward);
// RICH PRESENCE
void RichPresenceInit(int iPresenceCount, int iContextCount);
void RegisterRichPresenceContext(int iGameConfigContextID);
void SetRichPresenceContextValue(int iPad, int iContextID, int iVal);
void SetCurrentGameActivity(int iPad, int iNewPresence,
bool bSetOthersToIdle = false);
// PURCHASE
void DisplayFullVersionPurchase(bool bRequired, int iQuadrant,
int iUpsellParam = -1);
void SetUpsellCallback(void (*Func)(void* lpParam, eUpsellType type,
eUpsellResponse response,
int iUserData),
void* lpParam);
// Debug
void SetDebugFullOverride(
bool bVal); // To override the license version (trail/full). Only in
// debug/release, not ContentPackage
};
// Singleton
extern C_4JProfile ProfileManager;

View file

View file

@ -1,22 +0,0 @@
profile_sources = files(
'4J_Profile.cpp',
'PRO_AwardManager.cpp',
'PRO_Data.cpp',
'PRO_Main.cpp',
'PRO_RichPresence.cpp',
'PRO_Sys.cpp',
'stdafx.cpp',
)
# 4jprofile stink
lib_profile = static_library('4J_Profile',
profile_sources,
include_directories : include_directories('.'),
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
profile_dep = declare_dependency(
link_with : lib_profile,
include_directories : include_directories('.'),
)

View file

@ -1 +0,0 @@
#include "stdafx.h"

View file

@ -1,6 +0,0 @@
#ifndef _4J_PROFILE_STADAFX_H
#define _4J_PROFILE_STADAFX_H
#include "../4J.Common/4J_Compat.h"
#endif //_4J_PROFILE_STADAFX_H

View file

@ -1,917 +0,0 @@
#include "4J_Render.h"
#include <cstring>
#include <cstdlib> // getenv
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <SDL2/SDL.h>
#include <cstdio>
#include <cmath>
#include <pthread.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
C4JRender RenderManager;
// Hello SDL!
static SDL_Window* s_window = nullptr;
static SDL_GLContext s_glContext = nullptr;
static bool s_shouldClose = false;
static int s_textureLevels = 1;
static int s_windowWidth = 1920;
static int s_windowHeight = 1080;
// We set Window size with the monitor's res, so that I can get rid of ugly
// values.
static void SetInitialWindowSize() {
int w = 0, h = 0;
if (SDL_Init(SDL_INIT_VIDEO) == 0) {
SDL_DisplayMode mode;
if (SDL_GetCurrentDisplayMode(0, &mode) == 0) {
w = (int)(mode.w * 0.4f);
h = (int)(mode.h * 0.4f);
}
}
if (w > 0 && h > 0) { s_windowWidth = w; s_windowHeight = h; }
else { s_windowWidth = 1920; s_windowHeight = 1080; }
}
// (can't believe i had to rewrite this, i literally did it TODAY.)
static int s_reqWidth = 1920;
static int s_reqHeight = 1080;
// When we'll have a settings system in order, we'll set bool to that value, right now it's hardcoded.
static bool s_fullscreen = false;
static pthread_key_t s_glCtxKey;
static pthread_once_t s_glCtxKeyOnce = PTHREAD_ONCE_INIT;
static void makeGLCtxKey() { pthread_key_create(&s_glCtxKey, nullptr); }
// Do not touch exactly this number |
static const int MAX_SHARED_CONTEXTS = 6; // <- this one, do not touch
static SDL_Window* s_sharedContextWindows[MAX_SHARED_CONTEXTS] = {};
static SDL_GLContext s_sharedContexts[MAX_SHARED_CONTEXTS] = {};
static int s_sharedContextCount = 0;
static int s_nextSharedContext = 0;
static pthread_mutex_t s_sharedCtxMutex = PTHREAD_MUTEX_INITIALIZER;
// Tells thread to do Direct GL calls, just don't touch.
static pthread_mutex_t s_glCallMutex = PTHREAD_MUTEX_INITIALIZER;
// Track which thread is the main (rendering) thread
static pthread_t s_mainThread;
static bool s_mainThreadSet = false;
// viewport go brr
static void onFramebufferResize(int w, int h) {
if (w < 1) w = 1;
if (h < 1) h = 1;
s_windowWidth = w;
s_windowHeight = h;
::glViewport(0, 0, w, h);
}
// V-Sync
// Initialize OpenGL & The SDL window.
void C4JRender::Initialise() {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "[4J_Render] Failed to initialise SDL: %s\n",
SDL_GetError());
return;
}
SDL_DisplayMode mode;
int haveMode = (SDL_GetCurrentDisplayMode(0, &mode) == 0);
if (s_reqWidth > 0 && s_reqHeight > 0) {
s_windowWidth = s_reqWidth;
s_windowHeight = s_reqHeight;
} else if (haveMode) {
s_windowWidth = mode.w;
s_windowHeight = mode.h;
}
fprintf(stderr, "[4J_Render] Window %dx%d fullscreen=%s\n", s_windowWidth,
s_windowHeight, s_fullscreen ? "yes" : "no");
fflush(stderr);
// Setting the sdl_gl ver. Change in future incase we want to use shaders
// Yes i'm still using fixed functions, get mad at me
// I don't care.
// Im not gonna be rewriting the whole renderer.. AGAIN. ;w;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
if (s_fullscreen) winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
s_window = SDL_CreateWindow("Minecraft Console Edition",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
s_windowWidth, s_windowHeight, winFlags);
if (!s_window) {
fprintf(stderr, "[4J_Render] Failed to create SDL window: %s\n",
SDL_GetError());
SDL_Quit();
return;
}
s_glContext = SDL_GL_CreateContext(s_window);
if (!s_glContext) {
fprintf(stderr, "[4J_Render] Failed to create GL context: %s\n",
SDL_GetError());
SDL_DestroyWindow(s_window);
s_window = nullptr;
SDL_Quit();
return;
}
// 4JCraft VSync/V-Sync
#ifdef ENABLE_VSYNC
SDL_GL_SetSwapInterval(1); // V-Sync On Please.
#else
SDL_GL_SetSwapInterval(0); // V-Sync Off Please.
#endif
int fw, fh;
SDL_GetWindowSize(s_window, &fw, &fh);
onFramebufferResize(fw, fh);
// We initialize the OpenGL states. Touching those values makes some funny
// artifacts appear.
::glEnable(GL_TEXTURE_2D);
::glEnable(GL_DEPTH_TEST);
::glDepthFunc(GL_LEQUAL);
::glClearDepth(1.0);
::glEnable(GL_ALPHA_TEST);
::glAlphaFunc(GL_GREATER, 0.1f);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
::glEnable(GL_CULL_FACE);
::glCullFace(GL_BACK);
::glShadeModel(GL_SMOOTH);
::glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
::glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
::glViewport(0, 0, s_windowWidth, s_windowHeight);
::glEnable(GL_COLOR_MATERIAL);
::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
// Print the renderer's version incase we change it in the future.
printf("[4J_Render] OpenGL %s | %s\n",
(const char*)::glGetString(GL_VERSION),
(const char*)::glGetString(GL_RENDERER));
fflush(stdout);
// Tag this as the main rendering thread
pthread_once(&s_glCtxKeyOnce, makeGLCtxKey);
s_mainThread = pthread_self();
s_mainThreadSet = true;
pthread_setspecific(s_glCtxKey, (void*)s_window);
// Pre-create shared GL contexts for worker threads (chunk builders etc.)
// Ensure they are invisible so they don't interfere with the window
// manager.
// Pre-create shared GL contexts for worker threads (chunk builders & other
// shit etc.) SDL_GL_SHARE_WITH_CURRENT_CONTEXT my saviour.
for (int i = 0; i < MAX_SHARED_CONTEXTS; i++) {
SDL_Window* w = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 1, 1,
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
if (!w) break;
// Ensure sharing
// I've been stuck on this for a while. Im stupid..
SDL_GL_MakeCurrent(s_window, s_glContext);
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
SDL_GLContext ctx = SDL_GL_CreateContext(w);
if (!ctx) {
SDL_DestroyWindow(w);
break;
}
s_sharedContextWindows[s_sharedContextCount] = w;
s_sharedContexts[s_sharedContextCount] = ctx;
s_sharedContextCount++;
}
// Ensure main thread still has the context
SDL_GL_MakeCurrent(s_window, s_glContext);
fprintf(stderr,
"[4J_Render] Created %d shared GL contexts for worker threads\n",
s_sharedContextCount);
fflush(stderr);
}
void C4JRender::InitialiseContext() {
if (!s_window) return;
pthread_once(&s_glCtxKeyOnce, makeGLCtxKey);
// Main thread reclaiming context (e.g. after startup thread finishes)
if (s_mainThreadSet && pthread_equal(pthread_self(), s_mainThread)) {
SDL_GL_MakeCurrent(s_window, s_glContext);
pthread_setspecific(s_glCtxKey, (void*)s_window);
return;
}
// Worker thread checks if there's a context, we don't want to have multiple
// contexts.
void* ctxPtr = pthread_getspecific(s_glCtxKey);
if (ctxPtr) {
// ctxPtr -> SDL_GLContext pointer
SDL_GLContext ctx = (SDL_GLContext)ctxPtr;
int idx = -1;
for (int i = 0; i < s_sharedContextCount; ++i)
if (s_sharedContexts[i] == ctx) {
idx = i;
break;
}
if (idx >= 0 && s_sharedContextWindows[idx])
SDL_GL_MakeCurrent(s_sharedContextWindows[idx], ctx);
return;
}
// Grab a pre-created shared context from the pool
pthread_mutex_lock(&s_sharedCtxMutex);
SDL_GLContext shared = nullptr;
if (s_nextSharedContext < s_sharedContextCount) {
shared = s_sharedContexts[s_nextSharedContext++];
}
pthread_mutex_unlock(&s_sharedCtxMutex);
if (!shared) {
fprintf(stderr,
"[4J_Render] ERROR: no shared GL contexts left for worker "
"thread %lu!\n",
(unsigned long)pthread_self());
fflush(stderr);
return;
}
// ewww..... look at line 201-203, we gotta make a function for that....
int idx = -1;
for (int i = 0; i < s_sharedContextCount; ++i)
if (s_sharedContexts[i] == shared) {
idx = i;
break;
}
if (idx >= 0 && s_sharedContextWindows[idx])
SDL_GL_MakeCurrent(s_sharedContextWindows[idx], shared);
// Initialize some basic state for this context to ensure consistent display
// list recording
::glEnable(GL_TEXTURE_2D);
::glEnable(GL_DEPTH_TEST);
::glDepthFunc(GL_LEQUAL);
::glAlphaFunc(GL_GREATER, 0.1f);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
::glShadeModel(GL_SMOOTH);
::glEnable(GL_COLOR_MATERIAL);
::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
pthread_setspecific(s_glCtxKey, (void*)shared);
fprintf(stderr,
"[4J_Render] Assigned shared GL context %p to worker thread %lu\n",
(void*)shared, (unsigned long)pthread_self());
fflush(stderr);
}
void C4JRender::StartFrame() {
if (!s_window) return;
int w, h;
SDL_GetWindowSize(s_window, &w, &h);
s_windowWidth = w > 0 ? w : 1;
s_windowHeight = h > 0 ? h : 1;
::glViewport(0, 0, s_windowWidth, s_windowHeight);
}
void C4JRender::Present() {
if (!s_window) return;
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
if (ev.type == SDL_QUIT)
s_shouldClose = true;
else if (ev.type == SDL_WINDOWEVENT) {
if (ev.window.event == SDL_WINDOWEVENT_CLOSE)
s_shouldClose = true;
else if (ev.window.event == SDL_WINDOWEVENT_RESIZED)
onFramebufferResize(ev.window.data1, ev.window.data2);
}
}
// Present the rendered frame after processing input/events to avoid input
// timing issues
::glFlush();
// debug log to help diagnose mouse issues
// printf("[4J_Render] Presenting frame (mouse lock=%d)\n", s_mouseLocked);
// fflush(stdout);
SDL_GL_SwapWindow(s_window);
}
void C4JRender::SetWindowSize(int w, int h) {
s_reqWidth = (w > 0) ? w : 0;
s_reqHeight = (h > 0) ? h : 0;
}
void C4JRender::SetFullscreen(bool fs) { s_fullscreen = fs; }
bool C4JRender::ShouldClose() { return !s_window || s_shouldClose; }
void C4JRender::Close() { s_window = nullptr; }
void C4JRender::Shutdown() {
// Destroy the main window and clean up SDL resources so that
// destructors running after the game loop don't touch a dead context.
if (s_window) {
if (s_glContext) {
SDL_GL_DeleteContext(s_glContext);
s_glContext = nullptr;
}
SDL_DestroyWindow(s_window);
s_window = nullptr;
}
for (int i = 0; i < s_sharedContextCount; ++i) {
if (s_sharedContexts[i]) {
SDL_GL_DeleteContext(s_sharedContexts[i]);
s_sharedContexts[i] = 0;
}
if (s_sharedContextWindows[i]) {
SDL_DestroyWindow(s_sharedContextWindows[i]);
s_sharedContextWindows[i] = nullptr;
}
}
s_sharedContextCount = 0;
SDL_Quit();
}
// rip glfw. you won't be missed. (i hope)
void C4JRender::DoScreenGrabOnNextPresent() {}
void C4JRender::Clear(int flags) { ::glClear(flags); }
void C4JRender::SetClearColour(const float colourRGBA[4]) {
::glClearColor(colourRGBA[0], colourRGBA[1], colourRGBA[2], colourRGBA[3]);
}
bool C4JRender::IsWidescreen() { return true; }
bool C4JRender::IsHiDef() { return true; }
void C4JRender::GetFramebufferSize(int& width, int& height) {
width = s_windowWidth;
height = s_windowHeight;
}
void C4JRender::CaptureThumbnail(ImageFileBuffer*) {}
void C4JRender::CaptureScreen(ImageFileBuffer*, XSOCIAL_PREVIEWIMAGE*) {}
void C4JRender::BeginConditionalSurvey(int) {}
void C4JRender::EndConditionalSurvey() {}
void C4JRender::BeginConditionalRendering(int) {}
void C4JRender::EndConditionalRendering() {}
void C4JRender::MatrixMode(int type) { ::glMatrixMode(type); }
void C4JRender::MatrixSetIdentity() { ::glLoadIdentity(); }
void C4JRender::MatrixTranslate(float x, float y, float z) {
::glTranslatef(x, y, z);
}
void C4JRender::MatrixRotate(float angle, float x, float y, float z) {
// We use math from the math lib instead of hardcoding it. How Ugly.
::glRotatef(angle * (180.0f / static_cast<float>(M_PI)), x, y, z);
}
void C4JRender::MatrixScale(float x, float y, float z) { ::glScalef(x, y, z); }
void C4JRender::MatrixPerspective(float fovy, float aspect, float zNear,
float zFar) {
::gluPerspective((double)fovy, (double)aspect, (double)zNear, (double)zFar);
}
void C4JRender::MatrixOrthogonal(float left, float right, float bottom,
float top, float zNear, float zFar) {
::glOrtho(left, right, bottom, top, zNear, zFar);
}
void C4JRender::MatrixPop() { ::glPopMatrix(); }
void C4JRender::MatrixPush() { ::glPushMatrix(); }
void C4JRender::MatrixMult(float* mat) { ::glMultMatrixf(mat); }
const float* C4JRender::MatrixGet(int type) {
static float mat[16];
::glGetFloatv(type, mat);
return mat;
}
void C4JRender::Set_matrixDirty() {} // immediate-mode
static GLenum mapPrimType(int pt) {
// Handle GL constants first
if (pt == GL_QUADS) return GL_QUADS;
if (pt == GL_TRIANGLES) return GL_TRIANGLES;
if (pt == GL_LINES) return GL_LINES;
if (pt == GL_LINE_STRIP) return GL_LINE_STRIP;
if (pt == GL_TRIANGLE_STRIP) return GL_TRIANGLE_STRIP;
if (pt == GL_TRIANGLE_FAN) return GL_TRIANGLE_FAN;
// Map from ePrimitiveType enum
switch (pt) {
case C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST:
return GL_TRIANGLES;
case C4JRender::PRIMITIVE_TYPE_TRIANGLE_STRIP:
return GL_TRIANGLE_STRIP;
case C4JRender::PRIMITIVE_TYPE_TRIANGLE_FAN:
return GL_TRIANGLE_FAN;
case C4JRender::PRIMITIVE_TYPE_QUAD_LIST:
return GL_QUADS;
case C4JRender::PRIMITIVE_TYPE_LINE_LIST:
return GL_LINES;
case C4JRender::PRIMITIVE_TYPE_LINE_STRIP:
return GL_LINE_STRIP;
default:
return GL_TRIANGLES;
}
}
// This is the clientside vertex processing.
void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
void* dataIn, eVertexType vType,
C4JRender::ePixelShaderType psType) {
if (count <= 0 || !dataIn) return;
// trash trash trash trash
pthread_mutex_lock(&s_glCallMutex);
GLenum mode = mapPrimType((int)PrimitiveType);
if (vType == VERTEX_TYPE_COMPRESSED) {
int16_t* sdata = (int16_t*)dataIn;
::glBegin(mode);
for (int i = 0; i < count; i++) {
int16_t* vert = sdata + i * 8;
float x = vert[0] / 1024.0f;
float y = vert[1] / 1024.0f;
float z = vert[2] / 1024.0f;
// Unpack RGB565 colour (Tesselator stores as packedcol - 32768 to
// fit in int16)
unsigned short packedColor = (unsigned short)((int)vert[3] + 32768);
float r = ((packedColor >> 11) & 0x1f) / 31.0f;
float g = ((packedColor >> 5) & 0x3f) / 63.0f;
float b = (packedColor & 0x1f) / 31.0f;
float fu = vert[4] / 8192.0f;
float fv = vert[5] / 8192.0f;
// Tesselator does that. Thanks 4J.
if (fu >= 1.0f) fu -= 1.0f;
// Unit 1 (lightmap) UVs
float fu2 = (float)vert[6] / 256.0f;
float fv2 = (float)vert[7] / 256.0f;
::glColor3f(r, g, b);
::glTexCoord2f(fu, fv);
::glMultiTexCoord2f(GL_TEXTURE1, fu2, fv2);
::glVertex3f(x, y, z);
}
::glEnd();
} else {
unsigned int* idata = (unsigned int*)dataIn;
::glBegin(mode);
for (int i = 0; i < count; i++) {
float* fdata = (float*)(idata + i * 8);
unsigned int colorInt = idata[i * 8 + 5];
unsigned char cr = (colorInt >> 24) & 0xFF;
unsigned char cg = (colorInt >> 16) & 0xFF;
unsigned char cb = (colorInt >> 8) & 0xFF;
unsigned char ca = colorInt & 0xFF;
unsigned int normalInt = idata[i * 8 + 6];
int8_t nx = (int8_t)(normalInt & 0xFF);
int8_t ny = (int8_t)((normalInt >> 8) & 0xFF);
int8_t nz = (int8_t)((normalInt >> 16) & 0xFF);
unsigned int tex2Int = idata[i * 8 + 7];
if (nx != 0 || ny != 0 || nz != 0) {
::glNormal3f(nx / 127.0f, ny / 127.0f, nz / 127.0f);
}
// This breaks particle colors.. i think. fixme!
if (colorInt != 0) {
::glColor4ub(cr, cg, cb, ca);
}
::glTexCoord2f(fdata[3], fdata[4]);
// Unit 1 (lightmap) UVs - 0xfe00fe00 is sentinel for "no Unit 1
// UVs" Ugly hack, replace soon.
if (tex2Int != 0xfe00fe00) {
float u2 = (float)(short)(tex2Int & 0xFFFF) / 256.0f;
float v2 = (float)(short)((tex2Int >> 16) & 0xFFFF) / 256.0f;
::glMultiTexCoord2f(GL_TEXTURE1, u2, v2);
}
::glVertex3f(fdata[0], fdata[1], fdata[2]);
}
::glEnd();
}
::glFlush();
pthread_mutex_unlock(&s_glCallMutex);
}
void C4JRender::CBuffLockStaticCreations() {}
int C4JRender::CBuffCreate(int count) {
int id = (int)::glGenLists(count);
::glFlush();
return id;
}
void C4JRender::CBuffDelete(int first, int count) {
if (first > 0 && count > 0) {
::glDeleteLists(first, count);
::glFlush();
}
}
void C4JRender::CBuffStart(int index, bool /*full*/) {
if (index > 0) {
::glNewList(index, GL_COMPILE);
::glFlush();
}
}
void C4JRender::CBuffClear(int index) {
if (index > 0) {
::glNewList(index, GL_COMPILE);
::glEndList();
::glFlush();
}
}
int C4JRender::CBuffSize(int /*index*/) { return 0; }
void C4JRender::CBuffEnd() {
::glEndList();
::glFlush();
}
bool C4JRender::CBuffCall(int index, bool /*full*/) {
if (index <= 0) return false;
if (::glIsList(index)) {
::glCallList(index);
return true;
}
return false;
}
void C4JRender::CBuffTick() {}
void C4JRender::CBuffDeferredModeStart() {}
void C4JRender::CBuffDeferredModeEnd() {}
int C4JRender::TextureCreate() {
GLuint id = 0;
::glGenTextures(1, &id);
return (int)id;
}
void C4JRender::TextureFree(int idx) {
GLuint id = (GLuint)idx;
::glDeleteTextures(1, &id);
}
void C4JRender::TextureBind(int idx) {
if (idx < 0) {
::glBindTexture(GL_TEXTURE_2D, 0);
} else {
::glBindTexture(GL_TEXTURE_2D, (GLuint)idx);
}
}
void C4JRender::TextureBindVertex(int idx, bool scaleLight) {
// Unit 1 used for lightmapping in fixed-function or standard shaders
::glActiveTexture(GL_TEXTURE1);
if (idx < 0) {
::glBindTexture(GL_TEXTURE_2D, 0);
::glDisable(GL_TEXTURE_2D);
} else {
::glEnable(GL_TEXTURE_2D);
::glBindTexture(GL_TEXTURE_2D, (GLuint)idx);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// 4jcraft: jank workaround for entities
// referenced from the disabled code in GameRenderer::turnOnLightLayer
if (scaleLight) {
::glMatrixMode(GL_TEXTURE);
::glLoadIdentity();
float s = 1 / 16.0f / 15.0f * 15 / 16;
::glScalef(s, s, s);
::glTranslatef(8.0f, 8.0f, 8.0f);
::glMatrixMode(GL_MODELVIEW);
}
}
::glActiveTexture(GL_TEXTURE0);
::glFlush();
}
void C4JRender::TextureSetTextureLevels(int levels) {
// base level is always 0, no mipmaps sadly. I'll add them later.
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,
levels > 0 ? levels - 1 : 0);
s_textureLevels = levels;
}
int C4JRender::TextureGetTextureLevels() { return s_textureLevels; }
void C4JRender::TextureData(int width, int height, void* data, int level,
eTextureFormat /*format*/) {
// TODO: Check if correct format.
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data);
::glFlush();
if (level == 0) {
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
void C4JRender::TextureDataUpdate(int xoffset, int yoffset, int width,
int height, void* data, int level) {
::glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, data);
::glFlush();
}
void C4JRender::TextureSetParam(int param, int value) {
::glTexParameteri(GL_TEXTURE_2D, param, value);
}
void C4JRender::TextureDynamicUpdateStart() {}
void C4JRender::TextureDynamicUpdateEnd() {}
void C4JRender::Tick() {}
void C4JRender::UpdateGamma(unsigned short) {}
// Converts RGBA data to the format expected by the texture loader.
static int LoadFromSTB(unsigned char* data, int width, int height,
D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut) {
int pixelCount = width * height;
int* pixels = new int[pixelCount];
for (int i = 0; i < pixelCount; i++) {
unsigned char r = data[i * 4 + 0];
unsigned char g = data[i * 4 + 1];
unsigned char b = data[i * 4 + 2];
unsigned char a = data[i * 4 + 3];
// pixels[i] = (a << 24) | (b << 16) | (g << 8) | r;
pixels[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
if (pSrcInfo) {
pSrcInfo->Width = width;
pSrcInfo->Height = height;
}
*ppDataOut = pixels;
return 0;
}
int C4JRender::LoadTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo,
int** ppDataOut) {
int width, height, channels;
unsigned char* data = stbi_load(szFilename, &width, &height, &channels, 4);
if (!data) return -1;
const int hr = LoadFromSTB(data, width, height, pSrcInfo, ppDataOut);
stbi_image_free(data);
return hr;
}
int C4JRender::LoadTextureData(std::uint8_t* pbData,
std::uint32_t byteCount,
D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut) {
int width, height, channels;
unsigned char* data =
stbi_load_from_memory(pbData, byteCount, &width, &height, &channels, 4);
if (!data) return -1;
const int hr = LoadFromSTB(data, width, height, pSrcInfo, ppDataOut);
stbi_image_free(data);
return hr;
}
int C4JRender::SaveTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo,
int* ppDataOut) {
return 0;
}
int C4JRender::SaveTextureDataToMemory(void* pOutput, int outputCapacity,
int* outputLength, int width,
int height, int* ppDataIn) {
return 0;
}
void C4JRender::TextureGetStats() {}
void* C4JRender::TextureGetTexture(int idx) { return nullptr; }
void C4JRender::StateSetColour(float r, float g, float b, float a) {
::glColor4f(r, g, b, a);
}
void C4JRender::StateSetDepthMask(bool enable) {
::glDepthMask(enable ? GL_TRUE : GL_FALSE);
}
void C4JRender::StateSetBlendEnable(bool enable) {
if (enable)
::glEnable(GL_BLEND);
else
::glDisable(GL_BLEND);
}
void C4JRender::StateSetBlendFunc(int src, int dst) { ::glBlendFunc(src, dst); }
void C4JRender::StateSetBlendFactor(unsigned int colour) {
// colour is 0xAARRGGBB packed
float a = ((colour >> 24) & 0xFF) / 255.0f;
float r = ((colour >> 16) & 0xFF) / 255.0f;
float g = ((colour >> 8) & 0xFF) / 255.0f;
float b = (colour & 0xFF) / 255.0f;
::glBlendColor(r, g, b, a);
}
void C4JRender::StateSetAlphaFunc(int func, float param) {
::glAlphaFunc(func, param);
}
void C4JRender::StateSetDepthFunc(int func) { ::glDepthFunc(func); }
void C4JRender::StateSetFaceCull(bool enable) {
if (enable)
::glEnable(GL_CULL_FACE);
else
::glDisable(GL_CULL_FACE);
}
void C4JRender::StateSetFaceCullCW(bool enable) {
::glFrontFace(enable ? GL_CW : GL_CCW);
}
void C4JRender::StateSetLineWidth(float width) { ::glLineWidth(width); }
void C4JRender::StateSetWriteEnable(bool red, bool green, bool blue,
bool alpha) {
::glColorMask(red, green, blue, alpha);
}
void C4JRender::StateSetDepthTestEnable(bool enable) {
if (enable)
::glEnable(GL_DEPTH_TEST);
else
::glDisable(GL_DEPTH_TEST);
}
void C4JRender::StateSetAlphaTestEnable(bool enable) {
if (enable)
::glEnable(GL_ALPHA_TEST);
else
::glDisable(GL_ALPHA_TEST);
}
void C4JRender::StateSetDepthSlopeAndBias(float slope, float bias) {
if (slope != 0.0f || bias != 0.0f) {
::glEnable(GL_POLYGON_OFFSET_FILL);
::glPolygonOffset(slope, bias);
} else {
::glDisable(GL_POLYGON_OFFSET_FILL);
}
}
void C4JRender::StateSetFogEnable(bool enable) {
if (enable)
::glEnable(GL_FOG);
else
::glDisable(GL_FOG);
}
void C4JRender::StateSetFogMode(int mode) { ::glFogi(GL_FOG_MODE, mode); }
void C4JRender::StateSetFogNearDistance(float dist) {
::glFogf(GL_FOG_START, dist);
}
void C4JRender::StateSetFogFarDistance(float dist) {
::glFogf(GL_FOG_END, dist);
}
void C4JRender::StateSetFogDensity(float density) {
::glFogf(GL_FOG_DENSITY, density);
}
void C4JRender::StateSetFogColour(float red, float green, float blue) {
float c[4] = {red, green, blue, 1.0f};
::glFogfv(GL_FOG_COLOR, c);
}
void C4JRender::StateSetLightingEnable(bool enable) {
if (enable) {
::glEnable(GL_LIGHTING);
// Enable color material so glColor calls set material ambient+diffuse
::glEnable(GL_COLOR_MATERIAL);
::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
} else {
::glDisable(GL_LIGHTING);
::glDisable(GL_COLOR_MATERIAL);
}
}
void C4JRender::StateSetVertexTextureUV(float u, float v) {
::glMultiTexCoord2f(GL_TEXTURE1, u, v);
}
void C4JRender::StateSetLightColour(int light, float red, float green,
float blue) {
float diffuse[4] = {red, green, blue, 1.0f};
::glLightfv(GL_LIGHT0 + light, GL_DIFFUSE, diffuse);
}
void C4JRender::StateSetLightAmbientColour(float red, float green, float blue) {
float ambient[4] = {red, green, blue, 1.0f};
float model[4] = {red, green, blue, 1.0f};
::glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model);
::glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
}
void C4JRender::StateSetLightDirection(int light, float x, float y, float z) {
float dir[4] = {x, y, z,
0.0f}; // TODO: Java seems to do the reverse, gotta check.
::glLightfv(GL_LIGHT0 + light, GL_POSITION, dir);
}
void C4JRender::StateSetLightEnable(int light, bool enable) {
GLenum l = GL_LIGHT0 + light;
if (enable)
::glEnable(l);
else
::glDisable(l);
}
void C4JRender::StateSetViewport(eViewportType viewportType) {
// Use the full framebuffer for all viewport types
::glViewport(0, 0, s_windowWidth, s_windowHeight);
}
void C4JRender::StateSetEnableViewportClipPlanes(bool enable) {
// Clip planes not commonly used in the legacy path
if (enable)
::glEnable(GL_CLIP_PLANE0);
else
::glDisable(GL_CLIP_PLANE0);
}
void C4JRender::StateSetTexGenCol(int col, float x, float y, float z, float w,
bool eyeSpace) {
GLenum coord;
switch (col) {
case 0:
coord = GL_S;
break;
case 1:
coord = GL_T;
break;
case 2:
coord = GL_R;
break;
case 3:
coord = GL_Q;
break;
default:
coord = GL_S;
break;
}
float plane[4] = {x, y, z, w};
GLenum planeMode = eyeSpace ? GL_EYE_PLANE : GL_OBJECT_PLANE;
::glTexGeni(coord, GL_TEXTURE_GEN_MODE,
eyeSpace ? GL_EYE_LINEAR : GL_OBJECT_LINEAR);
::glTexGenfv(coord, planeMode, plane);
}
void C4JRender::StateSetStencil(int Function, uint8_t stencil_ref,
uint8_t stencil_func_mask,
uint8_t stencil_write_mask) {
::glEnable(GL_STENCIL_TEST);
::glStencilFunc(Function, stencil_ref, stencil_func_mask);
::glStencilMask(stencil_write_mask);
}
void C4JRender::StateSetForceLOD(int LOD) {} // No LOD bias in legacy GL path
void C4JRender::BeginEvent(const wchar_t* eventName) {}
void C4JRender::EndEvent() {}
void C4JRender::Suspend() {}
bool C4JRender::Suspended() { return false; }
void C4JRender::Resume() {}

View file

@ -1,325 +0,0 @@
#pragma once
#include <cstdint>
#include <cstdlib>
class ImageFileBuffer {
public:
enum EImageType { e_typePNG, e_typeJPG };
EImageType m_type;
void* m_pBuffer;
int m_bufferSize;
int GetType() { return m_type; }
void* GetBufferPointer() { return m_pBuffer; }
int GetBufferSize() { return m_bufferSize; }
void Release() {
std::free(m_pBuffer);
m_pBuffer = nullptr;
}
bool Allocated() { return m_pBuffer != nullptr; }
};
typedef struct {
int Width;
int Height;
} D3DXIMAGE_INFO;
typedef struct _XSOCIAL_PREVIEWIMAGE {
std::uint8_t* pBytes;
std::uint32_t Pitch;
std::uint32_t Width;
std::uint32_t Height;
// D3DFORMAT Format;
} XSOCIAL_PREVIEWIMAGE, *PXSOCIAL_PREVIEWIMAGE;
class C4JRender {
public:
void Tick();
void UpdateGamma(unsigned short usGamma);
// Matrix stack
void MatrixMode(int type);
void MatrixSetIdentity();
void MatrixTranslate(float x, float y, float z);
void MatrixRotate(float angle, float x, float y, float z);
void MatrixScale(float x, float y, float z);
void MatrixPerspective(float fovy, float aspect, float zNear, float zFar);
void MatrixOrthogonal(float left, float right, float bottom, float top,
float zNear, float zFar);
void MatrixPop();
void MatrixPush();
void MatrixMult(float* mat);
const float* MatrixGet(int type);
void Set_matrixDirty();
// Core
void Initialise();
void InitialiseContext();
// Call before Initialise() to override window size and/or fullscreen mode.
// If not called, the primary monitor's native resolution is used.
void SetWindowSize(int w, int h);
void SetFullscreen(bool fs);
void StartFrame();
void DoScreenGrabOnNextPresent();
void Present();
void Clear(int flags);
void SetClearColour(const float colourRGBA[4]);
bool IsWidescreen();
bool IsHiDef();
void GetFramebufferSize(int& width, int& height);
void CaptureThumbnail(ImageFileBuffer* pngOut);
void CaptureScreen(ImageFileBuffer* jpgOut,
XSOCIAL_PREVIEWIMAGE* previewOut);
void BeginConditionalSurvey(int identifier);
void EndConditionalSurvey();
void BeginConditionalRendering(int identifier);
void EndConditionalRendering();
// Vertex data handling
typedef enum {
VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, // Position 3 x float, texture 2 x
// float, colour 4 x byte, normal 4 x
// byte, padding 1 32-bit word
VERTEX_TYPE_COMPRESSED, // Compressed format - see comment at top of
// VS_PS3_TS2_CS1.hlsl for description of
// layout
VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_LIT, // as
// VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1
// with lighting applied,
VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN, // as
// VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1
// with tex gen
VERTEX_TYPE_COUNT
} eVertexType;
// Pixel shader
typedef enum {
PIXEL_SHADER_TYPE_STANDARD,
PIXEL_SHADER_TYPE_PROJECTION,
PIXEL_SHADER_TYPE_FORCELOD,
PIXEL_SHADER_COUNT
} ePixelShaderType;
typedef enum {
VIEWPORT_TYPE_FULLSCREEN,
VIEWPORT_TYPE_SPLIT_TOP,
VIEWPORT_TYPE_SPLIT_BOTTOM,
VIEWPORT_TYPE_SPLIT_LEFT,
VIEWPORT_TYPE_SPLIT_RIGHT,
VIEWPORT_TYPE_QUADRANT_TOP_LEFT,
VIEWPORT_TYPE_QUADRANT_TOP_RIGHT,
VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT,
VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT,
} eViewportType;
typedef enum {
PRIMITIVE_TYPE_TRIANGLE_LIST,
PRIMITIVE_TYPE_TRIANGLE_STRIP,
PRIMITIVE_TYPE_TRIANGLE_FAN,
PRIMITIVE_TYPE_QUAD_LIST,
PRIMITIVE_TYPE_LINE_LIST,
PRIMITIVE_TYPE_LINE_STRIP,
PRIMITIVE_TYPE_COUNT
} ePrimitiveType;
void DrawVertices(ePrimitiveType PrimitiveType, int count, void* dataIn,
eVertexType vType, C4JRender::ePixelShaderType psType);
// Command buffers
void CBuffLockStaticCreations();
int CBuffCreate(int count);
void CBuffDelete(int first, int count);
void CBuffStart(int index, bool full = false);
void CBuffClear(int index);
int CBuffSize(int index);
void CBuffEnd();
bool CBuffCall(int index, bool full = true);
void CBuffTick();
void CBuffDeferredModeStart();
void CBuffDeferredModeEnd();
typedef enum {
TEXTURE_FORMAT_RxGyBzAw, // Normal 32-bit RGBA texture, 8 bits per
// component
/* Don't think these are all directly available on D3D 11 - leaving for
now TEXTURE_FORMAT_R0G0B0Ax, // One 8-bit component mapped to
alpha channel, R=G=B=0 TEXTURE_FORMAT_R1G1B1Ax, // One 8-bit
component mapped to alpha channel, R=G=B=1 TEXTURE_FORMAT_RxGxBxAx,
// One 8-bit component mapped to all channels
*/
MAX_TEXTURE_FORMATS
} eTextureFormat;
// Textures
int TextureCreate();
void TextureFree(int idx);
void TextureBind(int idx);
void TextureBindVertex(int idx, bool scaleLight = false);
void TextureSetTextureLevels(int levels);
int TextureGetTextureLevels();
void TextureData(int width, int height, void* data, int level,
eTextureFormat format = TEXTURE_FORMAT_RxGyBzAw);
void TextureDataUpdate(int xoffset, int yoffset, int width, int height,
void* data, int level);
void TextureSetParam(int param, int value);
void TextureDynamicUpdateStart();
void TextureDynamicUpdateEnd();
int LoadTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo,
int** ppDataOut);
int LoadTextureData(std::uint8_t* pbData, std::uint32_t byteCount,
D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut);
int SaveTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo,
int* ppDataOut);
int SaveTextureDataToMemory(void* pOutput, int outputCapacity,
int* outputLength, int width, int height,
int* ppDataIn);
void TextureGetStats();
void* TextureGetTexture(int idx);
// State control
void StateSetColour(float r, float g, float b, float a);
void StateSetDepthMask(bool enable);
void StateSetBlendEnable(bool enable);
void StateSetBlendFunc(int src, int dst);
void StateSetBlendFactor(unsigned int colour);
void StateSetAlphaFunc(int func, float param);
void StateSetDepthFunc(int func);
void StateSetFaceCull(bool enable);
void StateSetFaceCullCW(bool enable);
void StateSetLineWidth(float width);
void StateSetWriteEnable(bool red, bool green, bool blue, bool alpha);
void StateSetDepthTestEnable(bool enable);
void StateSetAlphaTestEnable(bool enable);
void StateSetDepthSlopeAndBias(float slope, float bias);
void StateSetFogEnable(bool enable);
void StateSetFogMode(int mode);
void StateSetFogNearDistance(float dist);
void StateSetFogFarDistance(float dist);
void StateSetFogDensity(float density);
void StateSetFogColour(float red, float green, float blue);
void StateSetLightingEnable(bool enable);
void StateSetVertexTextureUV(float u, float v);
void StateSetLightColour(int light, float red, float green, float blue);
void StateSetLightAmbientColour(float red, float green, float blue);
void StateSetLightDirection(int light, float x, float y, float z);
void StateSetLightEnable(int light, bool enable);
void StateSetViewport(eViewportType viewportType);
void StateSetEnableViewportClipPlanes(bool enable);
void StateSetTexGenCol(int col, float x, float y, float z, float w,
bool eyeSpace);
void StateSetStencil(int Function, std::uint8_t stencil_ref,
std::uint8_t stencil_func_mask,
std::uint8_t stencil_write_mask);
void StateSetForceLOD(int LOD);
// Event tracking
void BeginEvent(const wchar_t* eventName);
void EndEvent();
// PLM event handling
void Suspend();
bool Suspended();
void Resume();
// Linux window management
bool ShouldClose();
void Close();
void Shutdown();
};
const int GL_MODELVIEW_MATRIX = 0x0BA6;
const int GL_PROJECTION_MATRIX = 0x0BA7;
const int GL_MODELVIEW = 0x1700;
const int GL_PROJECTION = 0x1701;
const int GL_TEXTURE = 0x1702;
// These things required for tex gen
const int GL_S = 0x2000;
const int GL_T = 0x2001;
const int GL_R = 0x2002;
const int GL_Q = 0x2003;
const int GL_TEXTURE_GEN_S = 0x0C60;
const int GL_TEXTURE_GEN_T = 0x0C61;
const int GL_TEXTURE_GEN_Q = 0x0C63;
const int GL_TEXTURE_GEN_R = 0x0C62;
const int GL_TEXTURE_GEN_MODE = 0x2500;
const int GL_OBJECT_LINEAR = 0x2401;
const int GL_EYE_LINEAR = 0x2400;
const int GL_OBJECT_PLANE = 0x2501;
const int GL_EYE_PLANE = 0x2502;
// These things are used by glEnable/glDisable so must be different and non-zero
// (zero is used by things we haven't assigned yet)
const int GL_TEXTURE_2D = 0x0DE1;
const int GL_BLEND = 0x0BE2;
const int GL_CULL_FACE = 0x0B44;
const int GL_ALPHA_TEST = 0x0BC0;
const int GL_DEPTH_TEST = 0x0B71;
const int GL_FOG = 0x0B60;
const int GL_LIGHTING = 0x0B50;
const int GL_LIGHT0 = 0x4000;
const int GL_LIGHT1 = 0x4001;
const int CLEAR_DEPTH_FLAG = 0x00000100;
const int CLEAR_COLOUR_FLAG = 0x00004000;
const int GL_DEPTH_BUFFER_BIT = CLEAR_DEPTH_FLAG;
const int GL_COLOR_BUFFER_BIT = CLEAR_COLOUR_FLAG;
const int GL_SRC_ALPHA = 0x0302;
const int GL_ONE_MINUS_SRC_ALPHA = 0x0303;
const int GL_ONE = 1;
const int GL_ZERO = 0;
const int GL_DST_ALPHA = 0x0304;
const int GL_SRC_COLOR = 0x0300;
const int GL_DST_COLOR = 0x0306;
const int GL_ONE_MINUS_DST_COLOR = 0x0307;
const int GL_ONE_MINUS_SRC_COLOR = 0x0301;
const int GL_CONSTANT_ALPHA = 0x8003;
const int GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004;
const int GL_GREATER = 0x0204;
const int GL_EQUAL = 0x0202;
const int GL_LEQUAL = 0x0203;
const int GL_GEQUAL = 0x0206;
const int GL_ALWAYS = 0x0207;
const int GL_TEXTURE_MIN_FILTER = 0x2801;
const int GL_TEXTURE_MAG_FILTER = 0x2800;
const int GL_TEXTURE_WRAP_S = 0x2802;
const int GL_TEXTURE_WRAP_T = 0x2803;
const int GL_NEAREST = 0x2600;
const int GL_LINEAR = 0x2601;
const int GL_EXP = 0x0800;
const int GL_NEAREST_MIPMAP_LINEAR = 0x2702; // TODO - mipmapping bit of this
const int GL_CLAMP = 0x2900;
const int GL_REPEAT = 0x2901;
const int GL_FOG_START = 0x0B63;
const int GL_FOG_END = 0x0B64;
const int GL_FOG_MODE = 0x0B65;
const int GL_FOG_DENSITY = 0x0B62;
const int GL_FOG_COLOR = 0x0B66;
const int GL_POSITION = 0x1203;
const int GL_AMBIENT = 0x1200;
const int GL_DIFFUSE = 0x1201;
const int GL_SPECULAR = 0x1202;
const int GL_LIGHT_MODEL_AMBIENT = 0x0B53;
const int GL_LINES = 0x0001;
const int GL_LINE_STRIP = 0x0003;
const int GL_QUADS = 0x0007;
const int GL_TRIANGLE_FAN = 0x0006;
const int GL_TRIANGLE_STRIP = 0x0005;
// Singleton
extern C4JRender RenderManager;

View file

@ -1,18 +0,0 @@
render_sources = files(
'4J_Render.cpp',
'stdafx.cpp',
)
lib_render = static_library('4J_Render',
render_sources,
include_directories : include_directories('.'),
dependencies : [sdl2_dep, gl_dep, thread_dep],
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
render_dep = declare_dependency(
link_with : lib_render,
include_directories : include_directories('.'),
)

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
#include "stdafx.h"

View file

@ -1,6 +0,0 @@
#ifndef _4J_RENDER_STADAFX_H
#define _4J_RENDER_STADAFX_H
#include "../4J.Common/4J_Compat.h"
#endif //_4J_RENDER_STADAFX_H

View file

@ -1,222 +0,0 @@
#include "4J_Storage.h"
#include <cstring>
#include <vector>
#include <string>
C4JStorage StorageManager;
static XMARKETPLACE_CONTENTOFFER_INFO s_dummyOffer = {};
static XCONTENT_DATA s_dummyContentData = {};
C4JStorage::C4JStorage() : m_pStringTable(nullptr) {}
void C4JStorage::Tick(void) {}
C4JStorage::EMessageResult C4JStorage::RequestMessageBox(
unsigned int uiTitle, unsigned int uiText, unsigned int* uiOptionA,
unsigned int uiOptionC, unsigned int pad,
int (*Func)(void*, int, const C4JStorage::EMessageResult), void* lpParam,
C4JStringTable* pStringTable, wchar_t* pwchFormatString,
unsigned int focusButton) {
return EMessage_ResultAccept;
}
C4JStorage::EMessageResult C4JStorage::GetMessageBoxResult() {
return EMessage_Undefined;
}
bool C4JStorage::SetSaveDevice(int (*Func)(void*, const bool), void* lpParam,
bool bForceResetOfSaveDevice) {
return true;
}
void C4JStorage::Init(unsigned int uiSaveVersion,
const wchar_t* pwchDefaultSaveName,
char* pszSavePackName, int iMinimumSaveSize,
int (*Func)(void*, const ESavingMessage, int),
void* lpParam, const char* szGroupID) {}
void C4JStorage::ResetSaveData() {}
void C4JStorage::SetDefaultSaveNameForKeyboardDisplay(
const wchar_t* pwchDefaultSaveName) {}
void C4JStorage::SetSaveTitle(const wchar_t* pwchDefaultSaveName) {}
bool C4JStorage::GetSaveUniqueNumber(int* piVal) {
if (piVal) *piVal = 0;
return true;
}
bool C4JStorage::GetSaveUniqueFilename(char* pszName) {
if (pszName) pszName[0] = '\0';
return true;
}
void C4JStorage::SetSaveUniqueFilename(char* szFilename) {}
void C4JStorage::SetState(ESaveGameControlState eControlState,
int (*Func)(void*, const bool), void* lpParam) {}
void C4JStorage::SetSaveDisabled(bool bDisable) {}
bool C4JStorage::GetSaveDisabled(void) { return false; }
unsigned int C4JStorage::GetSaveSize() { return 0; }
void C4JStorage::GetSaveData(void* pvData, unsigned int* puiBytes) {
if (puiBytes) *puiBytes = 0;
}
void* C4JStorage::AllocateSaveData(unsigned int uiBytes) {
return malloc(uiBytes);
}
void C4JStorage::SetSaveImages(std::uint8_t* pbThumbnail,
unsigned int thumbnailBytes,
std::uint8_t* pbImage,
unsigned int imageBytes,
std::uint8_t* pbTextData,
unsigned int textDataBytes) {}
C4JStorage::ESaveGameState C4JStorage::SaveSaveData(int (*Func)(void*,
const bool),
void* lpParam) {
return ESaveGame_Idle;
}
void C4JStorage::CopySaveDataToNewSave(std::uint8_t* pbThumbnail,
unsigned int cbThumbnail,
wchar_t* wchNewName,
int (*Func)(void* lpParam, bool),
void* lpParam) {}
void C4JStorage::SetSaveDeviceSelected(unsigned int uiPad, bool bSelected) {}
bool C4JStorage::GetSaveDeviceSelected(unsigned int iPad) { return true; }
C4JStorage::ESaveGameState C4JStorage::DoesSaveExist(bool* pbExists) {
if (pbExists) *pbExists = false;
return ESaveGame_Idle;
}
bool C4JStorage::EnoughSpaceForAMinSaveGame() { return true; }
void C4JStorage::SetSaveMessageVPosition(float fY) {}
C4JStorage::ESaveGameState C4JStorage::GetSavesInfo(
int iPad,
int (*Func)(void* lpParam, SAVE_DETAILS* pSaveDetails, const bool),
void* lpParam, char* pszSavePackName) {
return ESaveGame_Idle;
}
PSAVE_DETAILS C4JStorage::ReturnSavesInfo() { return nullptr; }
void C4JStorage::ClearSavesInfo() {}
C4JStorage::ESaveGameState C4JStorage::LoadSaveDataThumbnail(
PSAVE_INFO pSaveInfo,
int (*Func)(void* lpParam, std::uint8_t* thumbnailData,
unsigned int thumbnailBytes),
void* lpParam) {
return ESaveGame_Idle;
}
void C4JStorage::GetSaveCacheFileInfo(unsigned int fileIndex,
XCONTENT_DATA& xContentData) {
memset(&xContentData, 0, sizeof(xContentData));
}
void C4JStorage::GetSaveCacheFileInfo(unsigned int fileIndex,
std::uint8_t** ppbImageData,
unsigned int* pImageBytes) {
if (ppbImageData) *ppbImageData = nullptr;
if (pImageBytes) *pImageBytes = 0;
}
C4JStorage::ESaveGameState C4JStorage::LoadSaveData(
PSAVE_INFO pSaveInfo, int (*Func)(void* lpParam, const bool, const bool),
void* lpParam) {
return ESaveGame_Idle;
}
C4JStorage::ESaveGameState C4JStorage::DeleteSaveData(PSAVE_INFO pSaveInfo,
int (*Func)(void* lpParam,
const bool),
void* lpParam) {
return ESaveGame_Idle;
}
void C4JStorage::RegisterMarketplaceCountsCallback(
int (*Func)(void* lpParam, C4JStorage::DLC_TMS_DETAILS*, int),
void* lpParam) {}
void C4JStorage::SetDLCPackageRoot(char* pszDLCRoot) {}
C4JStorage::EDLCStatus C4JStorage::GetDLCOffers(
int iPad, int (*Func)(void*, int, std::uint32_t, int), void* lpParam,
std::uint32_t dwOfferTypesBitmask) {
return EDLC_NoOffers;
}
unsigned int C4JStorage::CancelGetDLCOffers() { return 0; }
void C4JStorage::ClearDLCOffers() {}
XMARKETPLACE_CONTENTOFFER_INFO& C4JStorage::GetOffer(unsigned int dw) { return s_dummyOffer; }
int C4JStorage::GetOfferCount() { return 0; }
unsigned int C4JStorage::InstallOffer(int iOfferIDC, std::uint64_t* ullOfferIDA,
int (*Func)(void*, int, int),
void* lpParam, bool bTrial) {
return 0;
}
unsigned int C4JStorage::GetAvailableDLCCount(int iPad) { return 0; }
C4JStorage::EDLCStatus C4JStorage::GetInstalledDLC(int iPad,
int (*Func)(void*, int, int),
void* lpParam) {
if (Func) {
Func(lpParam, 0, iPad);
}
return EDLC_NoInstalledDLC;
}
XCONTENT_DATA& C4JStorage::GetDLC(unsigned int dw) { return s_dummyContentData; }
std::uint32_t C4JStorage::MountInstalledDLC(
int iPad, std::uint32_t dwDLC,
int (*Func)(void*, int, std::uint32_t, std::uint32_t), void* lpParam,
const char* szMountDrive) {
return 0;
}
unsigned int C4JStorage::UnmountInstalledDLC(const char* szMountDrive) {
return 0;
}
void C4JStorage::GetMountedDLCFileList(const char* szMountDrive,
std::vector<std::string>& fileList) {
fileList.clear();
}
std::string C4JStorage::GetMountedPath(std::string szMount) { return ""; }
C4JStorage::ETMSStatus C4JStorage::ReadTMSFile(
int iQuadrant, eGlobalStorage eStorageFacility,
C4JStorage::eTMS_FileType eFileType, wchar_t* pwchFilename,
std::uint8_t** ppBuffer, unsigned int* pBufferSize,
int (*Func)(void*, wchar_t*, int, bool, int), void* lpParam,
int iAction) {
return ETMSStatus_Fail;
}
bool C4JStorage::WriteTMSFile(int iQuadrant, eGlobalStorage eStorageFacility,
wchar_t* pwchFilename, std::uint8_t* pBuffer,
unsigned int bufferSize) {
return false;
}
bool C4JStorage::DeleteTMSFile(int iQuadrant, eGlobalStorage eStorageFacility,
wchar_t* pwchFilename) {
return false;
}
void C4JStorage::StoreTMSPathName(wchar_t* pwchName) {}
C4JStorage::ETMSStatus C4JStorage::TMSPP_ReadFile(
int iPad, C4JStorage::eGlobalStorage eStorageFacility,
C4JStorage::eTMS_FILETYPEVAL eFileTypeVal, const char* szFilename,
int (*Func)(void*, int, int, PTMSPP_FILEDATA, const char*), void* lpParam,
int iUserData) {
return ETMSStatus_Fail;
}
unsigned int C4JStorage::CRC(unsigned char* buf, int len) {
unsigned int crc = 0xFFFFFFFF;
for (int i = 0; i < len; i++) {
crc ^= buf[i];
for (int j = 0; j < 8; j++) {
crc = (crc >> 1) ^ (0xEDB88320 & (-(crc & 1)));
}
}
return ~crc;
}
int C4JStorage::AddSubfile(int regionIndex) {
(void)regionIndex;
return 0;
}
unsigned int C4JStorage::GetSubfileCount() { return 0; }
void C4JStorage::GetSubfileDetails(unsigned int i, int* regionIndex,
void** data, unsigned int* size) {
(void)i;
if (regionIndex) *regionIndex = 0;
if (data) *data = 0;
if (size) *size = 0;
}
void C4JStorage::ResetSubfiles() {}
void C4JStorage::UpdateSubfile(int index, void* data, unsigned int size) {
(void)index;
(void)data;
(void)size;
}
void C4JStorage::SaveSubfiles(int (*Func)(void*, const bool), void* param) {
if (Func) Func(param, true);
}
C4JStorage::ESaveGameState C4JStorage::GetSaveState() { return ESaveGame_Idle; }
void C4JStorage::ContinueIncompleteOperation() {}

View file

@ -1,379 +0,0 @@
#pragma once
#include <cstdint>
#include <ctime>
#include <string>
#include <vector>
// #include <xtms.h>
#include "../4J.Common/4J_Compat.h"
class C4JStringTable;
#define MAX_DISPLAYNAME_LENGTH 128 // CELL_SAVEDATA_SYSP_SUBTITLE_SIZE on PS3
#define MAX_DETAILS_LENGTH 128 // CELL_SAVEDATA_SYSP_SUBTITLE_SIZE on PS3
#define MAX_SAVEFILENAME_LENGTH 32 // CELL_SAVEDATA_DIRNAME_SIZE
typedef struct {
time_t modifiedTime;
unsigned int dataSize;
unsigned int thumbnailSize;
} CONTAINER_METADATA;
typedef struct {
char UTF8SaveFilename[MAX_SAVEFILENAME_LENGTH];
char UTF8SaveTitle[MAX_DISPLAYNAME_LENGTH];
CONTAINER_METADATA metaData;
std::uint8_t* thumbnailData;
} SAVE_INFO, *PSAVE_INFO;
typedef struct {
int iSaveC;
PSAVE_INFO SaveInfoA;
} SAVE_DETAILS, *PSAVE_DETAILS;
typedef std::vector<PXMARKETPLACE_CONTENTOFFER_INFO> OfferDataArray;
typedef std::vector<PXCONTENT_DATA> XContentDataArray;
// typedef std::vector <PSAVE_DETAILS> SaveDetailsArray;
// Current version of the dlc data creator
#define CURRENT_DLC_VERSION_NUM 3
class C4JStorage {
public:
// Structs defined in the DLC_Creator, but added here to be used in the app
typedef struct {
unsigned int uiFileSize;
std::uint32_t dwType;
std::uint32_t dwWchCount; // count of wchar_t in next array
wchar_t wchFile[1];
} DLC_FILE_DETAILS, *PDLC_FILE_DETAILS;
typedef struct {
std::uint32_t dwType;
std::uint32_t dwWchCount; // count of wchar_t in next array;
wchar_t wchData[1]; // will be an array of size dwBytes
} DLC_FILE_PARAM, *PDLC_FILE_PARAM;
// End of DLC_Creator structs
typedef struct {
wchar_t wchDisplayName[XCONTENT_MAX_DISPLAYNAME_LENGTH];
char szFileName[XCONTENT_MAX_FILENAME_LENGTH];
std::uint32_t dwImageOffset;
std::uint32_t dwImageBytes;
} CACHEINFOSTRUCT;
// structure to hold DLC info in TMS
typedef struct {
std::uint32_t dwVersion;
std::uint32_t dwNewOffers;
std::uint32_t dwTotalOffers;
std::uint32_t dwInstalledTotalOffers;
std::uint8_t bPadding[1024 - sizeof(std::uint32_t) * 4];
// future expansion
} DLC_TMS_DETAILS;
enum eGTS_FileTypes { eGTS_Type_Skin = 0, eGTS_Type_Cape, eGTS_Type_MAX };
enum eGlobalStorage {
// eGlobalStorage_GameClip=0,
eGlobalStorage_Title = 0,
eGlobalStorage_TitleUser,
eGlobalStorage_Max
};
enum EMessageResult {
EMessage_Undefined = 0,
EMessage_Busy,
EMessage_Pending,
EMessage_Cancelled,
EMessage_ResultAccept,
EMessage_ResultDecline,
EMessage_ResultThirdOption,
EMessage_ResultFourthOption
};
enum ESaveGameControlState {
ESaveGameControl_Idle = 0,
ESaveGameControl_Save,
ESaveGameControl_InternalRequestingDevice,
ESaveGameControl_InternalGetSaveName,
ESaveGameControl_InternalSaving,
ESaveGameControl_CopySave,
ESaveGameControl_CopyingSave,
};
enum ESaveGameState {
ESaveGame_Idle = 0,
ESaveGame_Save,
ESaveGame_InternalRequestingDevice,
ESaveGame_InternalGetSaveName,
ESaveGame_InternalSaving,
ESaveGame_CopySave,
ESaveGame_CopyingSave,
ESaveGame_Load,
ESaveGame_GetSavesInfo,
ESaveGame_Rename,
ESaveGame_Delete,
ESaveGame_GetSaveThumbnail // Not used as an actual state in the PS4,
// but the game expects this to be returned
// to indicate success when getting a
// thumbnail
};
enum ELoadGameStatus {
ELoadGame_Idle = 0,
ELoadGame_InProgress,
ELoadGame_NoSaves,
ELoadGame_ChangedDevice,
ELoadGame_DeviceRemoved
};
enum EDeleteGameStatus {
EDeleteGame_Idle = 0,
EDeleteGame_InProgress,
};
enum ESGIStatus {
ESGIStatus_Error = 0,
ESGIStatus_Idle,
ESGIStatus_ReadInProgress,
ESGIStatus_NoSaves,
};
enum EDLCStatus {
EDLC_Error = 0,
EDLC_Idle,
EDLC_NoOffers,
EDLC_AlreadyEnumeratedAllOffers,
EDLC_NoInstalledDLC,
EDLC_Pending,
EDLC_LoadInProgress,
EDLC_Loaded,
EDLC_ChangedDevice
};
enum ESavingMessage {
ESavingMessage_None = 0,
ESavingMessage_Short,
ESavingMessage_Long
};
enum ETMSStatus {
ETMSStatus_Idle = 0,
ETMSStatus_Fail,
ETMSStatus_Fail_ReadInProgress,
ETMSStatus_Fail_WriteInProgress,
ETMSStatus_Pending,
};
enum eTMS_FileType {
eTMS_FileType_Normal = 0,
eTMS_FileType_Graphic,
};
enum eTMS_FILETYPEVAL {
TMS_FILETYPE_BINARY,
TMS_FILETYPE_CONFIG,
TMS_FILETYPE_JSON,
TMS_FILETYPE_MAX
};
enum eTMS_UGCTYPE { TMS_UGCTYPE_NONE, TMS_UGCTYPE_IMAGE, TMS_UGCTYPE_MAX };
typedef struct {
char szFilename[256];
int iFileSize;
eTMS_FILETYPEVAL eFileTypeVal;
} TMSPP_FILE_DETAILS, *PTMSPP_FILE_DETAILS;
typedef struct {
int iCount;
PTMSPP_FILE_DETAILS FileDetailsA;
} TMSPP_FILE_LIST, *PTMSPP_FILE_LIST;
typedef struct {
unsigned int size;
std::uint8_t* pbData;
} TMSPP_FILEDATA, *PTMSPP_FILEDATA;
C4JStorage();
void Tick(void);
// Messages
C4JStorage::EMessageResult RequestMessageBox(
unsigned int uiTitle, unsigned int uiText, unsigned int* uiOptionA,
unsigned int uiOptionC, unsigned int pad = XUSER_INDEX_ANY,
int (*Func)(void*, int, const C4JStorage::EMessageResult) = nullptr,
void* lpParam = nullptr, C4JStringTable* pStringTable = nullptr,
wchar_t* pwchFormatString = nullptr, unsigned int focusButton = 0);
C4JStorage::EMessageResult GetMessageBoxResult();
// save device
bool SetSaveDevice(int (*Func)(void*, const bool), void* lpParam,
bool bForceResetOfSaveDevice = false);
// savegame
void Init(unsigned int uiSaveVersion, const wchar_t* pwchDefaultSaveName,
char* pszSavePackName, int iMinimumSaveSize,
int (*Func)(void*, const ESavingMessage, int), void* lpParam,
const char* szGroupID);
void ResetSaveData(); // Call before a new save to clear out stored save
// file name
void SetDefaultSaveNameForKeyboardDisplay(
const wchar_t* pwchDefaultSaveName);
void SetSaveTitle(const wchar_t* pwchDefaultSaveName);
bool GetSaveUniqueNumber(int* piVal);
bool GetSaveUniqueFilename(char* pszName);
void SetSaveUniqueFilename(char* szFilename);
void SetState(ESaveGameControlState eControlState,
int (*Func)(void*, const bool), void* lpParam);
void SetSaveDisabled(bool bDisable);
bool GetSaveDisabled(void);
unsigned int GetSaveSize();
void GetSaveData(void* pvData, unsigned int* puiBytes);
void* AllocateSaveData(unsigned int uiBytes);
void SetSaveImages(
std::uint8_t* pbThumbnail, unsigned int thumbnailBytes,
std::uint8_t* pbImage, unsigned int imageBytes,
std::uint8_t* pbTextData,
unsigned int textDataBytes); // Sets the thumbnail & image for the
// save, optionally setting the
// metadata in the png
C4JStorage::ESaveGameState SaveSaveData(int (*Func)(void*, const bool),
void* lpParam);
void CopySaveDataToNewSave(std::uint8_t* pbThumbnail,
unsigned int cbThumbnail, wchar_t* wchNewName,
int (*Func)(void* lpParam, bool), void* lpParam);
void SetSaveDeviceSelected(unsigned int uiPad, bool bSelected);
bool GetSaveDeviceSelected(unsigned int iPad);
C4JStorage::ESaveGameState DoesSaveExist(bool* pbExists);
bool EnoughSpaceForAMinSaveGame();
void SetSaveMessageVPosition(
float fY); // The 'Saving' message will display at a default position
// unless changed
// Get the info for the saves
C4JStorage::ESaveGameState GetSavesInfo(
int iPad,
int (*Func)(void* lpParam, SAVE_DETAILS* pSaveDetails, const bool),
void* lpParam, char* pszSavePackName);
PSAVE_DETAILS ReturnSavesInfo();
void ClearSavesInfo(); // Clears results
C4JStorage::ESaveGameState LoadSaveDataThumbnail(
PSAVE_INFO pSaveInfo,
int (*Func)(void* lpParam, std::uint8_t* thumbnailData,
unsigned int thumbnailBytes),
void* lpParam); // Get the thumbnail for an individual save referenced
// by pSaveInfo
void GetSaveCacheFileInfo(unsigned int fileIndex, XCONTENT_DATA& xContentData);
void GetSaveCacheFileInfo(unsigned int fileIndex,
std::uint8_t** ppbImageData,
unsigned int* pImageBytes);
// Load the save. Need to call GetSaveData once the callback is called
C4JStorage::ESaveGameState LoadSaveData(PSAVE_INFO pSaveInfo,
int (*Func)(void* lpParam,
const bool, const bool),
void* lpParam);
C4JStorage::ESaveGameState DeleteSaveData(PSAVE_INFO pSaveInfo,
int (*Func)(void* lpParam,
const bool),
void* lpParam);
// DLC
void RegisterMarketplaceCountsCallback(
int (*Func)(void* lpParam, C4JStorage::DLC_TMS_DETAILS*, int),
void* lpParam);
void SetDLCPackageRoot(char* pszDLCRoot);
C4JStorage::EDLCStatus GetDLCOffers(
int iPad, int (*Func)(void*, int, std::uint32_t, int), void* lpParam,
std::uint32_t dwOfferTypesBitmask =
XMARKETPLACE_OFFERING_TYPE_CONTENT);
unsigned int CancelGetDLCOffers();
void ClearDLCOffers();
XMARKETPLACE_CONTENTOFFER_INFO& GetOffer(unsigned int dw);
int GetOfferCount();
unsigned int InstallOffer(int iOfferIDC, std::uint64_t* ullOfferIDA,
int (*Func)(void*, int, int), void* lpParam,
bool bTrial = false);
unsigned int GetAvailableDLCCount(int iPad);
C4JStorage::EDLCStatus GetInstalledDLC(int iPad,
int (*Func)(void*, int, int),
void* lpParam);
XCONTENT_DATA& GetDLC(unsigned int dw);
std::uint32_t MountInstalledDLC(int iPad, std::uint32_t dwDLC,
int (*Func)(void*, int, std::uint32_t,
std::uint32_t),
void* lpParam,
const char* szMountDrive = nullptr);
unsigned int UnmountInstalledDLC(const char* szMountDrive = nullptr);
void GetMountedDLCFileList(const char* szMountDrive,
std::vector<std::string>& fileList);
std::string GetMountedPath(std::string szMount);
// Global title storage
C4JStorage::ETMSStatus ReadTMSFile(
int iQuadrant, eGlobalStorage eStorageFacility,
C4JStorage::eTMS_FileType eFileType, wchar_t* pwchFilename,
std::uint8_t** ppBuffer, unsigned int* pBufferSize,
int (*Func)(void*, wchar_t*, int, bool, int) = nullptr,
void* lpParam = nullptr, int iAction = 0);
bool WriteTMSFile(int iQuadrant, eGlobalStorage eStorageFacility,
wchar_t* pwchFilename, std::uint8_t* pBuffer,
unsigned int bufferSize);
bool DeleteTMSFile(int iQuadrant, eGlobalStorage eStorageFacility,
wchar_t* pwchFilename);
void StoreTMSPathName(wchar_t* pwchName = nullptr);
// TMS++
#ifdef _XBOX
C4JStorage::ETMSStatus WriteTMSFile(
int iPad, C4JStorage::eGlobalStorage eStorageFacility,
C4JStorage::eTMS_FileType eFileType, char* pchFilePath,
char* pchBuffer, unsigned int bufferSize, TMSCLIENT_CALLBACK Func,
void* lpParam);
int GetUserQuotaInfo(int iPad, TMSCLIENT_CALLBACK Func, void* lpParam);
#endif
// Older TMS++ write/quota entry points were kept in platform-specific
// implementations and are intentionally not part of this shared API.
C4JStorage::ETMSStatus TMSPP_ReadFile(
int iPad, C4JStorage::eGlobalStorage eStorageFacility,
C4JStorage::eTMS_FILETYPEVAL eFileTypeVal, const char* szFilename,
int (*Func)(void*, int, int, PTMSPP_FILEDATA, const char*) = nullptr,
void* lpParam = nullptr, int iUserData = 0);
// Older TMS++ list/delete helpers stayed platform-specific. The shared
// surface keeps the read path plus CRC/subfile helpers below.
// enum eXBLWS
// {
// eXBLWS_GET,
// eXBLWS_POST,
// eXBLWS_PUT,
// eXBLWS_DELETE,
// };
// bool
// XBLWS_Command(eXBLWS eCommand);
unsigned int CRC(unsigned char* buf, int len);
int AddSubfile(int regionIndex);
unsigned int GetSubfileCount();
void GetSubfileDetails(unsigned int i, int* regionIndex, void** data,
unsigned int* size);
void ResetSubfiles();
void UpdateSubfile(int index, void* data, unsigned int size);
void SaveSubfiles(int (*Func)(void*, const bool), void* param);
ESaveGameState GetSaveState();
void ContinueIncompleteOperation();
C4JStringTable* m_pStringTable;
};
extern C4JStorage StorageManager;

View file

View file

@ -1,20 +0,0 @@
storage_sources = files(
'4J_Storage.cpp',
'stdafx.cpp',
'STO_DLC.cpp',
'STO_Main.cpp',
'STO_SaveGame.cpp',
)
lib_storage = static_library('4J_Storage',
storage_sources,
include_directories : include_directories('.'),
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
storage_dep = declare_dependency(
link_with : lib_storage,
include_directories : include_directories('.'),
)

View file

@ -1 +0,0 @@
#include "stdafx.h"

View file

@ -1,6 +0,0 @@
#ifndef _4J_STORAGE_STADAFX_H
#define _4J_STORAGE_STADAFX_H
#include "../4J.Common/4J_Compat.h"
#endif //_4J_STORAGE_STADAFX_H

View file

@ -1,6 +0,0 @@
#include "../../4J.Input/4J_Input.h"
#include "../../4J.Profile/4J_Profile.h"
#include "../../4J.Render/4J_Render.h"
#include "../../4J.Storage/4J_Storage.h"
int main() { return 0; }

View file

@ -1,125 +0,0 @@
gl_dep = dependency('gl', required: false)
sdl2_dep = dependency('sdl2', required: false)
thread_dep = dependency('threads')
fourj_cpp_args = [
'-fpermissive',
'-Wshift-count-overflow',
'-pipe',
]
fourj_cpp_defs = [
'-DSPLIT_SAVES',
'-D_LARGE_WORLDS',
'-D_EXTENDED_ACHIEVEMENTS',
'-D_DEBUG_MENUS_ENABLED',
'-D_DEBUG',
'-DDEBUG',
]
if host_machine.system() == 'linux'
fourj_cpp_defs += [
'-Dlinux',
'-D__linux',
'-D__linux__',
]
endif
render_inc = include_directories('../../4J.Render', '../../4J.Common')
render_sources = files('../../4J.Render/4J_Render.cpp', '../../4J.Render/stdafx.cpp')
lib_render = static_library(
'4J_Render',
render_sources,
include_directories: render_inc,
dependencies: [sdl2_dep, gl_dep, thread_dep],
cpp_args: fourj_cpp_args + fourj_cpp_defs + [
'-include', meson.current_source_dir() / '../../4J.Render/stdafx.h',
],
)
render_dep = declare_dependency(
link_with: lib_render,
include_directories: render_inc,
dependencies: [sdl2_dep, gl_dep, thread_dep],
)
input_inc = include_directories('../../4J.Input', '../../4J.Common')
input_sources = files(
'../../4J.Input/4J_Input.cpp',
'../../4J.Input/INP_ForceFeedback.cpp',
'../../4J.Input/INP_Keyboard.cpp',
'../../4J.Input/INP_Main.cpp',
'../../4J.Input/INP_StringCheck.cpp',
'../../4J.Input/stdafx.cpp',
)
lib_input = static_library(
'4J_Input',
input_sources,
include_directories: input_inc,
dependencies: [sdl2_dep],
cpp_args: fourj_cpp_args + fourj_cpp_defs + [
'-include', meson.current_source_dir() / '../../4J.Input/stdafx.h',
],
)
input_dep = declare_dependency(
link_with: lib_input,
include_directories: input_inc,
dependencies: [sdl2_dep],
)
profile_inc = include_directories('../../4J.Profile', '../../4J.Common')
profile_sources = files(
'../../4J.Profile/4J_Profile.cpp',
'../../4J.Profile/PRO_AwardManager.cpp',
'../../4J.Profile/PRO_Data.cpp',
'../../4J.Profile/PRO_Main.cpp',
'../../4J.Profile/PRO_RichPresence.cpp',
'../../4J.Profile/PRO_Sys.cpp',
'../../4J.Profile/stdafx.cpp',
)
lib_profile = static_library(
'4J_Profile',
profile_sources,
include_directories: profile_inc,
cpp_args: fourj_cpp_args + fourj_cpp_defs + [
'-include', meson.current_source_dir() / '../../4J.Profile/stdafx.h',
],
)
profile_dep = declare_dependency(
link_with: lib_profile,
include_directories: profile_inc,
)
storage_inc = include_directories('../../4J.Storage', '../../4J.Common')
storage_sources = files(
'../../4J.Storage/4J_Storage.cpp',
'../../4J.Storage/stdafx.cpp',
'../../4J.Storage/STO_DLC.cpp',
'../../4J.Storage/STO_Main.cpp',
'../../4J.Storage/STO_SaveGame.cpp',
)
lib_storage = static_library(
'4J_Storage',
storage_sources,
include_directories: storage_inc,
cpp_args: fourj_cpp_args + fourj_cpp_defs + [
'-include', meson.current_source_dir() / '../../4J.Storage/stdafx.h',
],
)
storage_dep = declare_dependency(
link_with: lib_storage,
include_directories: storage_inc,
)
meson.override_dependency('4j-render', render_dep)
meson.override_dependency('4j-input', input_dep)
meson.override_dependency('4j-profile', profile_dep)
meson.override_dependency('4j-storage', storage_dep)
if meson.project_name() == '4jlibs'
header_smoke = executable(
'4j-header-smoke',
'header_smoke.cpp',
build_by_default: false,
)
test('4j-header-smoke', header_smoke)
endif

View file

@ -1,15 +0,0 @@
project(
'4jlibs',
['c', 'cpp'],
version: '0.1.0',
meson_version: '>=1.1',
default_options: [
'cpp_std=c++23',
'warning_level=0',
'buildtype=debug',
'unity=on',
'unity_size=8',
'b_pch=true',
],
)
subdir('builddef')

View file

@ -188,10 +188,10 @@ typedef XUID GameSessionUID;
#include "../Platform/Windows64/4JLibs/inc/4J_Render.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Storage.h"
#elif defined __linux__
#include "../../4J.Input/4J_Input.h"
#include "../../4J.Profile/4J_Profile.h"
#include "../../4J.Render/4J_Render.h"
#include "../../4J.Storage/4J_Storage.h"
#include "4J_Input.h"
#include "4J_Profile.h"
#include "4J_Render.h"
#include "4J_Storage.h"
#elif defined __PSVITA__
#include "../Platform/PSVita/4JLibs/inc/4J_Input.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Profile.h"

View file

@ -174,10 +174,10 @@ void MemSect(int sect);
#include "../../Minecraft.Client/Platform/PSVita/4JLibs/inc/4J_Storage.h"
#include "../../Minecraft.Client/Platform/PSVita/4JLibs/inc/4J_Input.h"
#elif defined __linux__
#include "../../4J.Profile/4J_Profile.h"
#include "../../4J.Render/4J_Render.h"
#include "../../4J.Storage/4J_Storage.h"
#include "../../4J.Input/4J_Input.h"
#include "4J_Profile.h"
#include "4J_Render.h"
#include "4J_Storage.h"
#include "4J_Input.h"
#else
#include "../../Minecraft.Client/Platform/Orbis/4JLibs/inc/4J_Profile.h"
#include "../../Minecraft.Client/Platform/Orbis/4JLibs/inc/4J_Render.h"

View file

@ -5,7 +5,7 @@
#include <functional>
#include <cstdint>
#include <limits>
#include "../../../4J.Common/4J_Compat.h"
#include "4J_Compat.h"
#include "../../../Minecraft.Client/Rendering/Models/SkinBox.h"

View file

@ -27,7 +27,13 @@ world_sources = run_command(
lib_world = static_library('Minecraft.World',
world_sources,
include_directories : include_directories('Platform', 'Platform/x64headers'),
dependencies : [ assets_localisation_dep ],
dependencies : [
assets_localisation_dep,
render_dep,
input_dep,
profile_dep,
storage_dep,
],
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', 'Platform/stdafx.h',
],
@ -40,4 +46,4 @@ world_dep = declare_dependency(
link_with : lib_world,
dependencies : [dep_crypto, dep_zlib],
include_directories : include_directories('Platform/x64headers'),
)
)

View file

@ -2,11 +2,7 @@
# File Config
#---------------------------------------------------------------------------
PROJECT_NAME = "4JCraft"
INPUT = ../4J.Input \
../4J.Profile \
../4J.Render \
../4J.Storage \
../Minecraft.Assets \
INPUT = ../Minecraft.Assets \
../Minecraft.Client \
../Minecraft.World \
./doxymain.md

View file

@ -1,130 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import site
import shutil
import subprocess
import sys
from pathlib import Path
PATHS_TO_KEEP = [
"4J.Common",
"4J.Input",
"4J.Profile",
"4J.Render",
"4J.Storage",
"4jlibs",
]
def run(cmd: list[str], cwd: Path | None = None) -> None:
subprocess.run(cmd, cwd=cwd, check=True)
def require_clean_destination(dest: Path) -> None:
if dest.exists():
raise SystemExit(f"Destination already exists: {dest}")
def resolve_filter_repo_command() -> list[str]:
script_name = "git-filter-repo.exe" if sys.platform == "win32" else "git-filter-repo"
path_candidates = [
shutil.which("git-filter-repo"),
shutil.which(script_name),
]
user_script_dirs = [
Path(site.USER_BASE) / "Scripts",
Path(site.getusersitepackages()).parent / "Scripts",
]
for script_dir in user_script_dirs:
user_scripts = script_dir / script_name
path_candidates.append(str(user_scripts) if user_scripts.exists() else None)
for candidate in path_candidates:
if candidate:
return [candidate]
raise SystemExit(
"git-filter-repo is required. Install it first and rerun this script."
)
def clone_source(source: Path, dest: Path) -> None:
run(["git", "clone", "--no-local", str(source), str(dest)])
def filter_history(dest: Path) -> None:
cmd = resolve_filter_repo_command() + ["--force"]
for path in PATHS_TO_KEEP:
cmd.extend(["--path", path])
run(cmd, cwd=dest)
def rewrite_staged_layout(dest: Path) -> None:
staged_root = dest / "4jlibs"
meson_src = staged_root / "meson.build"
builddef_src = staged_root / "builddef"
if not meson_src.exists() or not builddef_src.exists():
raise SystemExit("Filtered tree is missing the staged 4jlibs Meson files.")
shutil.move(str(meson_src), str(dest / "meson.build"))
shutil.move(str(builddef_src), str(dest / "builddef"))
try:
staged_root.rmdir()
except OSError:
pass
builddef_meson = dest / "builddef" / "meson.build"
builddef_smoke = dest / "builddef" / "header_smoke.cpp"
builddef_meson.write_text(
builddef_meson.read_text(encoding="utf-8").replace("../../", "../"),
encoding="utf-8",
)
builddef_smoke.write_text(
builddef_smoke.read_text(encoding="utf-8").replace("../../", "../"),
encoding="utf-8",
)
def main() -> int:
parser = argparse.ArgumentParser(
description=(
"Create a filtered 4jlibs bootstrap repo from the current 4jcraft tree."
)
)
parser.add_argument(
"destination",
type=Path,
help="Path to create the filtered 4jlibs clone in",
)
parser.add_argument(
"--source",
type=Path,
default=Path.cwd(),
help="Source 4jcraft repo to clone from (default: current working directory)",
)
args = parser.parse_args()
source = args.source.resolve()
destination = args.destination.resolve()
require_clean_destination(destination)
clone_source(source, destination)
filter_history(destination)
rewrite_staged_layout(destination)
print(f"Created filtered 4jlibs bootstrap repo at: {destination}")
return 0
if __name__ == "__main__":
sys.exit(main())