[PSP] libctrl

Create a single thread for each patch to be added to the repository. Please try to stay on topic.
Post Reply
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

[PSP] libctrl

Post by lego »

Hi.

This is a wrapper library for the pspctrl one. May be it will be useful.

Code: Select all

diff -ru -N -x '.git*' tmp/libctrl.c libctrl/libctrl.c
--- tmp/libctrl.c       1970-01-01 03:00:00.000000000 +0300
+++ libctrl/libctrl.c   2009-10-02 22:54:43.000000000 +0400
@@ -0,0 +1,594 @@
+/*
+ *  libctrl - A wrapper for the pspctrl lib
+ *  Version 1.0.1
+ *  Copyright (C) 2009 Lego_12239 aka Oleg Nemanov
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <time.h>
+#include <stdlib.h>
+#include <pspkernel.h>
+#include <pspdebug.h>
+#include <pspctrl.h>
+#include <pspdisplay.h>
+#include <psprtc.h>
+#include "libctrl.h"
+
+
+#define printf pspDebugScreenPrintf
+
+
+#define CTRL_KEY_COUNT 10
+
+static ctrl_key_t ctrl_key&#91;CTRL_KEY_COUNT&#93;;
+static ctrl_jstick_t ctrl_jstick;
+
+/* For an efficient memory allocation time usage this variable is global.*/
+static pspTime ctrl_key_time;
+
+static int ctrl_events_queue_len = 16;
+static ctrl_event_t *ctrl_events_queue;
+/* Pointers to the last event and the first event in the events queue. */
+static ctrl_event_t *ctrl_events_queue_le, *ctrl_events_queue_fe;
+static SceUID ctrl_key_event_mutex;
+
+
+/*
+ * Lock a mutex.
+ * Return 0 if error or 1 otherwise.
+ */
+inline static int lock_mutex&#40;SceUID mutex&#41;
+&#123;
+  if &#40; sceKernelWaitSema&#40;mutex, 1, 0&#41; < 0 &#41;
+    return 0;
+  else
+    return 1;
+&#125;
+
+/*
+ * Unlock a mutex.
+ * Return 0 if error or 1 otherwise.
+ */
+inline static int unlock_mutex&#40;SceUID mutex&#41;
+&#123;
+  if &#40; sceKernelSignalSema&#40;mutex, 1&#41; < 0 &#41;
+    return 0;
+  else
+    return 1;
+&#125;
+
+/*
+ * Create the events queue. 
+ * Return 0 if error or 1 otherwise.
+ */
+static int create_events_queue&#40;void&#41;
+&#123;
+  int i;
+
+
+  ctrl_events_queue = &#40;ctrl_event_t*&#41;malloc&#40;ctrl_events_queue_len * 
+                                           sizeof&#40;ctrl_event_t&#41;&#41;;
+  if &#40; !ctrl_events_queue &#41;
+    return 0;
+
+  ctrl_events_queue_fe = ctrl_events_queue_le = ctrl_events_queue;
+
+  for&#40;i = 0; i < ctrl_events_queue_len; i++&#41; &#123;
+    ctrl_events_queue&#91;i&#93;.event = EMPTY;
+  &#125;
+
+  return 1;
+&#125;
+
+/*
+ * Change an events queue length.
+ * All events existing in the queue are deleted.
+ * A smaller events queue give a smaller latency.
+ * Return 0 if an error has occured during the create_events_queue&#40;&#41;
+ * call &#40;Not enough memory for a queue&#41; or the lock_mutex&#40;&#41; call or
+ * unlock_mutex&#40;&#41;.
+ */
+int ctrl_set_eq_len&#40;size_t len&#41;
+&#123;
+  int ret;
+
+
+  if &#40; ! lock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+
+  /* Delete old events queue. */
+  free&#40;ctrl_events_queue&#41;;
+
+  /* Create new events queue. */
+  /* Cann't create a zero-length queue. */
+  if &#40; ! len &#41; len++;
+  ctrl_events_queue_len = len;
+  ret = create_events_queue&#40;&#41;;
+
+  if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+
+  return ret;
+&#125;
+
+/*
+ * Clear an all events.
+ * Return 0 if a mutex error occured or 1 otherwise.
+ */
+int ctrl_clear_events&#40;void&#41;
+&#123;
+  int i;
+
+  if &#40; ! lock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+
+  for&#40;i = 0; i < ctrl_events_queue_len; i++&#41; &#123;
+    ctrl_events_queue&#91;i&#93;.event = EMPTY;
+  &#125;
+
+  ctrl_events_queue_fe = ctrl_events_queue_le = ctrl_events_queue;
+
+  if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+
+  return 1;
+&#125;
+
+/*
+ * Set key mode.
+ */
+void ctrl_set_key_mode&#40;ctrl_key_code_t key_code, ctrl_mode_t mode&#41;
+&#123;
+  if &#40;&#40; key_code < 0 &#41; || &#40; key_code > CTRL_KEY_CODE_MAX &#41;&#41; return;
+
+  ctrl_key&#91;key_code&#93;.mode = mode;
+&#125;
+
+/*
+ * Get a key mode.
+ */
+ctrl_mode_t ctrl_get_key_mode&#40;ctrl_key_code_t key_code&#41;
+&#123;
+  if &#40;&#40; key_code < 0 &#41; || &#40; key_code > CTRL_KEY_CODE_MAX &#41;&#41; return -1;
+
+  return ctrl_key&#91;key_code&#93;.mode;
+&#125;
+
+/*
+ * Set key repeat start time.
+ * rep_start_time is a time in seconds since key is pressed when
+ * repeating start.
+ */
+void ctrl_set_key_repstart&#40;ctrl_key_code_t key_code, 
+                         unsigned int rep_start_time&#41;
+&#123;
+  if &#40;&#40; key_code < 0 &#41; || &#40; key_code > CTRL_KEY_CODE_MAX &#41;&#41; return;
+
+  ctrl_key&#91;key_code&#93;.repeat_start = rep_start_time;
+&#125;
+
+/*
+ * Set key repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen PRESSED events 
+ * while key is pressed.
+ */
+void ctrl_set_key_repinterval&#40;ctrl_key_code_t key_code,
+                            unsigned int rep_interval&#41;
+&#123;
+  if &#40;&#40; key_code < 0 &#41; || &#40; key_code > CTRL_KEY_CODE_MAX &#41;&#41; return;
+
+  ctrl_key&#91;key_code&#93;.repeat_interval = rep_interval;
+&#125;
+
+/*
+ * Set joystick axes zero ranges.
+ * If an axis changes within this range, it interpretes like the zero value.
+ */
+void ctrl_set_jstick_zerorange&#40;unsigned char x_zero_range,
+                              unsigned char y_zero_range&#41;
+&#123;
+  ctrl_jstick.axis_x.zero_range = x_zero_range;
+  ctrl_jstick.axis_y.zero_range = y_zero_range;
+&#125;
+
+/*
+ * Get values of axes zero ranges.
+ */
+void ctrl_get_jstick_zerorange&#40;unsigned char *x_zero_range,
+                              unsigned char *y_zero_range&#41;
+&#123;
+  *x_zero_range = ctrl_jstick.axis_x.zero_range;
+  *y_zero_range = ctrl_jstick.axis_y.zero_range;
+&#125;
+
+/*
+ * Set joystick axes coordinates step.
+ * For example, if x_coord_step is 1, than x axis can be from -128 to 127;
+ * if x_coord_step is 10, than x axis can be from -12 to 12.
+ */
+void ctrl_set_jstick_coordstep&#40;unsigned char x_coord_step,
+                              unsigned char y_coord_step&#41;
+&#123;
+  if &#40; !x_coord_step &#41; x_coord_step++;
+  if &#40; !y_coord_step &#41; y_coord_step++;
+
+  ctrl_jstick.axis_x.coord_step = x_coord_step;
+  ctrl_jstick.axis_y.coord_step = y_coord_step;
+&#125;
+
+/*
+ * Get joystick axes coordinates step.
+ */
+void ctrl_get_jstick_coordstep&#40;unsigned char *x_coord_step,
+                              unsigned char *y_coord_step&#41;
+&#123;
+  *x_coord_step = ctrl_jstick.axis_x.coord_step;
+  *y_coord_step = ctrl_jstick.axis_y.coord_step;
+&#125;
+
+/*
+ * Return a count of coordinates taking into account a current coord_step.
+ */
+void ctrl_get_jstick_coordcount&#40;unsigned char *x_count, unsigned char *y_count&#41;
+&#123;
+  *x_count = 128 / ctrl_jstick.axis_x.coord_step;
+  *y_count = 128 / ctrl_jstick.axis_y.coord_step;
+&#125;
+
+/*
+ * Set joystick mode.
+ */
+void ctrl_set_jstick_mode&#40;ctrl_mode_t mode&#41;
+&#123;
+  ctrl_jstick.mode = mode;
+&#125;
+
+/*
+ * Set joystick repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen JOYSTICK events 
+ * while key is pressed.
+ */
+void ctrl_set_jstick_repinterval&#40;unsigned int rep_interval&#41;
+&#123;
+  ctrl_jstick.repeat_interval = rep_interval;
+&#125;
+
+/*
+ * Push an event into the queue.
+ * Return 0 if a mutex error occured or 1 otherwise.
+ */
+static int ctrl_events_queue_pushe&#40;ctrl_event_type_t event, unsigned int key,
+                                   char axis_x, char axis_y&#41;
+&#123;
+  ctrl_event_t *tmp = ctrl_events_queue_le;
+
+
+  if &#40; ! lock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+
+  if &#40; ctrl_events_queue_le->event != EMPTY &#41; &#123;
+    if &#40; tmp == &ctrl_events_queue&#91;ctrl_events_queue_len - 1&#93; &#41;
+      tmp = ctrl_events_queue;
+    else
+      tmp = ctrl_events_queue_le + 1;
+
+    if &#40; tmp == ctrl_events_queue_fe &#41; &#123;
+      if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+      return 1;
+    &#125;
+    ctrl_events_queue_le = tmp;
+  &#125;
+
+  ctrl_events_queue_le->event = event;
+  ctrl_events_queue_le->key = key;
+  ctrl_events_queue_le->jstick_x = axis_x;
+  ctrl_events_queue_le->jstick_y = axis_y;
+
+  if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return 0;
+
+  return 1;
+&#125;
+
+/*
+ * Return 1 if some event is poped.
+ * Return 0 if there is no event to pop.
+ * Return -1 if a mutex error occured.
+ */
+static int ctrl_events_queue_pope&#40;ctrl_event_t *const event&#41;
+&#123;
+  if &#40; ! lock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return -1;
+
+  if &#40; ctrl_events_queue_fe->event == EMPTY &#41; &#123;
+    event->event = EMPTY;
+    if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return -1;
+    return 0;
+  &#125;
+
+  event->event = ctrl_events_queue_fe->event;
+  event->key = ctrl_events_queue_fe->key;
+  event->jstick_x = ctrl_events_queue_fe->jstick_x;
+  event->jstick_y = ctrl_events_queue_fe->jstick_y;
+  ctrl_events_queue_fe->event = EMPTY;
+
+  if &#40; ctrl_events_queue_fe == ctrl_events_queue_le &#41; &#123;
+    if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return -1;
+    return 1;
+  &#125;
+  
+  if &#40; ctrl_events_queue_fe == &ctrl_events_queue&#91;ctrl_events_queue_len - 1&#93; &#41;
+    ctrl_events_queue_fe = ctrl_events_queue;
+  else
+    ctrl_events_queue_fe++;
+
+  if &#40; ! unlock_mutex&#40;ctrl_key_event_mutex&#41; &#41; return -1;
+  return 1;
+&#125;
+
+/*
+ * Nonblocking function.
+ * It check if any button is pressed.
+ * If any button is pressed return 1 and fill the key structure with 
+ * apropriate values or return 0 otherwise.
+ * Return -1 if a mutex error occured.
+ */
+inline int ctrl_pollevent&#40;ctrl_event_t *const event&#41;
+&#123;
+  return ctrl_events_queue_pope&#40;event&#41;;
+&#125;
+
+/*
+ * Blocking function.
+ * It wait button event and return a pointer to ctrl_key_t structure,
+ * after a key is pressed.
+ * Return -1 if a mutex error occured.
+ */
+int ctrl_waitevent&#40;ctrl_event_t *const event&#41;
+&#123;
+  int caught;
+
+  do &#123;
+    caught = ctrl_events_queue_pope&#40;event&#41;;
+    sceDisplayWaitVblankStart&#40;&#41;;
+  &#125; while &#40;!caught&#41;;
+
+  return caught;
+&#125;
+
+/*
+ * Return 1 if pressed, 2 if released, 0 otherwise.
+ * Return -1 if a mutex error occured.
+ */
+static int process_but&#40;unsigned int key_code, unsigned int is_pressed&#41;
+&#123;
+  ctrl_key_t * key = &ctrl_key&#91;key_code&#93;;
+  time_t t;
+  unsigned int decisec;
+
+  if &#40; &#40; !is_pressed &#41; && &#40; !key->press_time &#41; &#41; return 0;
+
+  if &#40; is_pressed &#41; &#123;
+    if &#40; !key->press_time &#41; &#123;
+      key->press_time = time&#40;NULL&#41;;
+      key->last_repeat = 0;
+
+      if &#40; ! ctrl_events_queue_pushe&#40;PRESSED, key_code, 0, 0&#41; &#41; return -1;
+
+      return 1;
+    &#125; else &#123;
+      t = time&#40;NULL&#41;;
+      sceRtcGetCurrentClockLocalTime&#40;&ctrl_key_time&#41;;
+      decisec = &#40;t - key->press_time&#41;*10 + 
+       ctrl_key_time.microseconds/100000;
+
+      if &#40; &#40; key->mode == REPEAT &#41; &&
+          &#40; t - key->press_time >= key->repeat_start &#41; &&
+          &#40; decisec - key->last_repeat >= key->repeat_interval&#41; &#41; &#123;
+       if &#40; ! ctrl_events_queue_pushe&#40;PRESSED, key_code, 0, 0&#41; &#41; return -1;
+       key->last_repeat = decisec;
+      &#125;
+
+      return 0;
+    &#125;
+  &#125; else &#123;
+    key->press_time = 0;
+  &#125;
+
+
+  if &#40; ! ctrl_events_queue_pushe&#40;RELEASED, key_code, 0, 0&#41; &#41; return -1;
+
+  return 2;
+&#125;
+
+/*
+ * Return 1 if everything is ok.
+ * Return 0 if a mutex error occured.
+ */
+static int process_jstick&#40;unsigned char Lx, unsigned char Ly&#41;
+&#123;
+  char x, y;
+  /* x and y zero half range. */
+  char x_zhr = ctrl_jstick.axis_x.zero_range / 2;
+  char y_zhr = ctrl_jstick.axis_y.zero_range / 2;
+  time_t t;
+  unsigned int decisec_delta;
+
+
+  /* Process the x axis. */
+  x = Lx - 128;
+  /* 
+   * If Lx isn't in the zero range, calculate x.
+   * Otherwise, set x to zero.
+   */
+  if &#40; x < -x_zhr &#41;
+    x = &#40;x + x_zhr&#41; / ctrl_jstick.axis_x.coord_step - 1;
+  else if &#40; x > x_zhr &#41;
+    x = &#40;x - x_zhr&#41; / ctrl_jstick.axis_x.coord_step + 1;
+  else
+    x = 0;
+
+  /* Process the y axis. */
+  y = Ly - 128;
+  /* 
+   * If Ly isn't in the zero range, calculate y.
+   * Otherwise, set y to zero.
+   */
+  if &#40; y < -y_zhr &#41;
+    y = &#40;y + y_zhr&#41; / ctrl_jstick.axis_y.coord_step - 1;
+  else if &#40; y > y_zhr &#41;
+    y = &#40;y - y_zhr&#41; / ctrl_jstick.axis_y.coord_step + 1;
+  else
+    y = 0;
+
+
+  /* Make a decision. */
+  /* If nothing has been changed - exit. */
+  if &#40;&#40; x == ctrl_jstick.axis_x.coord &#41; && &#40; y == ctrl_jstick.axis_y.coord &#41;&#41; &#123;
+    if &#40; ctrl_jstick.mode == REPEAT &#41; &#123;
+      t = time&#40;NULL&#41;;
+      sceRtcGetCurrentClockLocalTime&#40;&ctrl_key_time&#41;;
+      decisec_delta = &#40;t - ctrl_jstick.changed_time&#41;*10 + 
+       ctrl_key_time.microseconds/100000 - ctrl_jstick.last_repeat;
+
+      if &#40; decisec_delta < ctrl_jstick.repeat_interval &#41;
+       return 1;
+
+      ctrl_jstick.last_repeat += decisec_delta;
+    &#125; else
+      return 1;
+  &#125; else
+    if &#40; ctrl_jstick.mode == REPEAT &#41; &#123;
+      ctrl_jstick.changed_time = time&#40;NULL&#41;;
+      ctrl_jstick.last_repeat = 0;
+    &#125;
+
+
+  /* Else - place event in the events queue. */
+  if &#40; ! ctrl_events_queue_pushe&#40;JOYSTICK, 0, x, y&#41; &#41; return 0;
+
+  ctrl_jstick.axis_x.coord = x;
+  ctrl_jstick.axis_y.coord = y;
+
+  return 1;
+&#125;
+
+/*
+ * Return 1 if everything is ok.
+ * Return 0 if error.
+ */
+static int init_events_queue&#40;void&#41;
+&#123;
+  ctrl_key_event_mutex = sceKernelCreateSema&#40;"event_mutex", 0, 1, 1, NULL&#41;;
+
+  return create_events_queue&#40;&#41;;
+&#125;
+
+static void init_keys_array&#40;void&#41;
+&#123;
+  int i;
+
+
+  for&#40;i = 0; i < CTRL_KEY_COUNT; i++&#41; &#123;
+    ctrl_key&#91;i&#93;.repeat_start = 1;
+    ctrl_key&#91;i&#93;.repeat_interval = 4;
+  &#125;
+
+  ctrl_key&#91;PSP_CTRL_UP_KEY&#93;.button       = PSP_CTRL_UP;
+  ctrl_key&#91;PSP_CTRL_RIGHT_KEY&#93;.button    = PSP_CTRL_RIGHT;
+  ctrl_key&#91;PSP_CTRL_DOWN_KEY&#93;.button     = PSP_CTRL_DOWN;
+  ctrl_key&#91;PSP_CTRL_LEFT_KEY&#93;.button     = PSP_CTRL_LEFT;
+  ctrl_key&#91;PSP_CTRL_LTRIGGER_KEY&#93;.button = PSP_CTRL_LTRIGGER;
+  ctrl_key&#91;PSP_CTRL_RTRIGGER_KEY&#93;.button = PSP_CTRL_RTRIGGER;
+  ctrl_key&#91;PSP_CTRL_TRIANGLE_KEY&#93;.button = PSP_CTRL_TRIANGLE;
+  ctrl_key&#91;PSP_CTRL_CIRCLE_KEY&#93;.button   = PSP_CTRL_CIRCLE;
+  ctrl_key&#91;PSP_CTRL_CROSS_KEY&#93;.button    = PSP_CTRL_CROSS;
+  ctrl_key&#91;PSP_CTRL_SQUARE_KEY&#93;.button   = PSP_CTRL_SQUARE;
+&#125;
+
+static void init_jstick&#40;void&#41;
+&#123;
+  sceCtrlSetSamplingMode&#40;1&#41;;
+
+  ctrl_jstick.axis_x.coord = 0;
+  ctrl_jstick.axis_x.zero_range = 40;
+  ctrl_jstick.axis_x.coord_step = 10;
+  ctrl_jstick.axis_y.coord = 0;
+  ctrl_jstick.axis_y.zero_range = 40;
+  ctrl_jstick.axis_y.coord_step = 10;
+  ctrl_jstick.mode = NO_REPEAT;
+  ctrl_jstick.changed_time = 0;
+  ctrl_jstick.last_repeat = 0;
+  ctrl_jstick.repeat_interval = 4;
+&#125;
+
+int ctrl_thread&#40;SceSize args, void *argp&#41;
+&#123;
+  SceCtrlData *pad;
+  int i;
+  
+  if &#40; !&#40;pad = &#40;SceCtrlData*&#41;malloc&#40;sizeof&#40;SceCtrlData&#41;&#41;&#41; &#41;
+    sceKernelExitThread&#40;1&#41;;
+
+  /* Initialize the events queue. */
+  init_events_queue&#40;&#41;;
+
+  /* Initialize the ctrl_key array. */
+  init_keys_array&#40;&#41;;
+
+  /* Initialize the joystick related things. */
+  init_jstick&#40;&#41;;
+
+  /* Do a work. */
+  while &#40;1&#41; &#123;
+    sceDisplayWaitVblankStart&#40;&#41;;
+
+    sceCtrlReadBufferPositive&#40;pad, 1&#41;;
+
+    for&#40;i = 0; i < CTRL_KEY_COUNT; i++&#41; &#123;
+      process_but&#40;i, pad->Buttons & ctrl_key&#91;i&#93;.button&#41;;
+    &#125;
+    process_jstick&#40;pad->Lx, pad->Ly&#41;;
+  &#125;
+
+  free&#40;pad&#41;;
+
+  return 0;
+&#125;
+
+/*
+ * Init a ctrl thread. Must be called before calling any of the ctrl 
+ * functions.
+ * Return an error code or 0 if evething is ok. 
+ * ctrl thread id is returned through *thid. If an error occured 
+ * *thid is undefined.
+ */
+int init_ctrl_thread&#40;SceUID *thid&#41;
+&#123;
+  SceUID ctrl_thid;
+
+
+  ctrl_thid = sceKernelCreateThread&#40;"ctrl_thread", ctrl_thread, 0x10, 16384,
+                                 0, NULL&#41;;
+  if &#40; ctrl_thid < 0 &#41;
+    return ctrl_thid;
+
+  sceKernelStartThread&#40;ctrl_thid, 0, NULL&#41;;
+  /* Give ctrl_thread&#40;&#41; a time to initialize needed variables. */
+  sceKernelDelayThread&#40;10000&#41;;
+
+  /* If ctrl_thread&#40;&#41; do sceKernelExitThread&#40;&#41; return the error code 1. */
+  if &#40; sceKernelGetThreadExitStatus&#40;ctrl_thid&#41; != 0x800201a4 &#41;
+    return 1;
+
+  *thid = ctrl_thid;
+
+  return 0;
+&#125;
diff -ru -N -x '.git*' tmp/libctrl.h libctrl/libctrl.h
--- tmp/libctrl.h       1970-01-01 03&#58;00&#58;00.000000000 +0300
+++ libctrl/libctrl.h   2009-10-02 22&#58;54&#58;40.000000000 +0400
@@ -0,0 +1,212 @@
+/*
+ *  libctrl - A wrapper for the pspctrl lib
+ *  Version 1.0.1
+ *  Copyright &#40;C&#41; 2009 Lego_12239 aka Oleg Nemanov
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or &#40;at your option&#41; any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __LIBCTRL_H_
+#define __LIBCTRL_H_
+
+
+#define CTRL_KEY_CODE_MAX 9
+
+/* Key to array index mappings. */
+typedef enum ctrl_key_code_t &#123;
+  PSP_CTRL_UP_KEY = 0,
+  PSP_CTRL_RIGHT_KEY = 1,
+  PSP_CTRL_DOWN_KEY = 2,
+  PSP_CTRL_LEFT_KEY = 3,
+  PSP_CTRL_LTRIGGER_KEY = 4,
+  PSP_CTRL_RTRIGGER_KEY = 5,
+  PSP_CTRL_TRIANGLE_KEY = 6,
+  PSP_CTRL_CIRCLE_KEY = 7,
+  PSP_CTRL_CROSS_KEY = 8,
+  PSP_CTRL_SQUARE_KEY = CTRL_KEY_CODE_MAX
+&#125; ctrl_key_code_t;
+
+typedef enum ctrl_event_type_t &#123;
+    EMPTY,
+    PRESSED,
+    RELEASED,
+    JOYSTICK
+&#125; ctrl_event_type_t;
+
+typedef struct ctrl_event_t &#123;
+  /* Key codes. Like a PSP_CTRL_UP_KEY. */
+  ctrl_key_code_t key;
+  char jstick_x;
+  char jstick_y;
+  ctrl_event_type_t event;
+&#125; ctrl_event_t;
+
+typedef enum ctrl_mode_t &#123;
+  NO_REPEAT,
+  REPEAT
+&#125; ctrl_mode_t;
+
+typedef struct ctrl_key_t &#123;
+  /* PSP button codes. Like a PSP_CTRL_UP. */
+  unsigned int button;
+  /* Last press time. Must be 0 when initialized.*/
+  time_t press_time;
+  /* Last repeat time in deciseconds since press_time. */
+  unsigned int last_repeat;
+  /* Repeat start time in seconds since press_time. Default&#58; 1.*/
+  unsigned int repeat_start;
+  /* Repeat interval in deciseconds. Default&#58; 4. */
+  unsigned int repeat_interval;
+  /* Repeat or no repeat. */
+  ctrl_mode_t mode;
+  SceUID mutex;
+&#125; ctrl_key_t;
+
+typedef struct ctrl_jstick_axis_t &#123;
+  /* Axis value. */
+  char coord;
+  /* Zero range value. Default&#58; 40.*/
+  unsigned char zero_range;
+  /* Axis values step. Default&#58; 10.*/
+  unsigned char coord_step;
+&#125; ctrl_jstick_axis_t;
+
+typedef struct ctrl_jstick_t &#123;
+  /* Axes. */
+  ctrl_jstick_axis_t axis_x;
+  ctrl_jstick_axis_t axis_y;
+  /* Last change time. Must be 0 when initialized.*/
+  time_t changed_time;
+  /* Last repeat time in deciseconds since press_time. */
+  unsigned int last_repeat;
+  /* Repeat interval in deciseconds. Default&#58; 4. */
+  unsigned int repeat_interval;
+  /* Repeat or no repeat. */
+  ctrl_mode_t mode;
+&#125; ctrl_jstick_t;
+
+
+/*
+ * Change an events queue length by a queue recreating.
+ * All events existing in the queue and queue by itself are deleted.
+ * A smaller events queue give a smaller latency.
+ * Return 0 if an error has occured &#40;May be not enough memory for 
+ * a new queue or a mutex error occured&#41;. By default the queue len is 16.
+ */
+int ctrl_set_eq_len&#40;size_t len&#41;;
+
+/*
+ * Clear an all events.
+ * Return 0 if a mutex error occured or 1 otherwise.
+ */
+int ctrl_clear_events&#40;void&#41;;
+
+/*
+ * Set key mode
+ */
+void ctrl_set_key_mode&#40;ctrl_key_code_t key_code, ctrl_mode_t mode&#41;;
+
+/*
+ * Get a key mode.
+ */
+ctrl_mode_t ctrl_get_key_mode&#40;ctrl_key_code_t key_code&#41;;
+
+/*
+ * Set key repeat start time.
+ * rep_start_time is a time in seconds since key is pressed when
+ * repeating start.
+ */
+void ctrl_set_key_repstart&#40;ctrl_key_code_t key_code, 
+                         unsigned int rep_start_time&#41;;
+
+/*
+ * Set key repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen PRESSED events 
+ * until key is pressed.
+ */
+void ctrl_set_key_repinterval&#40;ctrl_key_code_t key_code,
+                            unsigned int rep_interval&#41;;
+
+/*
+ * Set a joystick axis zero range.
+ * If an axis changes within this range, it interpretes like the zero value.
+ */
+void ctrl_set_jstick_zerorange&#40;unsigned char x_zero_range,
+                              unsigned char y_zero_range&#41;;
+
+/*
+ * Get values of axes zero ranges.
+ */
+void ctrl_get_jstick_zerorange&#40;unsigned char *x_zero_range,
+                              unsigned char *y_zero_range&#41;;
+
+/*
+ * Set joystick axes values step.
+ * For example, if x_coord_step is 1, than x axis can be from -128 to 127;
+ * if x_coord_step is 10, than x axis can be from -12 to 12.
+ */
+void ctrl_set_jstick_coordstep&#40;unsigned char x_coord_step,
+                              unsigned char y_coord_step&#41;;
+
+/*
+ * Return a count of coordinates taking into account a current coord_step.
+ */
+void ctrl_get_jstick_coordcount&#40;unsigned char *x_count,
+                               unsigned char *y_count&#41;;
+
+/*
+ * Set joystick mode.
+ */
+void ctrl_set_jstick_mode&#40;ctrl_mode_t mode&#41;;
+
+/*
+ * Set joystick repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen JOYSTICK events 
+ * while key is pressed.
+ */
+void ctrl_set_jstick_repinterval&#40;unsigned int rep_interval&#41;;
+
+/*
+ * Nonblocking function.
+ * It check if any button is pressed.
+ * If any button is pressed return 1 and fill the key structure with 
+ * apropriate values or return 0 otherwise.
+ * Return -1 if a mutex error occured.
+ */
+inline int ctrl_pollevent&#40;ctrl_event_t *key&#41;;
+
+/*
+ * Blocking function.
+ * It wait button event and fill with values the key structure
+ * after a key is pressed and return.
+ * User must free it by himself.
+ * Return -1 if a mutex error occured.
+ */
+int ctrl_waitevent&#40;ctrl_event_t *key&#41;;
+
+int ctrl_thread&#40;SceSize args, void *argp&#41;;
+
+/*
+ * Init a ctrl thread. Must be called before calling any of the ctrl 
+ * functions.
+ * Return an error code or 0 if evething is ok. 
+ * ctrl thread id is returned through *thid. If an error occured 
+ * *thid is undefined.
+ */
+int init_ctrl_thread&#40;SceUID *thid&#41;;
+
+
+#endif /* __LIBCTRL_H__ */
diff -ru -N -x '.git*' tmp/Makefile libctrl/Makefile
--- tmp/Makefile        1970-01-01 03&#58;00&#58;00.000000000 +0300
+++ libctrl/Makefile    2009-03-26 21&#58;46&#58;48.000000000 +0300
@@ -0,0 +1,30 @@
+TARGET_LIB = libctrl.a
+OBJS = libctrl.o
+
+INCDIR = 
+CFLAGS = -O2 -G0 -Wall
+CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
+ASFLAGS = $&#40;CFLAGS&#41;
+
+LIBDIR =
+LDFLAGS =
+
+PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
+PSP_PREF=$&#40;shell psp-config --psp-prefix&#41;
+
+include $&#40;PSPSDK&#41;/lib/build.mak
+
+
+myclean&#58;
+       rm -f *~
+
+install&#58; all
+       install -m644 $&#40;TARGET_LIB&#41; $&#40;PSP_PREF&#41;/lib
+       install -m644 $&#40;patsubst %.a,%.h,$&#40;TARGET_LIB&#41;&#41; $&#40;PSP_PREF&#41;/include
+
+uninstall&#58;
+       rm -f $&#40;PSP_PREF&#41;/lib/$&#40;TARGET_LIB&#41;
+       rm -f $&#40;PSP_PREF&#41;/include/$&#40;patsubst %.a,%.h,$&#40;TARGET_LIB&#41;&#41;
+
+tags&#58;
+       etags --members --typedefs $&#40;patsubst %.o,%.c,$&#40;OBJS&#41;&#41;
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

