--- /dev/null
+*.o
+cscope.out
+tags
+// vim:shiftwidth=2:expandtab
#ifdef LOADER
#include "../loader/realfuncs.h"
#endif
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);
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");
+// 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();
+}
+
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);
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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__ */
#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;
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;
}
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++)
{
fb_work_buf = 0;
g_screen_ptr = gp2x_screens[0];
+ if (no_dblbuf)
+ fb_buf_count = 1;
+
return 0;
}
munmap((void *)memregs, 0x20000);
close(memdev);
+
+ warm_finish();
}
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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 "$@"
--- /dev/null
+#!/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/
+
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)
#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)
{
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);
perror("warning: mprotect");
while (1) {
+ next_line(f);
+
ret = fscanf(f, "%x-%*s %*s %*s %*s %*s %*s\n", &start);
if (ret <= 0)
break;
#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);
}
// 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)
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) { \
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;
}
// 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;
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);
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) {
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[] = {
--- /dev/null
+{
+global:
+ open;
+ fopen;
+ mmap;
+ mmap2;
+ read;
+ ioctl;
+ sigaction;
+ tcgetattr;
+ tcsetattr;
+ system;
+
+local:
+ *;
+};
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,
#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;
fprintf(stderr, PFX "missing buttons\n");
if (ifds[1] < 0)
fprintf(stderr, PFX "missing keypad\n");
- init_done = 1;
+
+ return 0;
}
static const struct {
struct input_event ev;
int i, ret;
- if (!init_done)
- init();
-
while (1)
{
ret = read(ifds[0], &ev, sizeof(ev));
--- /dev/null
+// 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);
+}
+
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;
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");
// vim:shiftwidth=2:expandtab
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
/* 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);
#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);
}
#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);
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
--- /dev/null
+#!/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
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)
#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)
{
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;
char *p, *pe;
int l;
+ if (!init_done)
+ fb_text_init();
+
if (fb_mem == NULL)
return;
}
}
-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;
FILE *fin, *fout;
int ret;
- fb_text_init();
-
if (argc < 2) {
err("usage: %s <script|program> [args]\n", argv[0]);
return 1;
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;
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:
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);