diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/Window_Xbox.c |
initial commit
Diffstat (limited to 'src/Window_Xbox.c')
-rw-r--r-- | src/Window_Xbox.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/Window_Xbox.c b/src/Window_Xbox.c new file mode 100644 index 0000000..2555879 --- /dev/null +++ b/src/Window_Xbox.c @@ -0,0 +1,254 @@ +#include "Core.h" +#if defined CC_BUILD_XBOX +#include "Window.h" +#include "Platform.h" +#include "Input.h" +#include "Event.h" +#include "Graphics.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Errors.h" +#include "ExtMath.h" +#include "VirtualKeyboard.h" +#include <hal/video.h> +#include <usbh_lib.h> +#include <xid_driver.h> + +static cc_bool launcherMode; +static xid_dev_t* xid_ctrl; +static xid_gamepad_in gp_state; + +struct _DisplayData DisplayInfo; +struct _WindowData WindowInfo; + +// TODO No idea if this even works +static void OnDataReceived(UTR_T* utr) { + xid_dev_t* xid_dev = (xid_dev_t*)utr->context; + + if (utr->status < 0 || !xid_ctrl || xid_dev != xid_ctrl) return; + + int len = min(utr->xfer_len, sizeof(gp_state)); + Mem_Copy(&gp_state, utr->buff, len); + int mods = gp_state.dButtons; + + // queue USB transfer again + // TODO don't call + utr->xfer_len = 0; + utr->bIsTransferDone = 0; + usbh_int_xfer(utr); +} + +static void OnDeviceChanged(xid_dev_t *xid_dev__, int status__) { + Platform_LogConst("Getting devices"); + xid_dev_t* xid_dev = usbh_xid_get_device_list(); + Platform_LogConst("Devices check"); + + for (; xid_dev; xid_dev = xid_dev->next) + { + int DEV = xid_dev->xid_desc.bType; + Platform_Log1("DEVICE: %i", &DEV); + if (xid_dev->xid_desc.bType != XID_TYPE_GAMECONTROLLER) + continue; + + xid_ctrl = xid_dev; + usbh_xid_read(xid_dev, 0, OnDataReceived); + return; + } + xid_ctrl = NULL; +} + +void Window_PreInit(void) { + XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); // TODO not call +} + +void Window_Init(void) { + VIDEO_MODE mode = XVideoGetMode(); + + DisplayInfo.Width = mode.width; + DisplayInfo.Height = mode.height; + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; + + Window_Main.Width = mode.width; + Window_Main.Height = mode.height; + Window_Main.Focused = true; + Window_Main.Exists = true; + + Input.Sources = INPUT_SOURCE_GAMEPAD; + DisplayInfo.ContentOffsetX = 10; + DisplayInfo.ContentOffsetY = 10; + +#ifndef CC_BUILD_CXBX + usbh_core_init(); + usbh_xid_init(); + + usbh_install_xid_conn_callback(OnDeviceChanged, OnDeviceChanged); + OnDeviceChanged(NULL, 0); // TODO useless call? +#endif +} + +void Window_Free(void) { usbh_core_deinit(); } + +void Window_Create2D(int width, int height) { launcherMode = true; } +void Window_Create3D(int width, int height) { launcherMode = false; } + +void Window_SetTitle(const cc_string* title) { } +void Clipboard_GetText(cc_string* value) { } +void Clipboard_SetText(const cc_string* value) { } + +int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; } +cc_result Window_EnterFullscreen(void) { return 0; } +cc_result Window_ExitFullscreen(void) { return 0; } +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { } +void Window_SetSize(int width, int height) { } + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + + +/*########################################################################################################################* +*----------------------------------------------------Input processing-----------------------------------------------------* +*#########################################################################################################################*/ +void Window_ProcessEvents(float delta) { +#ifndef CC_BUILD_CXBX + usbh_pooling_hubs(); +#endif +} + +void Cursor_SetPosition(int x, int y) { } // Makes no sense for Xbox + +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } +void Window_UpdateRawMouse(void) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +// https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_gamepad +// NOTE: Analog buttons use dedicated field rather than being part of dButtons +#define XINPUT_GAMEPAD_DPAD_UP 0x0001 +#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 +#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 +#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 +#define XINPUT_GAMEPAD_START 0x0010 +#define XINPUT_GAMEPAD_BACK 0x0020 +#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 +#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 + +static void HandleButtons(int port, xid_gamepad_in* gp) { + int mods = gp->dButtons; + Gamepad_SetButton(port, CCPAD_L, gp->l > 0x7F); + Gamepad_SetButton(port, CCPAD_R, gp->r > 0x7F); + Gamepad_SetButton(port, CCPAD_ZL, gp->white > 0x7F); + Gamepad_SetButton(port, CCPAD_ZR, gp->black > 0x7F); + + Gamepad_SetButton(port, CCPAD_A, gp->a > 0x7F); + Gamepad_SetButton(port, CCPAD_B, gp->b > 0x7F); + Gamepad_SetButton(port, CCPAD_X, gp->x > 0x7F); + Gamepad_SetButton(port, CCPAD_Y, gp->y > 0x7F); + + Gamepad_SetButton(port, CCPAD_START, mods & XINPUT_GAMEPAD_START); + Gamepad_SetButton(port, CCPAD_SELECT, mods & XINPUT_GAMEPAD_BACK); + Gamepad_SetButton(port, CCPAD_LSTICK, mods & XINPUT_GAMEPAD_LEFT_THUMB); + Gamepad_SetButton(port, CCPAD_RSTICK, mods & XINPUT_GAMEPAD_RIGHT_THUMB); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & XINPUT_GAMEPAD_DPAD_LEFT); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & XINPUT_GAMEPAD_DPAD_RIGHT); + Gamepad_SetButton(port, CCPAD_UP, mods & XINPUT_GAMEPAD_DPAD_UP); + Gamepad_SetButton(port, CCPAD_DOWN, mods & XINPUT_GAMEPAD_DPAD_DOWN); +} + +#define AXIS_SCALE 8192.0f +static void HandleJoystick(int port, int axis, int x, int y, float delta) { + if (Math_AbsI(x) <= 512) x = 0; + if (Math_AbsI(y) <= 512) y = 0; + + Gamepad_SetAxis(port, axis, x / AXIS_SCALE, -y / AXIS_SCALE, delta); +} + +void Window_ProcessGamepads(float delta) { + if (!xid_ctrl) return; + + HandleButtons(0, &gp_state); + HandleJoystick(0, PAD_AXIS_LEFT, gp_state.leftStickX, gp_state.leftStickY, delta); + HandleJoystick(0, PAD_AXIS_RIGHT, gp_state.rightStickX, gp_state.rightStickY, delta); +} + + +/*########################################################################################################################* +*------------------------------------------------------Framebuffer--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, 4, "window pixels"); + bmp->width = width; + bmp->height = height; +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + void* fb = XVideoGetFB(); + //XVideoWaitForVBlank(); + // XVideoWaitForVBlank installs an interrupt handler for VBlank - + // however this will cause pbkit's attempt to install an interrupt + // handler fail - so instead just accept tearing in the launcher + + cc_uint32* src = (cc_uint32*)bmp->scan0 + r.x; + cc_uint32* dst = (cc_uint32*)fb + r.x; + + for (int y = r.y; y < r.y + r.height; y++) + { + Mem_Copy(dst + y * bmp->width, src + y * bmp->width, r.width * 4); + } +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); +} + + +/*########################################################################################################################* +*------------------------------------------------------Soft keyboard------------------------------------------------------* +*#########################################################################################################################*/ +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { + if (Input.Sources & INPUT_SOURCE_NORMAL) return; + VirtualKeyboard_Open(args, launcherMode); +} + +void OnscreenKeyboard_SetText(const cc_string* text) { + VirtualKeyboard_SetText(text); +} + +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { + VirtualKeyboard_Display2D(r, bmp); +} + +void OnscreenKeyboard_Draw3D(void) { + VirtualKeyboard_Display3D(); +} + +void OnscreenKeyboard_Close(void) { + VirtualKeyboard_Close(); +} + + +/*########################################################################################################################* +*-------------------------------------------------------Misc/Other--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_ShowDialog(const char* title, const char* msg) { + /* TODO implement */ + Platform_LogConst(title); + Platform_LogConst(msg); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} +#endif |