Some demonstration program:

ctrldemo.c:

Code: Select all

/* 68x34 480x272 */
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <libctrl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>


PSP_MODULE_INFO&#40;"libctrl demo", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;PSP_THREAD_ATTR_USER&#41;;

#define printf pspDebugScreenPrintf


#define WORD_INTERVAL 7
#define MAX_X 417 // 480 - word_count*WORD_INTERVAL
#define MAX_Y 262 // 272 - 10

/* coordinate settings */
int x = 0;
int oldx = 0;
int y = 9;
int oldy = 9;
int dx = 1;
int dy = 1;
SceUID dx_mutex, dy_mutex;
int color = 0x11ffe6;

char autochange = 1;

int delay = 30000;

char pressed = 0;


/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41; &#123;
  sceKernelExitGame&#40;&#41;;
  return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41; &#123;
  int cbid;

  cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
  sceKernelRegisterExitCallback&#40;cbid&#41;;

  sceKernelSleepThreadCB&#40;&#41;;

  return 0;

&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41; &#123;
  int thid = 0;

  thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
  if&#40;thid >= 0&#41; &#123;
    sceKernelStartThread&#40;thid, 0, 0&#41;;
  &#125;

  return thid;
&#125;

void print_word&#40;int x, int y, int color, char const *const str&#41;
&#123;
  char *i;

  if &#40; !str &#41; return;

  i = &#40;char*&#41;str;

  while &#40; *i &#41; &#123;
    pspDebugScreenPutChar&#40;x, y, color, *i&#41;;

    x += WORD_INTERVAL;
    i++;
  &#125;
