wiz port. Lots of refactoring, some bugfixes
authornotaz <notaz@pixelinis>
Thu, 29 Jul 2010 16:26:04 +0000 (19:26 +0300)
committernotaz <notaz@pixelinis>
Thu, 29 Jul 2010 16:26:04 +0000 (19:26 +0300)
31 files changed:
.gitignore [new file with mode: 0644]
common/cmn.c
common/fbdev.c
common/host_fb.c
common/host_fb.h
common/warm.c [new file with mode: 0644]
common/warm.h [new file with mode: 0644]
common/wiz_video.c
dist/ginge.gpe [new file with mode: 0755]
dist/ginge.pxml [moved from ginge.pxml with 100% similarity]
dist/ginge.sh [new file with mode: 0755]
dist/ginge32.png [new file with mode: 0644]
dist/ginge60.png [moved from ginge.png with 100% similarity]
dist/ginge_dyn_eabi.sh [moved from loader/ginge_dyn.sh with 100% similarity]
dist/ginge_dyn_oabi.sh [new file with mode: 0755]
dist/make_cmn.sh [new file with mode: 0755]
loader/.gitignore [deleted file]
loader/Makefile
loader/dl.c
loader/emu.c
loader/ginge_dyn.symver [new file with mode: 0644]
loader/header.h
loader/host_pnd.c
loader/host_wiz.c [new file with mode: 0644]
loader/loader.c
loader/override.c
loader/realfuncs.h
make_pnd.sh
make_wiz.sh [new file with mode: 0755]
prep/Makefile
prep/main.c

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2c222af
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+cscope.out
+tags
index 9f802ba..7886c7c 100644 (file)
@@ -1,3 +1,4 @@
+// vim:shiftwidth=2:expandtab
 #ifdef LOADER
 #include "../loader/realfuncs.h"
 #endif
@@ -12,24 +13,24 @@ int make_local_path(char *buf, size_t size, const char *file)
   ssize_t ret;
   char *p;
 
