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_3DS.c |
initial commit
Diffstat (limited to 'src/Window_3DS.c')
-rw-r--r-- | src/Window_3DS.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/Window_3DS.c b/src/Window_3DS.c new file mode 100644 index 0000000..186f035 --- /dev/null +++ b/src/Window_3DS.c @@ -0,0 +1,293 @@ +#include "Core.h" +#if defined CC_BUILD_3DS +#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 "Gui.h" +#include <3ds.h> + +static cc_bool launcherMode; +static Result irrst_result; +static u16 top_width, top_height; +static u16 btm_width, btm_height; + +struct _DisplayData DisplayInfo; +struct _WindowData WindowInfo; +struct _WindowData Window_Alt; +cc_bool launcherTop; + +void Window_PreInit(void) { + gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false); +} + +// Note from https://github.com/devkitPro/libctru/blob/master/libctru/include/3ds/gfx.h +// * Please note that the 3DS uses *portrait* screens rotated 90 degrees counterclockwise. +// * Width/height refer to the physical dimensions of the screen; that is, the top screen +// * is 240 pixels wide and 400 pixels tall; while the bottom screen is 240x320. +void Window_Init(void) { + // deliberately swapped + gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &top_height, &top_width); + gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, &btm_height, &btm_width); + + DisplayInfo.Width = top_width; + DisplayInfo.Height = top_height; + DisplayInfo.ScaleX = 0.5f; + DisplayInfo.ScaleY = 0.5f; + + Window_Main.Width = top_width; + Window_Main.Height = top_height; + Window_Main.Focused = true; + Window_Main.Exists = true; + + Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; + Input_SetTouchMode(true); + Gui_SetTouchUI(true); + Input.Sources = INPUT_SOURCE_GAMEPAD; + irrst_result = irrstInit(); + + Window_Alt.Width = btm_width; + Window_Alt.Height = btm_height; +} + +void Window_Free(void) { irrstExit(); } + +void Window_Create2D(int width, int height) { + DisplayInfo.Width = btm_width; + Window_Main.Width = btm_width; + Window_Alt.Width = top_width; + launcherMode = true; +} + +void Window_Create3D(int width, int height) { + DisplayInfo.Width = top_width; + Window_Main.Width = top_width; + Window_Alt.Width = btm_width; + 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-----------------------------------------------------* +*#########################################################################################################################*/ +static void ProcessTouchInput(int mods) { + touchPosition touch; + hidTouchRead(&touch); + + if (mods & KEY_TOUCH) { + Input_AddTouch(0, touch.px, touch.py); + } else if (hidKeysUp() & KEY_TOUCH) { + Input_RemoveTouch(0, Pointers[0].x, Pointers[0].y); + } +} + +void Window_ProcessEvents(float delta) { + hidScanInput(); + + if (!aptMainLoop()) { + Window_Main.Exists = false; + Window_RequestClose(); + return; + } + + u32 mods = hidKeysDown() | hidKeysHeld(); + ProcessTouchInput(mods); +} + +void Cursor_SetPosition(int x, int y) { } // Makes no sense for 3DS + +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } + +void Window_UpdateRawMouse(void) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +static void HandleButtons(u32 mods) { + Gamepad_SetButton(0, CCPAD_L, mods & KEY_L); + Gamepad_SetButton(0, CCPAD_R, mods & KEY_R); + + Gamepad_SetButton(0, CCPAD_A, mods & KEY_A); + Gamepad_SetButton(0, CCPAD_B, mods & KEY_B); + Gamepad_SetButton(0, CCPAD_X, mods & KEY_X); + Gamepad_SetButton(0, CCPAD_Y, mods & KEY_Y); + + Gamepad_SetButton(0, CCPAD_START, mods & KEY_START); + Gamepad_SetButton(0, CCPAD_SELECT, mods & KEY_SELECT); + + Gamepad_SetButton(0, CCPAD_LEFT, mods & KEY_DLEFT); + Gamepad_SetButton(0, CCPAD_RIGHT, mods & KEY_DRIGHT); + Gamepad_SetButton(0, CCPAD_UP, mods & KEY_DUP); + Gamepad_SetButton(0, CCPAD_DOWN, mods & KEY_DDOWN); + + Gamepad_SetButton(0, CCPAD_ZL, mods & KEY_ZL); + Gamepad_SetButton(0, CCPAD_ZR, mods & KEY_ZR); +} + +#define AXIS_SCALE 8.0f +static void ProcessCircleInput(int axis, circlePosition* pos, float delta) { + // May not be exactly 0 on actual hardware + if (Math_AbsI(pos->dx) <= 24) pos->dx = 0; + if (Math_AbsI(pos->dy) <= 24) pos->dy = 0; + + Gamepad_SetAxis(0, axis, pos->dx / AXIS_SCALE, -pos->dy / AXIS_SCALE, delta); +} + +void Window_ProcessGamepads(float delta) { + u32 mods = hidKeysDown() | hidKeysHeld(); + HandleButtons(mods); + + circlePosition hid_pos; + hidCircleRead(&hid_pos); + + if (irrst_result == 0) { + circlePosition stk_pos; + irrstScanInput(); + irrstCstickRead(&stk_pos); + + ProcessCircleInput(PAD_AXIS_RIGHT, &stk_pos, delta); + ProcessCircleInput(PAD_AXIS_LEFT, &hid_pos, delta); + } else { + ProcessCircleInput(PAD_AXIS_RIGHT, &hid_pos, 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) { + u16 width, height; + gfxScreen_t screen = launcherTop ? GFX_TOP : GFX_BOTTOM; + + gfxSetDoubleBuffering(screen, false); + u8* fb = gfxGetFramebuffer(screen, GFX_LEFT, &width, &height); + // SRC y = 0 to 240 + // SRC x = 0 to 400 + // DST X = 0 to 240 + // DST Y = 0 to 400 + + for (int y = r.y; y < r.y + r.height; y++) + for (int x = r.x; x < r.x + r.width; x++) + { + BitmapCol color = Bitmap_GetPixel(bmp, x, y); + int addr = (width - 1 - y + x * width) * 3; // TODO -1 or not + fb[addr+0] = BitmapCol_B(color); + fb[addr+1] = BitmapCol_G(color); + fb[addr+2] = BitmapCol_R(color); + } + // TODO gspWaitForVBlank(); + gfxFlushBuffers(); + //gfxSwapBuffers(); + // TODO: tearing?? + /* + gfxSetDoubleBuffering(GFX_TOP, false); + gfxScreenSwapBuffers(GFX_TOP, true); + gfxSetDoubleBuffering(GFX_TOP, true); + gfxScreenSwapBuffers(GFX_BOTTOM, true); + */ +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); +} + + +/*########################################################################################################################* +*------------------------------------------------------Soft keyboard------------------------------------------------------* +*#########################################################################################################################*/ +static void OnscreenTextChanged(const char* text) { + char tmpBuffer[NATIVE_STR_LEN]; + cc_string tmp = String_FromArray(tmpBuffer); + String_AppendUtf8(&tmp, text, String_Length(text)); + + Event_RaiseString(&InputEvents.TextChanged, &tmp); + Input_SetPressed(CCKEY_ENTER); + Input_SetReleased(CCKEY_ENTER); +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { + const char* btnText = args->type & KEYBOARD_FLAG_SEND ? "Send" : "Enter"; + char input[NATIVE_STR_LEN] = { 0 }; + char output[NATIVE_STR_LEN] = { 0 }; + SwkbdState swkbd; + String_EncodeUtf8(input, args->text); + + int mode = args->type & 0xFF; + int type = (mode == KEYBOARD_TYPE_INTEGER || mode == KEYBOARD_TYPE_NUMBER) ? SWKBD_TYPE_NUMPAD : SWKBD_TYPE_WESTERN; + + swkbdInit(&swkbd, type, 3, -1); + swkbdSetInitialText(&swkbd, input); + swkbdSetHintText(&swkbd, args->placeholder); + //swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false); + //swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, btnText, true); + swkbdSetButton(&swkbd, SWKBD_BUTTON_CONFIRM, btnText, true); + + if (mode == KEYBOARD_TYPE_INTEGER) { + swkbdSetNumpadKeys(&swkbd, '-', 0); + } else if (mode == KEYBOARD_TYPE_NUMBER) { + swkbdSetNumpadKeys(&swkbd, '-', '.'); + } + + if (mode == KEYBOARD_TYPE_PASSWORD) + swkbdSetPasswordMode(&swkbd, SWKBD_PASSWORD_HIDE_DELAY); + if (args->multiline) + swkbdSetFeatures(&swkbd, SWKBD_MULTILINE); + + // TODO filter callbacks and OnscreenKeyboard_SetText ?? + int btn = swkbdInputText(&swkbd, output, sizeof(output)); + if (btn != SWKBD_BUTTON_CONFIRM) return; + OnscreenTextChanged(output); +} +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { /* TODO implement */ } + + +/*########################################################################################################################* +*-------------------------------------------------------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 |