&#125;

int draw_thread&#40;SceSize args, void *argp&#41;
&#123;
  while &#40;1&#41; &#123;
    print_word&#40;oldx, oldy, color, "      "&#41;;
    print_word&#40;x, y, color, "Hello!"&#41;;

    oldx = x;
    oldy = y;
    x += dx;
    y += dy;
    if &#40; &#40; x > MAX_X &#41; || &#40; x < 1 &#41; &#41; &#123;
      sceKernelWaitSema&#40;dx_mutex, 1, 0&#41;;
      dx = -dx;
      sceKernelSignalSema&#40;dx_mutex, 1&#41;;
    &#125;
    if &#40; &#40; y > MAX_Y &#41; || &#40; y < 1 &#41; &#41; &#123;
      sceKernelWaitSema&#40;dy_mutex, 1, 0&#41;;
      dy = -dy;
      sceKernelSignalSema&#40;dy_mutex, 1&#41;;
    &#125;
    x = oldx + dx;
    y = oldy + dy;
    
    if &#40; autochange &#41; color += 1000;
    if &#40; color > 0xFFFFFF &#41; color = 1;

    sceKernelDelayThread&#40;delay&#41;;
  &#125;

  return 0;
&#125;

int main&#40;&#41;
&#123;
  SceUID ctrl_thid, draw_thid;
  ctrl_event_t *ctrl_event;


  pspDebugScreenInit&#40;&#41;;
  SetupCallbacks&#40;&#41;;


  pspDebugScreenSetXY&#40;40,20&#41;;

  pspDebugScreenSetTextColor&#40;0x11ffe6&#41;;


  /* Create mutexes */
  dx_mutex = sceKernelCreateSema&#40;"dx_mutex", 0, 1, 1, NULL&#41;;
  dy_mutex = sceKernelCreateSema&#40;"dy_mutex", 0, 1, 1, NULL&#41;;

  /* threads */
  ctrl_thid = sceKernelCreateThread&#40;"ctrl_thread", ctrl_thread, 0x10, 16384, 
                               0, NULL&#41;;
  if &#40; ctrl_thid < 0 &#41; &#123;
    printf&#40;"Thread error"&#41;;
    return 1;
  &#125;
  sceKernelStartThread&#40;ctrl_thid, 0, NULL&#41;;
  /* Time to safeguard against ctrl_thread&#40;&#41; initialization isn't finished. */
  sceKernelDelayThread&#40;100000&#41;;

  draw_thid = sceKernelCreateThread&#40;"draw_thread", draw_thread, 0x10, 16384, 
                               0, NULL&#41;;
  if &#40; draw_thid < 0 &#41; &#123;
    printf&#40;"Thread error"&#41;;
    return 1;
  &#125;
  sceKernelStartThread&#40;draw_thid, 0, NULL&#41;;

  /* Some settings */
  ctrl_set_key_mode&#40;PSP_CTRL_UP_KEY, REPEAT&#41;;
  ctrl_set_key_repstart&#40;PSP_CTRL_UP_KEY, 0&#41;;
  ctrl_set_key_mode&#40;PSP_CTRL_DOWN_KEY, REPEAT&#41;;
  ctrl_set_key_repstart&#40;PSP_CTRL_DOWN_KEY, 0&#41;;
  ctrl_set_key_mode&#40;PSP_CTRL_LEFT_KEY, REPEAT&#41;;
  ctrl_set_key_repstart&#40;PSP_CTRL_LEFT_KEY, 0&#41;;
  ctrl_set_key_mode&#40;PSP_CTRL_RIGHT_KEY, REPEAT&#41;;
  ctrl_set_key_repstart&#40;PSP_CTRL_RIGHT_KEY, 0&#41;;
  ctrl_set_key_mode&#40;PSP_CTRL_LTRIGGER_KEY, REPEAT&#41;;
  ctrl_set_key_repstart&#40;PSP_CTRL_LTRIGGER_KEY, 0&#41;;
  ctrl_set_key_mode&#40;PSP_CTRL_RTRIGGER_KEY, REPEAT&#41;;
  ctrl_set_key_repstart&#40;PSP_CTRL_RTRIGGER_KEY, 0&#41;;
  ctrl_set_jstick_coordstep&#40;50, 50&#41;;
  ctrl_set_jstick_mode&#40;REPEAT&#41;;


  ctrl_event = &#40;ctrl_event_t*&#41;malloc&#40;sizeof&#40;ctrl_event_t&#41;&#41;;

  while &#40;1&#41; &#123;
    pspDebugScreenSetTextColor&#40;0x663333&#41;;

    pspDebugScreenSetXY&#40;1,1&#41;;
    printf&#40;"                                                  "&#41;;
    pspDebugScreenSetXY&#40;1,1&#41;;
    printf&#40;"delay - %d, color - %x", delay, color&#41;;

    ctrl_pollevent&#40;ctrl_event&#41;;

    if &#40; ctrl_event->event == PRESSED &#41;
      switch &#40;ctrl_event->key&#41; &#123;
      case PSP_CTRL_UP_KEY&#58;
        sceKernelWaitSema&#40;dy_mutex, 1, 0&#41;;
        if &#40; dy > -5 &#41; dy--;
        sceKernelSignalSema&#40;dy_mutex, 1&#41;;
        break;
      case PSP_CTRL_DOWN_KEY&#58;
        sceKernelWaitSema&#40;dy_mutex, 1, 0&#41;;
        if &#40; dy < 5 &#41; dy++;
        sceKernelSignalSema&#40;dy_mutex, 1&#41;;
        break;
      case PSP_CTRL_LEFT_KEY&#58;
        sceKernelWaitSema&#40;dx_mutex, 1, 0&#41;;
        if &#40; dx > -5 &#41; dx--;
        sceKernelSignalSema&#40;dx_mutex, 1&#41;;
        break;
      case PSP_CTRL_RIGHT_KEY&#58;
        sceKernelWaitSema&#40;dx_mutex, 1, 0&#41;;
        if &#40; dx < 5 &#41; dx++;
        sceKernelSignalSema&#40;dx_mutex, 1&#41;;
        break;
      case PSP_CTRL_LTRIGGER_KEY&#58;
        if &#40; delay < 2000000 &#41; delay += 2000;
        break;
      case PSP_CTRL_RTRIGGER_KEY&#58;
        if &#40; delay > 10000 &#41; delay -= 2000;
        break;
      default&#58;
        break;
      &#125;

    if &#40; ctrl_event->event == JOYSTICK &#41; &#123;
      dy += ctrl_event->jstick_y;
      if &#40; dy <= -5 &#41; dy = -5;
      if &#40; dy >= 5 &#41; dy = 5;

      dx += ctrl_event->jstick_x;
      if &#40; dx <= -5 &#41; dx = -5;
      if &#40; dx >= 5 &#41; dx = 5;
    &#125;

    sceDisplayWaitVblankStart&#40;&#41;;
  &#125;

  sceKernelExitGame&#40;&#41;;
  return 0;