-  ret = readlink("/proc/self/exe", buf, size - 1);
-  if (ret < 0) {
-    perror("readlink");
-    goto err;
+  p = getenv("GINGE_ROOT");
+  if (p != NULL) {
+    strncpy(buf, p, size);
+    buf[size - 1] = 0;
+    p = buf + strlen(buf);
   }
-  buf[ret] = 0;
-
-  p = strrchr(buf, '/');
-  if (p == NULL)
-    goto err;
-  p++;
+  else {
+    ret = readlink("/proc/self/exe", buf, size - 1);
+    if (ret < 0) {
+      perror("readlink");
+      goto err;
+    }
+    buf[ret] = 0;
 
-  if (strstr(p, ".so")) {
-    p = getenv("GINGE_ROOT");
+    p = strrchr(buf, '/');
     if (p == NULL)
       goto err;
-    strcpy(buf, p);
-    p = buf + strlen(buf);
+    p++;
   }
 
   snprintf(p, size - (p - buf), "%s", file);
index 069dc6e..afcd529 100644 (file)
@@ -64,7 +64,7 @@ struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int n
        if (fbdev == NULL)
                return NULL;
 
-       fbdev->fd = open(fbdev_name, O_RDWR, 0);
+       fbdev->fd = open(fbdev_name, O_RDWR);
        if (fbdev->fd == -1) {
                fprintf(stderr, "%s: ", fbdev_name);
                perror("open");
index 92cde57..46467d4 100644 (file)
+// vim:shiftwidth=2:expandtab
+#include <string.h>
 #ifdef LOADER
 #include "../loader/realfuncs.h"
 #endif
 
-#include "fbdev.c"
 #include "host_fb.h"
 
+static void *host_screen;
+static int host_stride;
+
+#if defined(PND)
+
+#include "fbdev.c"
+
 static struct vout_fbdev *fbdev;
 
+void *host_video_flip(void)
+{
+  host_screen = vout_fbdev_flip(fbdev);
+  return host_screen;
+}
+
 int host_video_init(int *stride, int no_dblbuf)
 {
-       const char *fbdev_name;
-       int w, h;
+  const char *fbdev_name;
+  int w, h;
+
+  fbdev_name = getenv("FBDEV");
+  if (fbdev_name == NULL)
+    fbdev_name = "/dev/fb1";
+
+  fbdev = vout_fbdev_init(fbdev_name, &w, &h, no_dblbuf);
+  if (fbdev == NULL)
+    return -1;
+
+  host_stride = w * 2;
+  if (stride != 0)
+    *stride = host_stride;
+  host_video_flip();
 
-       fbdev_name = getenv("FBDEV");
-       if (fbdev_name == NULL)
-               fbdev_name = "/dev/fb1";
-       
-       fbdev = vout_fbdev_init(fbdev_name, &w, &h, no_dblbuf);
-       *stride = w * 2;
-       return (fbdev != 0) ? 0 : -1;
+  return 0;
 }
 
+#elif defined(WIZ)
+
+#include "warm.c"
+#include "wiz_video.c"
+
 void *host_video_flip(void)
 {
-       return vout_fbdev_flip(fbdev);
+  vout_gp2x_flip();
+  host_screen = g_screen_ptr;
+  return host_screen;
+}
+
+int host_video_init(int *stride, int no_dblbuf)
+{
+  int ret;
+
+  host_stride = 320 * 2;
+  if (stride != 0)
+    *stride = host_stride;
+
+  ret = vout_gp2x_init(no_dblbuf);
+  if (ret != 0)
+    return ret;
+
+  host_video_flip();
+  return 0;
+}
+
+#endif
+
+static unsigned short host_pal[256];
+
+static void host_update_pal(unsigned int *pal)
+{
+  unsigned short *dstp = host_pal;
+  int i;
+
+  for (i = 0; i < 256; i++, pal++, dstp++) {
+    unsigned int t = *pal;
+    *dstp = ((t >> 8) & 0xf800) | ((t >> 5) & 0x07e0) | ((t >> 3) & 0x001f);
+  }
+}
+
+void host_video_blit4(const unsigned char *src, int w, int h, unsigned int *pal)
+{
+  unsigned short *dst = host_screen;
+  unsigned short *hpal = host_pal;
+  int i, u;
+
+  if (pal != NULL)
+    host_update_pal(pal);
+
+  for (i = 0; i < 240; i++, dst += host_stride / 2 - 320) {
+    for (u = 320 / 2; u > 0; u--, src++) {
+      *dst++ = hpal[*src >> 4];
+      *dst++ = hpal[*src & 0x0f];
+    }
+  }
+
+  host_video_flip();
 }
+
+void host_video_blit8(const unsigned char *src, int w, int h, unsigned int *pal)
+{
+  unsigned short *dst = host_screen;
+  unsigned short *hpal = host_pal;
+  int i, u;
+
+  if (pal != NULL)
+    host_update_pal(pal);
+
+  for (i = 0; i < 240; i++, dst += host_stride / 2 - 320) {
+    for (u = 320 / 4; u > 0; u--) {
+      *dst++ = hpal[*src++];
+      *dst++ = hpal[*src++];
+      *dst++ = hpal[*src++];
+      *dst++ = hpal[*src++];
+    }
+  }
+
+  host_video_flip();
+}
+
+void host_video_blit16(const unsigned short *src, int w, int h)
+{
+  unsigned short *dst = host_screen;
+  int i;
+
+  for (i = 0; i < 240; i++, dst += host_stride / 2, src += 320)
+    memcpy(dst, src, 320*2);
+
+  host_video_flip();
+}
+
index bd739d4..edb931b 100644 (file)
@@ -1,3 +1,6 @@
 int   host_video_init(int *stride, int no_dblbuf);
 void *host_video_flip(void);
 
+void host_video_blit4(const unsigned char *src, int w, int h, unsigned int *pal);
+void host_video_blit8(const unsigned char *src, int w, int h, unsigned int *pal);
+void host_video_blit16(const unsigned short *src, int w, int h);
diff --git a/common/warm.c b/common/warm.c
new file mode 100644 (file)
index 0000000..7cf22ac
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * wARM - exporting ARM processor specific privileged services to userspace
+ * userspace part
+ *
+ * Copyright (c) GraÅžvydas "notaz" Ignotas, 2009
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the organization nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+#define WARM_CODE
+#include "warm.h"
+
+/* provided by glibc */
+extern long init_module(void *, unsigned long, const char *);
+extern long delete_module(const char *, unsigned int);
+
+static int warm_fd = -1;
+static int kernel_version;
+
+static void sys_cacheflush(void *start, void *end)
+{
+#ifdef __ARM_EABI__
+       /* EABI version */
+       int num = __ARM_NR_cacheflush;
+       __asm__("mov  r0, %0 ;"
+               "mov  r1, %1 ;"
+               "mov  r2, #0 ;"
+               "mov  r7, %2 ;"
+               "swi  0" : : "r" (start), "r" (end), "r" (num)
+                       : "r0", "r1", "r2", "r3", "r7");
+#else
+       /* OABI */
+       __asm__("mov  r0, %0 ;"
+               "mov  r1, %1 ;"
+               "mov  r2, #0 ;"
+               "swi  %2" : : "r" (start), "r" (end), "i" __ARM_NR_cacheflush
+                       : "r0", "r1", "r2", "r3");
+#endif
+}
+
+/* Those are here because system() occasionaly fails on Wiz
+ * with errno 12 for some unknown reason */
+static int manual_insmod_26(const char *fname, const char *opts)
+{
+       unsigned long len, read_len;
+       int ret = -1;
+       void *buff;
+       FILE *f;
+
+       f = fopen(fname, "rb");
+       if (f == NULL)
+               return -1;
+
+       fseek(f, 0, SEEK_END);
+       len = ftell(f);
+       fseek(f, 0, SEEK_SET);
+
+       buff = malloc(len);
+       if (buff == NULL)
+               goto fail0;
+
+       read_len = fread(buff, 1, len, f);
+       if (read_len != len) {
+               fprintf(stderr, "failed to read module\n");
+               goto fail1;
+       }
+
+       ret = init_module(buff, len, opts);
+
+fail1:
+       free(buff);
+fail0:
+       fclose(f);
+       return ret;
+}
+
+static int manual_rmmod(const char *name)
+{
+       return delete_module(name, O_NONBLOCK|O_EXCL);
+}
+
+int warm_init(void)
+{
+       struct utsname unm;
+       char buff1[32], buff2[128];
+       int ret;
+
+       memset(&unm, 0, sizeof(unm));
+       uname(&unm);
+
+       if (strlen(unm.release) < 3 || unm.release[1] != '.') {
+               fprintf(stderr, "unexpected version string: %s\n", unm.release);
+               goto fail;
+       }
+       kernel_version = ((unm.release[0] - '0') << 4) | (unm.release[2] - '0');
+
+       warm_fd = open("/proc/warm", O_RDWR);
+       if (warm_fd >= 0)
+               return 0;
+
+       snprintf(buff1, sizeof(buff1), "warm_%s.%s", unm.release, kernel_version >= 0x26 ? "ko" : "o");
+       snprintf(buff2, sizeof(buff2), "/sbin/insmod %s verbose=1", buff1);
+
+       /* try to insmod */
+       ret = system(buff2);
+       if (ret != 0) {
+               fprintf(stderr, "system/insmod failed: %d %d\n", ret, errno);
+               if (kernel_version >= 0x26) {
+                       ret = manual_insmod_26(buff1, "verbose=1");
+                       if (ret != 0)
+                               fprintf(stderr, "manual insmod also failed: %d\n", ret);
+               }
+       }
+
+       warm_fd = open("/proc/warm", O_RDWR);
+       if (warm_fd >= 0)
+               return 0;
+
+fail:
+       fprintf(stderr, "wARM: can't init, acting as sys_cacheflush wrapper\n");
+       return -1;
+}
+
+void warm_finish(void)
+{
+       char name[32], cmd[64];
+       int ret;
+
+       if (warm_fd < 0)
+               return;
+
+       close(warm_fd);
+       warm_fd = -1;
+
+       if (kernel_version < 0x26) {
+               struct utsname unm;
+               memset(&unm, 0, sizeof(unm));
+               uname(&unm);
+               snprintf(name, sizeof(name), "warm_%s", unm.release);
+       }
+       else
+               strcpy(name, "warm");
+
+       snprintf(cmd, sizeof(cmd), "/sbin/rmmod %s", name);
+       ret = system(cmd);
+       if (ret != 0) {
+               fprintf(stderr, "system/rmmod failed: %d %d\n", ret, errno);
+               manual_rmmod(name);
+       }
+}
+
+int warm_cache_op_range(int op, void *addr, unsigned long size)
+{
+       struct warm_cache_op wop;
+       int ret;
+
+       if (warm_fd < 0) {
+               /* note that this won't work for warm_cache_op_all */
+               sys_cacheflush(addr, (char *)addr + size);
+               return -1;
+       }
+
+       wop.ops = op;
+       wop.addr = (unsigned long)addr;
+       wop.size = size;
+
+       ret = ioctl(warm_fd, WARMC_CACHE_OP, &wop);
+       if (ret != 0) {
+               perror("WARMC_CACHE_OP failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+int warm_cache_op_all(int op)
+{
+       return warm_cache_op_range(op, NULL, (unsigned long)-1);
+}
+
+int warm_change_cb_range(int cb, int is_set, void *addr, unsigned long size)
+{
+       struct warm_change_cb ccb;
+       int ret;
+
+       if (warm_fd < 0)
+               return -1;
+       
+       ccb.addr = (unsigned long)addr;
+       ccb.size = size;
+       ccb.cb = cb;
+       ccb.is_set = is_set;
+
+       ret = ioctl(warm_fd, WARMC_CHANGE_CB, &ccb);
+       if (ret != 0) {
+               perror("WARMC_CHANGE_CB failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+int warm_change_cb_upper(int cb, int is_set)
+{
+       return warm_change_cb_range(cb, is_set, 0, 0);
+}
+
+unsigned long warm_virt2phys(const void *ptr)
+{
+       unsigned long ptrio;
+       int ret;
+
+       ptrio = (unsigned long)ptr;
+       ret = ioctl(warm_fd, WARMC_VIRT2PHYS, &ptrio);
+       if (ret != 0) {
+               perror("WARMC_VIRT2PHYS failed");
+               return (unsigned long)-1;
+       }
+
+       return ptrio;
+}
+
diff --git a/common/warm.h b/common/warm.h
new file mode 100644 (file)
index 0000000..a3fdd6b
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * wARM - exporting ARM processor specific privileged services to userspace
+ * library functions
+ *
+ * Copyright (c) GraÅžvydas "notaz" Ignotas, 2009
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the organization nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __WARM_H__
+#define __WARM_H__ 1
+
+/* cache operations (warm_cache_op_*):
+ * o clean - write dirty data to memory, but also leave in cache.
+ * o invalidate - throw away everything in cache, losing dirty data.
+ *
+ * Write buffer is always drained, no ops will only drain WB
+ */
+#define WOP_D_CLEAN            (1 << 0)
+#define WOP_D_INVALIDATE       (1 << 1)
+#define WOP_I_INVALIDATE       (1 << 2)
+
+/* change C and B bits (warm_change_cb_*)
+ * if is_set in not zero, bits are set, else cleared.
+ * the address for range function is virtual address.
+ */
+#define WCB_C_BIT              (1 << 0)
+#define WCB_B_BIT              (1 << 1)
+
+#ifndef __ASSEMBLER__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int warm_init(void);
+
+int warm_cache_op_range(int ops, void *virt_addr, unsigned long size);
+int warm_cache_op_all(int ops);
+
+int warm_change_cb_upper(int cb, int is_set);
+int warm_change_cb_range(int cb, int is_set, void *virt_addr, unsigned long size);
+
+unsigned long warm_virt2phys(const void *ptr);
+
+void warm_finish(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* internal */
+#ifdef WARM_CODE
+
+#include <linux/ioctl.h>
+
+#define WARM_IOCTL_BASE 'A'
+
+struct warm_cache_op
+{
+       unsigned long addr;
+       unsigned long size;
+       int ops;
+};
+
+struct warm_change_cb
+{
+       unsigned long addr;
+       unsigned long size;
+       int cb;
+       int is_set;
+};
+
+#define WARMC_CACHE_OP _IOW(WARM_IOCTL_BASE,  0, struct warm_cache_op)
+#define WARMC_CHANGE_CB        _IOW(WARM_IOCTL_BASE,  1, struct warm_change_cb)
+#define WARMC_VIRT2PHYS        _IOWR(WARM_IOCTL_BASE, 2, unsigned long)
+
+#endif /* WARM_CODE */
+#endif /* !__ASSEMBLER__ */
+#endif /* __WARM_H__ */
index 4395683..7996ee3 100644 (file)
@@ -8,13 +8,15 @@
 #include <sys/mman.h>
 #include <unistd.h>
 #include <linux/fb.h>
+#include "warm.h"
 
 static volatile unsigned short *memregs;
 static volatile unsigned long  *memregl;
-static int memdev = -1;
+int memdev = -1;
 
 #define FB_BUF_COUNT 4
 static unsigned int fb_paddr[FB_BUF_COUNT];
+static int fb_buf_count = FB_BUF_COUNT;
 static int fb_work_buf;
 static int fbdev = -1;
 
@@ -28,12 +30,12 @@ static void vout_gp2x_flip(void)
        memregl[0x4058>>2] |= 0x10;
 
        fb_work_buf++;
-       if (fb_work_buf >= FB_BUF_COUNT)
+       if (fb_work_buf >= fb_buf_count)
                fb_work_buf = 0;
        g_screen_ptr = gp2x_screens[fb_work_buf];
 }
 
-static int vout_gp2x_init(void)
+static int vout_gp2x_init(int no_dblbuf)
 {
        struct fb_fix_screeninfo fbfix;
        int i, ret;
@@ -75,6 +77,13 @@ static int vout_gp2x_init(void)
        }
        memset(gp2x_screens[0], 0, 320*240*2*FB_BUF_COUNT);
 
+       if (!no_dblbuf) {
+               warm_init();
+               ret = warm_change_cb_range(WCB_B_BIT, 1, gp2x_screens[0], 320*240*2*FB_BUF_COUNT);
+               if (ret != 0)
+                       fprintf(stderr, "could not make fb buferable.\n");
+       }
+
        printf("  %p -> %08x\n", gp2x_screens[0], fb_paddr[0]);
        for (i = 1; i < FB_BUF_COUNT; i++)
        {
@@ -85,6 +94,9 @@ static int vout_gp2x_init(void)
        fb_work_buf = 0;
        g_screen_ptr = gp2x_screens[0];
 
+       if (no_dblbuf)
+               fb_buf_count = 1;
+
        return 0;
 }
 
@@ -96,5 +108,7 @@ void vout_gp2x_finish(void)
 
        munmap((void *)memregs, 0x20000);
        close(memdev);
+
+       warm_finish();
 }
 
diff --git a/dist/ginge.gpe b/dist/ginge.gpe
new file mode 100755 (executable)
index 0000000..27521e5
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+/sbin/rmmod warm 2> /dev/null
+/sbin/insmod ./warm_2.6.24.ko
+
+# theoretically GP2X apps can make use of more RAM, because
+# Wiz has 2.6 kernel (larger memory requirements) and larger
+# reserved areas, so we mount some swap here just in case.
+mkswap swapfile
+swapon swapfile
+
+./gp2xmenu
+
+swapoff swapfile
similarity index 100%
rename from ginge.pxml
rename to dist/ginge.pxml
diff --git a/dist/ginge.sh b/dist/ginge.sh
new file mode 100755 (executable)
index 0000000..66a99e1
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+export FBDEV=/dev/fb1
+ofbset -fb $FBDEV -pos 80 0 -size 640 480 -mem 614400 -en 1
+fbset -fb $FBDEV -g 320 240 320 480 16
+
+# make ir runnable from ssh
+if [ -z "$DISPLAY" ]; then
+export DISPLAY=:0
+fi
+
+./gp2xmenu
+  
+ofbset -fb $FBDEV -pos 0 0 -size 0 0 -mem 0 -en 0
diff --git a/dist/ginge32.png b/dist/ginge32.png
new file mode 100644 (file)
index 0000000..5bc2a4f
Binary files /dev/null and b/dist/ginge32.png differ
similarity index 100%
rename from ginge.png
rename to dist/ginge60.png
similarity index 100%
rename from loader/ginge_dyn.sh
rename to dist/ginge_dyn_eabi.sh
diff --git a/dist/ginge_dyn_oabi.sh b/dist/ginge_dyn_oabi.sh
new file mode 100755 (executable)
index 0000000..180d0da
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+root=$1
+shift
+
+#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${root}lib"
+export LD_PRELOAD="${root}ginge_dyn"
+
+export GINGE_ROOT="${root}"
+
+exec "$@"
diff --git a/dist/make_cmn.sh b/dist/make_cmn.sh
new file mode 100755 (executable)
index 0000000..486f949
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+set -e
+
+if [ -z "$1" ]; then
+       echo "usage: $0 <out_dir>"
+       exit 1
+fi
+
+rm -rf $1
+mkdir $1
+cp gp2xmenu/gp2xmenu $1/
+cp -r gp2xmenu/gp2xmenu_data $1/
+cp prep/ginge_prep $1/
+cp loader/ginge_dyn $1/
+cp loader/ginge_sloader $1/
+cp readme.txt $1/
+
diff --git a/loader/.gitignore b/loader/.gitignore
deleted file mode 100644 (file)
index 5761abc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*.o
index ed9d113..0a28670 100644 (file)
@@ -22,20 +22,28 @@ ifeq "$(ARCH)" "arm"
 ASFLAGS += -mfloat-abi=soft
 OBJ += sys_cacheflush.o emu_arm.o
 endif
+ifdef PND
+CFLAGS += -DPND
+OBJ += host_pnd.o
+endif
+ifdef WIZ
+CFLAGS += -DWIZ
+OBJ += host_wiz.o
+endif
 
 vpath %.c = ../common/
 
 TARGET_S = ginge_sloader
 TARGET_D = ginge_dyn
 
-OBJ += emu.o host_fb.o host_pnd.o cmn.o
+OBJ += emu.o host_fb.o cmn.o
 OBJ_S += $(OBJ) loader.o loader_$(ARCH).o patches.o
 OBJ_D += $(OBJ) dl.o
 
 all: $(TARGET_S) $(TARGET_D)
 
 $(TARGET_S): LDFLAGS += -Wl,-T script_$(ARCH).lds
-$(TARGET_D): LDFLAGS += -ldl
+$(TARGET_D): LDFLAGS += -ldl -Wl,--version-script=$(TARGET_D).symver
 
 $(TARGET_S): $(OBJ_S)
        $(CC) -o $@ $^ -static $(LDFLAGS)
index 154e012..468a2e0 100644 (file)
@@ -9,6 +9,14 @@
 #define DL
 #include "override.c"
 
+static void next_line(FILE *f)
+{
+  int c;
+  do {
+    c = fgetc(f);
+  } while (c != EOF && c != '\n');
+}
+
 __attribute__((constructor))
 static void ginge_init(void)
 {
@@ -32,7 +40,7 @@ static void ginge_init(void)
     exit(1);
   }
 
-  ret = fscanf(f, "%x-%x %*s %*s %*s %*s %*s\n", &start, &end);
+  ret = fscanf(f, "%x-%x ", &start, &end);
   if (ret != 2) {
     perror("parse maps");
     exit(1);
@@ -46,6 +54,8 @@ static void ginge_init(void)
     perror("warning: mprotect");
 
   while (1) {
+    next_line(f);
+
     ret = fscanf(f, "%x-%*s %*s %*s %*s %*s %*s\n", &start);
     if (ret <= 0)
       break;
@@ -62,6 +72,10 @@ static void ginge_init(void)
 #endif
   fclose(f);
 
+  // remove self from preload, further commands (from system() and such)
+  // will be handled by ginge_prep.
+  unsetenv("LD_PRELOAD");
+
   emu_init((void *)lowest_segment);
 }
 
index f161795..3ab4b34 100644 (file)
@@ -103,15 +103,11 @@ static struct {
 
   // state
   void *umem;
-  u16 host_pal[256];
   u32 old_mlc_stl_adr;
   u32 btn_state; // as seen through /dev/GPIO
   u32 dirty_pal:1;
 } mmsp2;
 
-static u16 *host_screen;
-static int host_stride;
-
 
 #if defined(LOG_IO) || defined(LOG_IO_UNK)
 static void log_io(const char *pfx, u32 a, u32 d, int size)
@@ -270,56 +266,34 @@ bad_blit:
   dump_blitter();
 }
 
-// TODO: hw scaler stuff
-static void mlc_flip(u8 *src, int bpp)
+// FIXME: pass real dimensions to blitters
+static void mlc_flip(void *src, int bpp)
 {
-  u16 *dst = host_screen;
-  u16 *hpal = mmsp2.host_pal;
-  int i, u;
+  u32 *srcp = NULL;
 
+  // only pass pal to host if it's dirty
   if (bpp <= 8 && mmsp2.dirty_pal) {
-    u32 *srcp = mmsp2.mlc_stl_pallt_d32;
-    u16 *dstp = hpal;
-
-    for (i = 0; i < 256; i++, srcp++, dstp++) {
-      u32 t = *srcp;
-      *dstp = ((t >> 8) & 0xf800) | ((t >> 5) & 0x07e0) | ((t >> 3) & 0x001f);
-    }
+    srcp = mmsp2.mlc_stl_pallt_d32;
     mmsp2.dirty_pal = 0;
   }
 
   switch (bpp) {
   case  4:
-    for (i = 0; i < 240; i++, dst += host_stride / 2 - 320) {
-      for (u = 320 / 2; u > 0; u--, src++) {
-        *dst++ = hpal[*src >> 4];
-        *dst++ = hpal[*src & 0x0f];
-      }
-    }
+    host_video_blit4(src, 320, 240, srcp);
     break;
 
   case  8:
-    for (i = 0; i < 240; i++, dst += host_stride / 2 - 320) {
-      for (u = 320 / 4; u > 0; u--) {
-        *dst++ = hpal[*src++];
-        *dst++ = hpal[*src++];
-        *dst++ = hpal[*src++];
-        *dst++ = hpal[*src++];
-      }
-    }
+    host_video_blit8(src, 320, 240, srcp);
     break;
 
   case 16:
-    for (i = 0; i < 240; i++, dst += host_stride / 2, src += 320*2)
-      memcpy(dst, src, 320*2);
+    host_video_blit16(src, 320, 240);
     break;
 
   case 24:
     // TODO
     break;
   }
-
-  host_screen = host_video_flip();
 }
 
 #define ts_add_nsec(ts, ns) { \
@@ -372,11 +346,11 @@ static void *fb_sync_thread(void *arg)
       ts_add_nsec(ts, 50000000);
       manual_refresh++;
       if (manual_refresh == 2)
-        log("fb_thread: switch to manual refresh\n");
+        dbg("fb_thread: switch to manual refresh\n");
     } else {
       ts_add_nsec(ts, 16666667);
       if (manual_refresh > 1)
-        log("fb_thread: switch to auto refresh\n");
+        dbg("fb_thread: switch to auto refresh\n");
       manual_refresh = 0;
     }
 
@@ -747,7 +721,7 @@ static void segv_sigaction(int num, siginfo_t *info, void *ctx)
     // real crash - time to die
     err("segv %d %p @ %08x\n", info->si_code, info->si_addr, regs[15]);
     for (i = 0; i < 8; i++)
-      err(" r%d=%08x r%2d=%08x\n", i, regs[i], i+8, regs[i+8]);
+      dbg(" r%d=%08x r%2d=%08x\n", i, regs[i], i+8, regs[i+8]);
     signal(num, SIG_DFL);
     raise(num);
     return;
@@ -804,7 +778,7 @@ void emu_init(void *map_bottom)
 
   g_linkpage = (void *)(((u32)map_bottom - LINKPAGE_ALLOC) & ~0xfff);
   pret = mmap(g_linkpage, LINKPAGE_ALLOC, PROT_READ|PROT_WRITE,
-              MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+              MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
   if (pret != g_linkpage) {
     perror(PFX "mmap linkpage");
     exit(1);
@@ -812,20 +786,31 @@ void emu_init(void *map_bottom)
   log("linkpages @ %p\n", g_linkpage);
   init_linkpage();
 
-  mmsp2.umem = mmap(NULL, 0x2000000, PROT_READ|PROT_WRITE|PROT_EXEC,
-                    MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-  if (mmsp2.umem == MAP_FAILED) {
-    perror(PFX "mmap upper mem");
+  // host stuff
+  ret = host_init();
+  if (ret != 0) {
+    err("can't init host\n");
     exit(1);
   }
 
-  // host stuff
-  ret = host_video_init(&host_stride, 0);
+  ret = host_video_init(NULL, 0);
   if (ret != 0) {
-    err("can't init video\n");
+    err("can't init host video\n");
+    exit(1);
+  }
+
+#ifdef WIZ
+  // we are short on memmory on Wiz, need special handling
+  extern void *host_mmap_upper(void);
+  mmsp2.umem = host_mmap_upper();
+#else
+  mmsp2.umem = mmap(NULL, 0x2000000, PROT_READ|PROT_WRITE|PROT_EXEC,
+                    MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+#endif
+  if (mmsp2.umem == MAP_FAILED) {
+    perror(PFX "mmap upper mem");
     exit(1);
   }
-  host_screen = host_video_flip();
 
   ret = pthread_create(&tid, NULL, fb_sync_thread, NULL);
   if (ret != 0) {
@@ -844,16 +829,16 @@ void emu_init(void *map_bottom)
 
 int emu_read_gpiodev(void *buf, int count)
 {
-  unsigned int btns;
-
-  if (count < 4) {
+  if (count <= 0) {
     err("gpiodev read %d?\n", count);
     return -1;
   }
+  if (count > 4)
+    count = 4;
 
-  btns = host_read_btns();
-  memcpy(buf, &btns, 4);
-  return 4;
+  mmsp2.btn_state = host_read_btns();
+  memcpy(buf, &mmsp2.btn_state, count);
+  return count;
 }
 
 struct dev_fd_t emu_interesting_fds[] = {
diff --git a/loader/ginge_dyn.symver b/loader/ginge_dyn.symver
new file mode 100644 (file)
index 0000000..c0c70c1
--- /dev/null
@@ -0,0 +1,16 @@
+{
+global:
+       open;
+       fopen;
+       mmap;
+       mmap2;
+       read;
+       ioctl;
+       sigaction;
+       tcgetattr;
+       tcsetattr;
+       system;
+
+local:
+       *;
+};
index 34db74f..752dd03 100644 (file)
@@ -46,6 +46,7 @@ int   emu_read_gpiodev(void *buf, int count);
 void *emu_do_fopen(const char *path, const char *mode);
 int   emu_do_system(const char *command);
 
+int   host_init(void);
 int   host_read_btns(void);
 
 enum  { GP2X_UP = 0,      GP2X_LEFT = 2,      GP2X_DOWN = 4,  GP2X_RIGHT = 6,
index 5c79b91..9064047 100644 (file)
 #include "realfuncs.h"
 
 static int ifds[2] = { -1, -1 };
-static int init_done;
 static int keystate;
 
-static void init(void)
+int host_init(void)
 {
   char buff[64];
   int i, ifd, ret;
 
   for (ifd = -1, i = 0; ifds[0] == -1 || ifds[1] == -1; i++) {
     snprintf(buff, sizeof(buff), "/dev/input/event%i", i);
-    ifd = open(buff, O_RDONLY | O_NONBLOCK, 0);
+    ifd = open(buff, O_RDONLY | O_NONBLOCK);
     if (ifd == -1)
       break;
 
@@ -47,7 +46,8 @@ static void init(void)
     fprintf(stderr, PFX "missing buttons\n");
   if (ifds[1] < 0)
     fprintf(stderr, PFX "missing keypad\n");
-  init_done = 1;
+
+  return 0;
 }
 
 static const struct {
@@ -84,9 +84,6 @@ int host_read_btns(void)
   struct input_event ev;
   int i, ret;
 
-  if (!init_done)
-    init();
-
   while (1)
   {
     ret = read(ifds[0], &ev, sizeof(ev));
diff --git a/loader/host_wiz.c b/loader/host_wiz.c
new file mode 100644 (file)
index 0000000..dccd841
--- /dev/null
@@ -0,0 +1,83 @@
+// vim:shiftwidth=2:expandtab
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "header.h"
+#include "../common/warm.h"
+#include "realfuncs.h"
+
+static int gpiodev = -1;
+extern int memdev; // leasing from wiz_video
+
+int host_init(void)
+{
+  gpiodev = open("/dev/GPIO", O_RDONLY);
+  if (gpiodev < 0)
+    perror(PFX "couldn't open /dev/GPIO");
+
+  return 0;
+}
+
+int host_read_btns(void)
+{
+  int r, value = 0;
+
+  r = read(gpiodev, &value, 4);
+  if (value & 0x02)
+    value |= 0x05;
+  if (value & 0x08)
+    value |= 0x14;
+  if (value & 0x20)
+    value |= 0x50;
+  if (value & 0x80)
+    value |= 0x41;
+
+  return value;
+}
+
+void *host_mmap_upper(void)
+{
+  void *ret;
+  int r;
+
+  // Wiz                GP2X
+  // <linux mem>        03460000-03ffffff  00ba0000
+  // 02aa0000-02dfffff  03100000-0345ffff  00360000
+  // <linux mem>        03000000-030fffff  00100000
+  // 03000000-03ffffff  02000000-02ffffff  01000000
+  ret = mmap((void *)0x82000000, 0x1000000, PROT_READ|PROT_WRITE|PROT_EXEC,
+             MAP_SHARED|MAP_FIXED, memdev, 0x3000000);
+  if (ret != (void *)0x82000000)
+    goto fail;
+
+  ret = mmap((void *)0x83000000, 0x100000, PROT_READ|PROT_WRITE|PROT_EXEC,
+             MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+  if (ret != (void *)0x83000000)
+    goto fail;
+
+  ret = mmap((void *)0x83100000, 0x360000, PROT_READ|PROT_WRITE|PROT_EXEC,
+             MAP_SHARED|MAP_FIXED, memdev, 0x2aa0000);
+  if (ret != (void *)0x83100000)
+    goto fail;
+
+  ret = mmap((void *)0x83460000, 0xba0000, PROT_READ|PROT_WRITE|PROT_EXEC,
+             MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+  if (ret != (void *)0x83460000)
+    goto fail;
+
+  r  = warm_change_cb_range(WCB_B_BIT|WCB_C_BIT, 1, (void *)0x82000000, 0x1000000);
+  r |= warm_change_cb_range(WCB_B_BIT|WCB_C_BIT, 1, (void *)0x83100000, 0x360000);
+  if (r != 0)
+    err("could not make upper mem cacheable.\n");
+
+  return (void *)0x82000000;
+
+fail:
+  err("mmap %p: ", ret);
+  perror(NULL);
+  exit(1);
+}
+
index 28bdf8e..fea8bb6 100644 (file)
@@ -125,7 +125,7 @@ int main(int argc, char *argv[])
       return 1;
     }
 
-    printf("load %d %08x-%08x from %08x\n", phdr[i].p_type,
+    log("load %d %08x-%08x from %08x\n", phdr[i].p_type,
       phdr[i].p_vaddr, end_addr, phdr[i].p_offset);
 
     align = phdr[i].p_vaddr & 0xfff;
@@ -170,7 +170,7 @@ int main(int argc, char *argv[])
     stack_frame[sfp++] = (long)environ[i];
   stack_frame[sfp++] = 0;
 
-  printf("entering %08x, %d stack entries\n", hdr.e_entry, sfp);
+  log("entering %08x, %d stack entries\n", hdr.e_entry, sfp);
   do_entry(hdr.e_entry, stack_frame, sfp, NULL);
 
   fprintf(stderr, "do_entry failed!\n");
index 5a10193..42b52ab 100644 (file)
@@ -1,6 +1,7 @@
 // vim:shiftwidth=2:expandtab
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -167,6 +168,7 @@ static UNUSED int w_system(const char *command)
   /* wrapper to real functions, to be set up on load */ \
   static typeof(sym) *p_real_##sym
 
+// note: update symver too
 MAKE_WRAP_SYM(open);
 MAKE_WRAP_SYM(fopen);
 MAKE_WRAP_SYM(mmap);
@@ -212,8 +214,14 @@ static const struct {
 #endif
 
 // just call real funcs for static, pointer for dynamic
-int real_open(const char *pathname, int flags, mode_t mode)
+int real_open(const char *pathname, int flags, ...)
 {
+  va_list ap;
+  mode_t mode;
+
+  va_start(ap, flags);
+  mode = va_arg(ap, mode_t);
+  va_end(ap);
   return open(pathname, flags, mode);
 }
 
index 4bca950..bda599a 100644 (file)
@@ -10,7 +10,7 @@
 #include <termios.h>
 
 
-int   real_open(const char *pathname, int flags, mode_t mode);
+int   real_open(const char *pathname, int flags, ...);
 FILE *real_fopen(const char *path, const char *mode);
 void *real_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
 int   real_read(int fd, void *buf, size_t count);
index 8970d38..8a0fab0 100755 (executable)
@@ -4,15 +4,11 @@ pnd_make=$HOME/dev/pnd/src/pandora-libraries/testdata/scripts/pnd_make.sh
 
 set -e
 
-rm -rf out
-mkdir out
-cp gp2xmenu/run.sh out/ginge.sh
-cp gp2xmenu/gp2xmenu out/
-cp -r gp2xmenu/gp2xmenu_data out/
-cp prep/ginge_prep out/
-cp loader/ginge_* out/
-cp -r tools out/
-cp -r lib out/
-cp readme.txt out/
-
-$pnd_make -p ginge.pnd -d out -x ginge.pxml -c -i ginge.png
+dist/make_cmn.sh out_pnd
+mkdir -p out_pnd/tools
+cp dist/ginge.sh out_pnd/
+cp dist/ginge_dyn_eabi.sh out_pnd/ginge_dyn.sh
+cp tools/cramfsck_eabi out_pnd/tools/cramfsck
+cp -r lib out_pnd/
+
+$pnd_make -p ginge.pnd -d out_pnd -x dist/ginge.pxml -c -i dist/ginge60.png
diff --git a/make_wiz.sh b/make_wiz.sh
new file mode 100755 (executable)
index 0000000..9176fc2
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e
+
+dist/make_cmn.sh out_wiz
+mkdir -p out_wiz/tools
+cp dist/ginge.gpe out_wiz/
+cp dist/ginge32.png out_wiz/ginge.png
+cp dist/ginge_dyn_oabi.sh out_wiz/ginge_dyn.sh
+cp tools/cramfsck_oabi out_wiz/tools/cramfsck
+
+dd if=/dev/zero of=out_wiz/swapfile bs=1M count=16
index 368dc0e..bf9c95c 100644 (file)
@@ -1,11 +1,17 @@
 CC = $(CROSS_COMPILE)gcc
 CFLAGS += -Wall -O2
 LDFLAGS = -s -O2
+ifdef WIZ
+CFLAGS += -DWIZ
+endif
+ifdef PND
+CFLAGS += -DPND
+endif
 
 vpath %.c = ../common/
 
 TARGET = ginge_prep
-OBJS = main.o host_fb.o cmn.o
+OBJS += main.o host_fb.o cmn.o
 
 all: $(TARGET)
 
index 7cc4337..8acbef7 100644 (file)
 #define LOADER_DYNAMIC  "ginge_dyn.sh"
 #define LAUNCHER        "gp2xmenu"
 
+#ifdef PND
+#define WRAP_APP        "op_runfbapp "
+#else
+#define WRAP_APP        ""
+#endif
+
 #include "font.c"
 
 static void *fb_mem;
 static int fb_stride;
 static int fb_x, fb_y;
+static int init_done;
 
 static char *sskip(char *p)
 {
@@ -36,6 +43,16 @@ static char *cskip(char *p)
   return p;
 }
 
+static void fb_text_init(void)
+{
+  int ret = host_video_init(&fb_stride, 1);
+  if (ret == 0)
+    fb_mem = host_video_flip();
+  fb_x = 4;
+  fb_y = 4;
+  init_done = 1;
+}
+
 static void fb_syms_out(void *fbi, int x, int y, int dotsz, int stride, const char *text, int count)
 {
   int v = -1, n = 0, *p;
@@ -72,6 +89,9 @@ static void fb_text_out(char *text)
   char *p, *pe;
   int l;
 
+  if (!init_done)
+    fb_text_init();
+
   if (fb_mem == NULL)
     return;
 
@@ -98,15 +118,6 @@ static void fb_text_out(char *text)
   }
 }
 
-static void fb_text_init(void)
-{
-  int ret = host_video_init(&fb_stride, 1);
-  if (ret == 0)
-    fb_mem = host_video_flip();
-  fb_x = 4;
-  fb_y = 4;
-}
-
 static void fbprintf(int is_err, const char *format, ...)
 {
   va_list ap;
@@ -242,8 +253,6 @@ int main(int argc, char *argv[])
   FILE *fin, *fout;
   int ret;
 
-  fb_text_init();
-
   if (argc < 2) {
     err("usage: %s <script|program> [args]\n", argv[0]);
     return 1;
@@ -281,13 +290,13 @@ int main(int argc, char *argv[])
     break;
 
   case 1:
-    fprintf(fout, "op_runfbapp %s%s ", root_path, LOADER_STATIC);
+    fprintf(fout, WRAP_APP "%s%s ", root_path, LOADER_STATIC);
     dump_args(fout, argc - 1, &argv[1]);
     fprintf(fout, "\n");
     goto no_in_script;
 
   case 2:
-    fprintf(fout, "op_runfbapp %s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path);
+    fprintf(fout, WRAP_APP "%s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path);
     dump_args(fout, argc - 1, &argv[1]);
     fprintf(fout, "\n");
     goto no_in_script;
@@ -385,12 +394,12 @@ int main(int argc, char *argv[])
       switch (ret) {
       case 1:
         printf(PFX "prefixing as static: %s", p);
-        fprintf(fout, "op_runfbapp %s%s ", root_path, LOADER_STATIC);
+        fprintf(fout, WRAP_APP "%s%s ", root_path, LOADER_STATIC);
         break;
 
       case 2:
         printf(PFX "prefixing as dynamic: %s", p);
-        fprintf(fout, "op_runfbapp %s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path);
+        fprintf(fout, WRAP_APP "%s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path);
         break;
 
       default:
@@ -412,10 +421,13 @@ no_in_script:
 
   fclose(fout);
 
-  msg("starting script..\n");
-  if (have_cramfs)
-    msg("\nsome files need to be unpacked, this may tike a few minutes.\n"
-        "Please wait at least while SD LED is active.\n");
+  //msg("starting script..\n");
+  if (have_cramfs) {
+    msg("\nsome files need to be unpacked, this may tike a few minutes.\n");
+#ifdef PND
+    msg("Please wait at least while SD LED is active.\n");
+#endif
+  }
   system("echo ---; cat /tmp/ginge_conv.sh; echo ---");
   chmod(out_script, S_IRWXU|S_IRWXG|S_IRWXO);
   chdir(cwd);