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_Dreamcast.c |
initial commit
Diffstat (limited to 'src/Window_Dreamcast.c')
-rw-r--r-- | src/Window_Dreamcast.c | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/src/Window_Dreamcast.c b/src/Window_Dreamcast.c new file mode 100644 index 0000000..7502130 --- /dev/null +++ b/src/Window_Dreamcast.c @@ -0,0 +1,353 @@ +#include "Core.h" +#if defined CC_BUILD_DREAMCAST +#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 <kos.h> +static cc_bool launcherMode; +cc_bool window_inited; + +struct _DisplayData DisplayInfo; +struct _WindowData WindowInfo; + +void Window_PreInit(void) { + vid_set_mode(DEFAULT_VID_MODE, DEFAULT_PIXEL_MODE); + vid_flip(0); + + int cable = vid_check_cable(); + if (cable == CT_VGA) return; + + if (flashrom_get_region() == FLASHROM_REGION_EUROPE) { + Platform_LogConst("Forcing 50hz for PAL region"); + vid_set_mode(DM_640x480_PAL_IL, DEFAULT_PIXEL_MODE); + } +} + +void Window_Init(void) { + DisplayInfo.Width = vid_mode->width; + DisplayInfo.Height = vid_mode->height; + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; + + Window_Main.Width = vid_mode->width; + Window_Main.Height = vid_mode->height; + Window_Main.Focused = true; + Window_Main.Exists = true; + + Input.Sources = INPUT_SOURCE_GAMEPAD; + DisplayInfo.ContentOffsetX = 10; + DisplayInfo.ContentOffsetY = 20; + Window_Main.SoftKeyboard = SOFT_KEYBOARD_VIRTUAL; + + window_inited = true; +} + +void Window_Free(void) { } + +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-----------------------------------------------------* +*#########################################################################################################################*/ +// TODO: More intelligent diffing that uses less space +static cc_bool has_prevState; +static kbd_state_t prevState; + +static int MapKey(int k) { + if (k >= KBD_KEY_A && k <= KBD_KEY_Z) return 'A' + (k - KBD_KEY_A); + if (k >= KBD_KEY_0 && k <= KBD_KEY_9) return '0' + (k - KBD_KEY_0); + if (k >= KBD_KEY_F1 && k <= KBD_KEY_F12) return CCKEY_F1 + (k - KBD_KEY_F1); + // KBD_KEY_PAD_0 isn't before KBD_KEY_PAD_1 + if (k >= KBD_KEY_PAD_1 && k <= KBD_KEY_PAD_9) return CCKEY_KP1 + (k - KBD_KEY_PAD_1); + + switch (k) { + case KBD_KEY_ENTER: return CCKEY_ENTER; + case KBD_KEY_ESCAPE: return CCKEY_ESCAPE; + case KBD_KEY_BACKSPACE: return CCKEY_BACKSPACE; + case KBD_KEY_TAB: return CCKEY_TAB; + case KBD_KEY_SPACE: return CCKEY_SPACE; + case KBD_KEY_MINUS: return CCKEY_MINUS; + case KBD_KEY_PLUS: return CCKEY_EQUALS; + case KBD_KEY_LBRACKET: return CCKEY_LBRACKET; + case KBD_KEY_RBRACKET: return CCKEY_RBRACKET; + case KBD_KEY_BACKSLASH: return CCKEY_BACKSLASH; + case KBD_KEY_SEMICOLON: return CCKEY_SEMICOLON; + case KBD_KEY_QUOTE: return CCKEY_QUOTE; + case KBD_KEY_TILDE: return CCKEY_TILDE; + case KBD_KEY_COMMA: return CCKEY_COMMA; + case KBD_KEY_PERIOD: return CCKEY_PERIOD; + case KBD_KEY_SLASH: return CCKEY_SLASH; + case KBD_KEY_CAPSLOCK: return CCKEY_CAPSLOCK; + case KBD_KEY_PRINT: return CCKEY_PRINTSCREEN; + case KBD_KEY_SCRLOCK: return CCKEY_SCROLLLOCK; + case KBD_KEY_PAUSE: return CCKEY_PAUSE; + case KBD_KEY_INSERT: return CCKEY_INSERT; + case KBD_KEY_HOME: return CCKEY_HOME; + case KBD_KEY_PGUP: return CCKEY_PAGEUP; + case KBD_KEY_DEL: return CCKEY_DELETE; + case KBD_KEY_END: return CCKEY_END; + case KBD_KEY_PGDOWN: return CCKEY_PAGEDOWN; + case KBD_KEY_RIGHT: return CCKEY_RIGHT; + case KBD_KEY_LEFT: return CCKEY_LEFT; + case KBD_KEY_DOWN: return CCKEY_DOWN; + case KBD_KEY_UP: return CCKEY_UP; + + case KBD_KEY_PAD_NUMLOCK: return CCKEY_NUMLOCK; + case KBD_KEY_PAD_DIVIDE: return CCKEY_KP_DIVIDE; + case KBD_KEY_PAD_MULTIPLY: return CCKEY_KP_MULTIPLY; + case KBD_KEY_PAD_MINUS: return CCKEY_KP_MINUS; + case KBD_KEY_PAD_PLUS: return CCKEY_KP_PLUS; + case KBD_KEY_PAD_ENTER: return CCKEY_KP_ENTER; + case KBD_KEY_PAD_0: return CCKEY_KP0; + case KBD_KEY_PAD_PERIOD: return CCKEY_KP_DECIMAL; + } + return INPUT_NONE; +} +#define ToggleKey(diff, cur, mask, btn) if (diff & mask) Input_Set(btn, cur & mask) +static void UpdateKeyboardState(kbd_state_t* state) { + int cur_keys = state->shift_keys; + int diff_keys = prevState.shift_keys ^ state->shift_keys; + + if (diff_keys) { + ToggleKey(diff_keys, cur_keys, KBD_MOD_LALT, CCKEY_LALT); + ToggleKey(diff_keys, cur_keys, KBD_MOD_RALT, CCKEY_RALT); + ToggleKey(diff_keys, cur_keys, KBD_MOD_LCTRL, CCKEY_LCTRL); + ToggleKey(diff_keys, cur_keys, KBD_MOD_RCTRL, CCKEY_RCTRL); + ToggleKey(diff_keys, cur_keys, KBD_MOD_LSHIFT, CCKEY_LSHIFT); + ToggleKey(diff_keys, cur_keys, KBD_MOD_RSHIFT, CCKEY_RSHIFT); + } + + // see keyboard.h, KEY_S3 seems to be highest used key + for (int i = KBD_KEY_A; i < KBD_KEY_S3; i++) + { + if (state->matrix[i] == prevState.matrix[i]) continue; + int btn = MapKey(i); + if (btn) Input_Set(btn, state->matrix[i]); + } +} + +static void ProcessKeyboardInput(void) { + maple_device_t* kb_dev; + kbd_state_t* state; + + kb_dev = maple_enum_type(0, MAPLE_FUNC_KEYBOARD); + if (!kb_dev) return; + state = (kbd_state_t*)maple_dev_status(kb_dev); + if (!state) return; + + if (has_prevState) UpdateKeyboardState(state); + has_prevState = true; + prevState = *state; + + Input.Sources |= INPUT_SOURCE_NORMAL; + int ret = kbd_queue_pop(kb_dev, 1); + if (ret < 0) return; + + // Ascii printable characters + // NOTE: Escape, Enter etc map to ASCII control characters + if (ret >= ' ' && ret <= 0x7F) + Event_RaiseInt(&InputEvents.Press, ret); +} + + +/*########################################################################################################################* +*----------------------------------------------------Input processing-----------------------------------------------------* +*#########################################################################################################################*/ +static void ProcessMouseInput(float delta) { + maple_device_t* mouse; + mouse_state_t* state; + + mouse = maple_enum_type(0, MAPLE_FUNC_MOUSE); + if (!mouse) return; + state = (mouse_state_t*)maple_dev_status(mouse); + if (!state) return; + + int mods = state->buttons; + Input_SetNonRepeatable(CCMOUSE_L, mods & MOUSE_LEFTBUTTON); + Input_SetNonRepeatable(CCMOUSE_R, mods & MOUSE_RIGHTBUTTON); + Input_SetNonRepeatable(CCMOUSE_M, mods & MOUSE_SIDEBUTTON); + + if (!Input.RawMode) return; + float scale = (delta * 60.0) / 2.0f; + Event_RaiseRawMove(&PointerEvents.RawMoved, + state->dx * scale, state->dy * scale); +} + +void Window_ProcessEvents(float delta) { + ProcessKeyboardInput(); + ProcessMouseInput(delta); +} + +void Cursor_SetPosition(int x, int y) { } /* TODO: Dreamcast mouse support */ + +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } +void Window_UpdateRawMouse(void) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +static void HandleButtons(int port, int mods) { + Gamepad_SetButton(port, CCPAD_A, mods & CONT_A); + Gamepad_SetButton(port, CCPAD_B, mods & CONT_B); + Gamepad_SetButton(port, CCPAD_X, mods & CONT_X); + Gamepad_SetButton(port, CCPAD_Y, mods & CONT_Y); + + Gamepad_SetButton(port, CCPAD_START, mods & CONT_START); + Gamepad_SetButton(port, CCPAD_SELECT, mods & CONT_D); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & CONT_DPAD_LEFT); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & CONT_DPAD_RIGHT); + Gamepad_SetButton(port, CCPAD_UP, mods & CONT_DPAD_UP); + Gamepad_SetButton(port, CCPAD_DOWN, mods & CONT_DPAD_DOWN); + + // Buttons not on standard controller + Gamepad_SetButton(port, CCPAD_C, mods & CONT_C); + Gamepad_SetButton(port, CCPAD_D, mods & CONT_D); + Gamepad_SetButton(port, CCPAD_Z, mods & CONT_Z); + Gamepad_SetButton(port, CCPAD_CLEFT, mods & CONT_DPAD2_LEFT); + Gamepad_SetButton(port, CCPAD_CRIGHT, mods & CONT_DPAD2_RIGHT); + Gamepad_SetButton(port, CCPAD_CUP, mods & CONT_DPAD2_UP); + Gamepad_SetButton(port, CCPAD_CDOWN, mods & CONT_DPAD2_DOWN); +} + +#define AXIS_SCALE 8.0f +static void HandleJoystick(int port, int axis, int x, int y, float delta) { + if (Math_AbsI(x) <= 8) x = 0; + if (Math_AbsI(y) <= 8) y = 0; + + Gamepad_SetAxis(port, axis, x / AXIS_SCALE, y / AXIS_SCALE, delta); +} + +static void HandleController(int port, cont_state_t* state, float delta) { + Gamepad_SetButton(port, CCPAD_L, state->ltrig > 10); + Gamepad_SetButton(port, CCPAD_R, state->rtrig > 10); + // TODO second joystick + // TODO: verify values are right + HandleJoystick(port, PAD_AXIS_RIGHT, state->joyx, state->joyy, delta); +} + +void Window_ProcessGamepads(float delta) { + maple_device_t* cont; + cont_state_t* state; + + for (int port = 0; port < INPUT_MAX_GAMEPADS; port++) + { + cont = maple_enum_type(port, MAPLE_FUNC_CONTROLLER); + if (!cont) return; + state = (cont_state_t*)maple_dev_status(cont); + if (!state) return; + + HandleButtons(port, state->buttons); + HandleController(port, state, 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) { + // TODO: double buffering ?? + // https://dcemulation.org/phpBB/viewtopic.php?t=99999 + // https://dcemulation.org/phpBB/viewtopic.php?t=43214 + vid_waitvbl(); + + for (int y = r.y; y < r.y + r.height; y++) + { + BitmapCol* src = Bitmap_GetRow(bmp, y); + uint16_t* dst = vram_s + vid_mode->width * y; + + for (int x = r.x; x < r.x + r.width; x++) + { + BitmapCol color = src[x]; + // 888 to 565 (discard least significant bits) + dst[x] = ((BitmapCol_R(color) & 0xF8) << 8) | ((BitmapCol_G(color) & 0xFC) << 3) | (BitmapCol_B(color) >> 3); + } + } +} + +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 |