diff --git a/gp2x/Makefile b/gp2x/Makefile index 94eb604..376970b 100644 --- a/gp2x/Makefile +++ b/gp2x/Makefile @@ -10,8 +10,12 @@ STRIP = $(PREFIX)/bin/arm-open2x-linux-strip OBJS = main.o cpu.o memory.u video.o input.o sound.o gp2x.o gui.o \ cheats.o zip.o cpu_threaded.z arm_stub.o video_blend.o \ - warm.o sys_cacheflush.o upscale_aspect.o -BIN = gpsp.gpe + warm.o upscale_aspect.o +ifeq ($(WIZ),1) +BIN = gpsp_wiz +else +BIN = gpsp_gp2x +endif # Platform specific definitions @@ -31,9 +35,6 @@ ifneq ($(WIZ),1) LIBS += -static endif -#CFLAGS += -ggdb -#LIBS += -ggdb - # Compilation: .SUFFIXES: .c @@ -54,7 +55,7 @@ endif $(CC) $(ASFLAGS) $(INCLUDES) -c -o $@ $< all: $(OBJS) - $(CC) $(OBJS) $(LIBS) -o $(BIN) + $(CC) $(OBJS) $(LIBS) -o $(BIN) $(STRIP) $(BIN) clean: diff --git a/gp2x/sys_cacheflush.S b/gp2x/sys_cacheflush.S deleted file mode 100644 index d26f81a..0000000 --- a/gp2x/sys_cacheflush.S +++ /dev/null @@ -1,29 +0,0 @@ -@ vim:filetype=armasm -#include - - -.global sys_cacheflush @ void *start_addr, void *end_addr - -sys_cacheflush: - mov r2, #0 -#ifdef __ARM_EABI__ - /* EABI version */ - str r7, [sp, #-4]! - mov r7, #(__ARM_NR_cacheflush & 0xff) - orr r7, r7, #(__ARM_NR_cacheflush & 0x00ff00) - orr r7, r7, #(__ARM_NR_cacheflush & 0xff0000) - swi 0 - ldr r7, [sp], #4 -#else - /* OABI */ - swi __ARM_NR_cacheflush -#endif - bx lr - -.global spend_cycles -spend_cycles: - mov r0,r0,lsr #2 - 0:subs r0, r0, #1 - bne 0b - bx lr - diff --git a/gp2x/sys_cacheflush.h b/gp2x/sys_cacheflush.h deleted file mode 100644 index 27f3c4c..0000000 --- a/gp2x/sys_cacheflush.h +++ /dev/null @@ -1,3 +0,0 @@ - -void sys_cacheflush(void *start_addr, void *end_addr); - diff --git a/gp2x/warm.c b/gp2x/warm.c index 197df0f..fd3fb4c 100644 --- a/gp2x/warm.c +++ b/gp2x/warm.c @@ -36,18 +36,77 @@ #include #include #include +#include #include #define WARM_CODE #include "warm.h" -#include "sys_cacheflush.h" + +extern long init_module(void *, unsigned long, const char *); /* provided by glibc */ 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 +} + +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; +} int warm_init(void) { struct utsname unm; - char buff[128]; + char buff1[32], buff2[128]; + int ret; warm_fd = open("/proc/warm", O_RDWR); if (warm_fd >= 0) @@ -55,23 +114,56 @@ int warm_init(void) memset(&unm, 0, sizeof(unm)); uname(&unm); - snprintf(buff, sizeof(buff), "/sbin/insmod warm_%s.ko", unm.release); + + 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'); + + 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 */ - system(buff); + 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) { - if (warm_fd >= 0) - close(warm_fd); - system("rmmod warm"); + char cmd[64]; + + 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(cmd, sizeof(cmd), "/sbin/rmmod warm_%s", unm.release); + } + else + strcpy(cmd, "/sbin/rmmod warm"); + + system(cmd); } int warm_cache_op_range(int op, void *addr, unsigned long size) @@ -80,6 +172,7 @@ int warm_cache_op_range(int op, void *addr, unsigned long size) 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; } @@ -99,7 +192,7 @@ int warm_cache_op_range(int op, void *addr, unsigned long size) int warm_cache_op_all(int op) { - return warm_cache_op_range(op, NULL, (size_t)-1); + 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)