&#125;
Makefile:

Code: Select all

TARGET = ctrldemo.c
OBJS = ctrldemo.o

PSPSDK = $&#40;PSPDEV&#41;/psp/sdk
CFLAGS = -O2 -G0 -Wall
LIBS = -lctrl -lpsprtc
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

BUILD_PRX = 1
PSP_FW_VERSION = 500

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = libctrl demo

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak

install&#58;
        mount /media/usbflash 
        mkdir -p /media/usbflash/psp/game5xx/ctrldemo || true
        cp EBOOT.PBP /media/usbflash/psp/game5xx/ctrldemo
        umount /media/usbflash
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

I have a strange idea. May be I will add a callback mechanism to the library.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

I committed both the library and demo in rev 2474, thanks.

Code: Select all

$ svn commit
Adding         libctrl
Adding         libctrl/Makefile
Adding         libctrl/demo
Adding         libctrl/demo/Makefile
Adding         libctrl/demo/ctrldemo.c
Adding         libctrl/libctrl.c
Adding         libctrl/libctrl.h
Transmitting file data .....
Committed revision 2474.
http://svn.ps2dev.org/listing.php?repna ... =2474&sc=1

ps. Having the inline patches here for viewing is nice, but it's hard to apply them (the forum mangles the format). For future patches, if you could also send a link to the patch somewhere, that would make things easier for us.
Post Reply