summary refs log tree commit diff
path: root/src/Window_PS3.c
diff options
context:
space:
mode:
authorWlodekM <[email protected]>2024-06-16 10:35:45 +0300
committerWlodekM <[email protected]>2024-06-16 10:35:45 +0300
commitabef6da56913f1c55528103e60a50451a39628b1 (patch)
treeb3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/Window_PS3.c
initial commit
Diffstat (limited to 'src/Window_PS3.c')
-rw-r--r--src/Window_PS3.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/src/Window_PS3.c b/src/Window_PS3.c
new file mode 100644
index 0000000..68d64e0
--- /dev/null
+++ b/src/Window_PS3.c
@@ -0,0 +1,394 @@
+#include "Core.h"
+#if defined CC_BUILD_PS3
+#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 "Logger.h"
+#include "VirtualKeyboard.h"
+#include <io/pad.h>
+#include <io/kb.h> 
+#include <sysutil/sysutil.h>
+#include <sysutil/video.h>
+
+static cc_bool launcherMode;
+static padInfo  pad_info;
+static padData  pad_data;
+static KbInfo   kb_info;
+static KbData   kb_data;
+static KbConfig kb_config;
+
+struct _DisplayData DisplayInfo;
+struct _WindowData WindowInfo;
+
+static void sysutil_callback(u64 status, u64 param, void* usrdata) {
+	switch (status) {
+		case SYSUTIL_EXIT_GAME:
+			Window_Main.Exists = false;
+			Window_RequestClose();
+			break;
+	}
+}
+
+void Window_PreInit(void) {
+	sysUtilRegisterCallback(0, sysutil_callback, NULL);
+}
+
+void Window_Init(void) {
+	videoState state;
+	videoResolution resolution;
+	
+	videoGetState(0, 0, &state);
+	videoGetResolution(state.displayMode.resolution, &resolution);
+      
+	DisplayInfo.Width  = resolution.width;
+	DisplayInfo.Height = resolution.height;
+	DisplayInfo.ScaleX = 1;
+	DisplayInfo.ScaleY = 1;
+	
+	Window_Main.Width   = resolution.width;
+	Window_Main.Height  = resolution.height;
+	Window_Main.Focused = true;
+	Window_Main.Exists  = true;
+
+	Input.Sources = INPUT_SOURCE_GAMEPAD;
+	DisplayInfo.ContentOffsetX = 20;
+	DisplayInfo.ContentOffsetY = 20;
+
+	ioPadInit(MAX_PORT_NUM);
+	ioKbInit(MAX_KB_PORT_NUM);
+	ioKbSetCodeType(0, KB_CODETYPE_RAW);
+	ioKbGetConfiguration(0, &kb_config);
+}
+
+void Window_Free(void) { }
+
+void Window_Create2D(int width, int height) { 
+	launcherMode = true;
+	Gfx_Create(); // launcher also uses RSX to draw
+}
+
+void Window_Create3D(int width, int height) { 
+	launcherMode = false; 
+}
+
+void Window_SetTitle(const cc_string* title) { }
+void Clipboard_GetText(cc_string* value) { } // TODO sceClipboardGetText
+void Clipboard_SetText(const cc_string* value) { } // TODO sceClipboardSetText
+
+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);
+}
+
+
+/*########################################################################################################################*
+*--------------------------------------------------Keyboard processing----------------------------------------------------*
+*#########################################################################################################################*/
+#define MAX_KEYCODE_MAPPINGS 148
+static char now_pressed[MAX_KEYCODE_MAPPINGS], was_pressed[MAX_KEYCODE_MAPPINGS];
+static int MapKey(int k) {
+	if (k >= KB_RAWKEY_A      && k <= KB_RAWKEY_Z)      return 'A'       + (k - KB_RAWKEY_A);
+	if (k >= KB_RAWKEY_1      && k <= KB_RAWKEY_9)      return '1'       + (k - KB_RAWKEY_1);
+	if (k >= KB_RAWKEY_F1     && k <= KB_RAWKEY_F12)    return CCKEY_F1  + (k - KB_RAWKEY_F1);
+	if (k >= KB_RAWKEY_KPAD_1 && k <= KB_RAWKEY_KPAD_9) return CCKEY_KP1 + (k - KB_RAWKEY_KPAD_1);
+	switch (k) {
+	case KB_RAWKEY_PRINTSCREEN: return CCKEY_PRINTSCREEN;
+	case KB_RAWKEY_SCROLL_LOCK: return CCKEY_SCROLLLOCK;
+	case KB_RAWKEY_PAUSE:       return CCKEY_PAUSE;
+	case KB_RAWKEY_INSERT:      return CCKEY_INSERT;
+	case KB_RAWKEY_HOME:        return CCKEY_HOME;
+	case KB_RAWKEY_PAGE_UP:     return CCKEY_PAGEUP;
+	case KB_RAWKEY_DELETE:      return CCKEY_DELETE;
+	case KB_RAWKEY_END:         return CCKEY_END;
+	case KB_RAWKEY_PAGE_DOWN:   return CCKEY_PAGEDOWN;
+	case KB_RAWKEY_RIGHT_ARROW: return CCKEY_RIGHT;
+	case KB_RAWKEY_LEFT_ARROW:  return CCKEY_LEFT;
+	case KB_RAWKEY_DOWN_ARROW:  return CCKEY_DOWN;
+	case KB_RAWKEY_UP_ARROW:    return CCKEY_UP;
+	case KB_RAWKEY_0:         return '0';
+	case KB_RAWKEY_ENTER:     return CCKEY_ENTER;
+	case KB_RAWKEY_ESCAPE:    return CCKEY_ESCAPE;
+	case KB_RAWKEY_BS:        return CCKEY_BACKSPACE;
+	case KB_RAWKEY_TAB:       return CCKEY_TAB;
+	case KB_RAWKEY_SPACE:     return CCKEY_SPACE;
+	case KB_RAWKEY_MINUS:     return CCKEY_MINUS;
+	case KB_RAWKEY_EQUAL_101: return CCKEY_EQUALS;
+	//case KB_RAWKEY_ACCENT_CIRCONFLEX_106: return CCKEY_TILDE;
+	//case KB_RAWKEY_LEFT_BRACKET_101:  return CCKEY_LBRACKET;
+	//case KB_RAWKEY_ATMARK_106
+	//case KB_RAWKEY_RIGHT_BRACKET_101: return CCKEY_RBRACKET;
+	case KB_RAWKEY_LEFT_BRACKET_106:  return CCKEY_LBRACKET;
+	case KB_RAWKEY_BACKSLASH_101:     return CCKEY_BACKSLASH;
+	case KB_RAWKEY_RIGHT_BRACKET_106: return CCKEY_RBRACKET;
+	case KB_RAWKEY_SEMICOLON:         return CCKEY_SEMICOLON;
+	case KB_RAWKEY_QUOTATION_101:     return CCKEY_QUOTE;
+	//case KB_RAWKEY_COLON_106:         return CCKEY_SEMICOLON;
+	case KB_RAWKEY_COMMA:             return CCKEY_COMMA;
+	case KB_RAWKEY_PERIOD:            return CCKEY_PERIOD;
+	case KB_RAWKEY_SLASH:             return CCKEY_SLASH;
+	case KB_RAWKEY_CAPS_LOCK:         return CCKEY_CAPSLOCK;
+	
+	case KB_RAWKEY_KPAD_NUMLOCK:  return CCKEY_NUMLOCK;
+	case KB_RAWKEY_KPAD_SLASH:    return CCKEY_KP_DIVIDE;
+	case KB_RAWKEY_KPAD_ASTERISK: return CCKEY_KP_MULTIPLY;
+	case KB_RAWKEY_KPAD_MINUS:    return CCKEY_KP_MINUS;
+	case KB_RAWKEY_KPAD_PLUS:     return CCKEY_KP_PLUS;
+	case KB_RAWKEY_KPAD_ENTER:    return CCKEY_KP_ENTER;
+	case KB_RAWKEY_KPAD_0:        return CCKEY_KP0;
+	case KB_RAWKEY_KPAD_PERIOD:   return CCKEY_KP_DECIMAL;
+	case KB_RAWKEY_BACKSLASH_106: return CCKEY_BACKSLASH;
+	
+	case 147: return CCKEY_TILDE;
+	}
+	return 0;
+}
+static cc_bool kb_deferredClear;
+static void ProcessKBButtons(void) {
+	// PS3 keyboard APIs only seem to return current keys pressed,
+	//  which is a massive pain to work with
+	// 
+	// The API is really strange and when pressing two keys produces e.g.
+	//   - Event 1) pressed 82
+	//   - Event 2) pressed 46
+	// instead of
+	//   - Event 1) pressed 82
+	//   - Event 2) pressed 82 46
+	// 
+	// Additionally on real hardware, the following events when observed
+	//   - Releasing key: [key] [0]
+	//   - Holding key: [key] [0] [key] [0] [key] [0]
+	// I don't really know why this happens, so try to detect this by
+	//  deferring resetting all keys to next Window_ProcessEvents
+	// TODO properly investigate this	
+	
+	if (kb_deferredClear && (kb_data.nb_keycode == 0 || kb_data.keycode[0] == 0)) {
+		Mem_Set(now_pressed, 0, sizeof(now_pressed));
+		kb_deferredClear = false;
+	} else {
+		kb_deferredClear = false;
+		if (!kb_data.nb_keycode) return;
+	}
+	
+	// possibly unpress all keys next time around
+	if (kb_data.keycode[0] == 0) kb_deferredClear = true;
+	
+	for (int i = 0; i < kb_data.nb_keycode; i++)
+	{
+		int rawcode = kb_data.keycode[i];
+		if (rawcode > 0 && rawcode < MAX_KEYCODE_MAPPINGS) 
+			now_pressed[rawcode] = true;
+	}
+	
+	for (int i = 0; i < MAX_KEYCODE_MAPPINGS; i++)
+	{
+		if (now_pressed[i] == was_pressed[i]) continue;
+		
+		int key = MapKey(i);
+		if (key) Input_SetNonRepeatable(key, now_pressed[i]);
+		//if (key) Platform_Log3("UPDATE %h: %c = %t", &i, Input_DisplayNames[key], &now_pressed[i]);
+	}
+	
+	Mem_Copy(was_pressed, now_pressed, sizeof(now_pressed));
+}
+
+static KbMkey old_mods;
+#define ToggleMod(field, btn) if (diff._KbMkeyU._KbMkeyS. field) Input_Set(btn, mods->_KbMkeyU._KbMkeyS. field);
+
+static void ProcessKBModifiers(KbMkey* mods) {
+	KbMkey diff;
+	diff._KbMkeyU.mkeys = mods->_KbMkeyU.mkeys ^ old_mods._KbMkeyU.mkeys;
+	
+	ToggleMod(l_alt,   CCKEY_LALT);
+	ToggleMod(r_alt,   CCKEY_RALT);
+	ToggleMod(l_ctrl,  CCKEY_LCTRL);
+	ToggleMod(r_ctrl,  CCKEY_RCTRL);
+	ToggleMod(l_shift, CCKEY_LSHIFT);
+	ToggleMod(r_shift, CCKEY_RSHIFT);
+	ToggleMod(l_win,   CCKEY_LWIN);
+	ToggleMod(r_win,   CCKEY_RWIN);
+	
+	old_mods = *mods;
+}
+
+static void ProcessKBTextInput(void) {
+	for (int i = 0; i < kb_data.nb_keycode; i++)
+	{
+		int rawcode = kb_data.keycode[i];
+		if (!rawcode) continue;
+		int unicode = ioKbCnvRawCode(kb_config.mapping, kb_data.mkey, kb_data.led, rawcode);
+		
+		if (unicode && unicode <= 0xFF) 
+			Event_RaiseInt(&InputEvents.Press, (cc_unichar)unicode);
+			
+		//char C = unicode;
+		//Platform_Log4("%i --> %i / %h / %r", &rawcode, &unicode, &unicode, &C);
+	}
+}
+
+static void ProcessKBInput(void) {
+	int res = ioKbRead(0, &kb_data);
+	Input.Sources |= INPUT_SOURCE_NORMAL;
+
+	if (res == 0 && kb_data.nb_keycode > 0) {
+		ProcessKBButtons();
+		ProcessKBModifiers(&kb_data.mkey);
+		ProcessKBTextInput();
+	}
+}
+
+
+/*########################################################################################################################*
+*----------------------------------------------------Input processing-----------------------------------------------------*
+*#########################################################################################################################*/
+void Window_ProcessEvents(float delta) {
+	ioKbGetInfo(&kb_info);
+	if (kb_info.status[0]) ProcessKBInput();
+}
+
+void Cursor_SetPosition(int x, int y) { } // Makes no sense for PS Vita
+
+void Window_EnableRawMouse(void)  { Input.RawMode = true; }
+void Window_UpdateRawMouse(void)  {  }
+void Window_DisableRawMouse(void) { Input.RawMode = false; }
+
+
+/*########################################################################################################################*
+*-------------------------------------------------------Gamepads----------------------------------------------------------*
+*#########################################################################################################################*/
+static void HandleButtons(int port, padData* data) {
+	//Platform_Log2("BUTTONS: %h (%h)", &data->button[2], &data->button[0]);
+	Gamepad_SetButton(port, CCPAD_A, data->BTN_TRIANGLE);
+	Gamepad_SetButton(port, CCPAD_B, data->BTN_SQUARE);
+	Gamepad_SetButton(port, CCPAD_X, data->BTN_CROSS);
+	Gamepad_SetButton(port, CCPAD_Y, data->BTN_CIRCLE);
+      
+	Gamepad_SetButton(port, CCPAD_START,  data->BTN_START);
+	Gamepad_SetButton(port, CCPAD_SELECT, data->BTN_SELECT);
+	Gamepad_SetButton(port, CCPAD_LSTICK, data->BTN_L3);
+	Gamepad_SetButton(port, CCPAD_RSTICK, data->BTN_R3);
+
+	Gamepad_SetButton(port, CCPAD_LEFT,   data->BTN_LEFT);
+	Gamepad_SetButton(port, CCPAD_RIGHT,  data->BTN_RIGHT);
+	Gamepad_SetButton(port, CCPAD_UP,     data->BTN_UP);
+	Gamepad_SetButton(port, CCPAD_DOWN,   data->BTN_DOWN);
+	
+	Gamepad_SetButton(port, CCPAD_L,  data->BTN_L1);
+	Gamepad_SetButton(port, CCPAD_R,  data->BTN_R1);
+	Gamepad_SetButton(port, CCPAD_ZL, data->BTN_L2);
+	Gamepad_SetButton(port, CCPAD_ZR, data->BTN_R2);
+}
+
+#define AXIS_SCALE 32.0f
+static void HandleJoystick(int port, int axis, int x, int y, float delta) {
+	if (Math_AbsI(x) <= 32) x = 0;
+	if (Math_AbsI(y) <= 32) y = 0;	
+	
+	Gamepad_SetAxis(port, axis, x / AXIS_SCALE, y / AXIS_SCALE, delta);
+}
+
+static void ProcessPadInput(int port, float delta, padData* pad) {
+	HandleButtons(port, pad);
+	HandleJoystick(port, PAD_AXIS_LEFT,  pad->ANA_L_H - 0x80, pad->ANA_L_V - 0x80, delta);
+	HandleJoystick(port, PAD_AXIS_RIGHT, pad->ANA_R_H - 0x80, pad->ANA_R_V - 0x80, delta);
+}
+
+void Window_ProcessGamepads(float delta) {
+	ioPadGetInfo(&pad_info);
+	for (int port = 0; port < INPUT_MAX_GAMEPADS; port++)
+	{
+		if (!pad_info.status[port]) continue;
+		
+		ioPadGetData(port, &pad_data);
+		ProcessPadInput(port, delta, &pad_data);
+	}
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------Framebuffer--------------------------------------------------------*
+*#########################################################################################################################*/
+static u32 fb_offset;
+
+extern u32* Gfx_AllocImage(u32* offset, s32 w, s32 h);
+extern void Gfx_TransferImage(u32 offset, s32 w, s32 h);
+
+void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) {
+	u32* pixels = Gfx_AllocImage(&fb_offset, width, height);
+	bmp->scan0  = pixels;
+	bmp->width  = width;
+	bmp->height = height;
+	
+	Gfx_ClearColor(PackedCol_Make(0x40, 0x60, 0x80, 0xFF));
+}
+
+void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
+	// TODO test
+	Gfx_BeginFrame();
+	Gfx_ClearBuffers(GFX_BUFFER_COLOR | GFX_BUFFER_DEPTH);
+	// TODO: Only transfer dirty region instead of the entire bitmap
+	Gfx_TransferImage(fb_offset, bmp->width, bmp->height);
+	Gfx_EndFrame();
+}
+
+void Window_FreeFramebuffer(struct Bitmap* bmp) {
+	//Mem_Free(bmp->scan0);
+	/* TODO free framebuffer */
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------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