From dc90c02d39fc8968d2078512e228d99e7c553267 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 21 Jul 2010 19:36:07 +0300 Subject: [PATCH] wip, most of my SD static bins work --- loader/emu.c | 153 +++++++++++++++++++++++++++++++++++++++--- loader/header.h | 28 +++++++- loader/patches.c | 86 ++++++++++++++++++------ loader/tools/mcut.c | 6 ++ loader/tools/static.c | 4 ++ 5 files changed, 249 insertions(+), 28 deletions(-) diff --git a/loader/emu.c b/loader/emu.c index 389103e..3db8053 100644 --- a/loader/emu.c +++ b/loader/emu.c @@ -103,7 +103,7 @@ static struct { u16 host_pal[256]; u32 old_mlc_stl_adr; u32 btn_state; // as seen through /dev/GPIO - u16 dirty_pal:1; + u32 dirty_pal:1; } mmsp2; static u16 *host_screen; @@ -189,7 +189,7 @@ static void blitter_do(void) u8 *dst, *dste, *src = NULL, *srce = NULL; int w, h, sstrd, dstrd; int to_screen = 0; - u32 addr; + u32 bpp, addr; w = blitter.size & 0x7ff; h = (blitter.size >> 16) & 0x7ff; @@ -199,8 +199,13 @@ static void blitter_do(void) // XXX: need to confirm this.. addr = (blitter.dstaddr & ~3) | ((blitter.dstctrl & 0x1f) >> 3); + // use dst bpp.. How does it do blits with different src bpp? + bpp = (blitter.dstctrl & 0x20) ? 16 : 8; + // maybe the screen? - if (w == 320 && h == 240 && mmsp2.mlc_stl_adr <= addr && addr < mmsp2.mlc_stl_adr + 320*240*2) + if (((w == 320 && h == 240) || // blit whole screen + (w * h >= 320*240/2)) && // ..or at least half of the area + mmsp2.mlc_stl_adr <= addr && addr < mmsp2.mlc_stl_adr + 320*240*2) to_screen = 1; dst = uppermem_lookup(addr, &dste); @@ -222,6 +227,9 @@ static void blitter_do(void) } } + if (dst == NULL) + goto bad_blit; + if (dst + dstrd * h > dste) { err("blit %08x->%08x %dx%d did not fit dst\n", blitter.srcaddr, blitter.dstaddr, w, h); @@ -230,21 +238,27 @@ static void blitter_do(void) if (src != NULL) { // copy - if (blitter.ctrl & CTRL_TRANSPARENCYENB) { + if (bpp == 16 && (blitter.ctrl & CTRL_TRANSPARENCYENB)) { u32 trc = blitter.ctrl >> 16; for (; h > 0; h--, dst += dstrd, src += sstrd) blt_tr(dst, src, trc, w); } else { for (; h > 0; h--, dst += dstrd, src += sstrd) - memcpy(dst, src, w * 2); + memcpy(dst, src, w * bpp / 8); } } else { // fill. Assume the pattern is cleared and bg color is used u32 bgc = blitter.patbackcolor & 0xffff; - for (; h > 0; h--, dst += dstrd) - memset16(dst, bgc, w); + if (bpp == 16) { + for (; h > 0; h--, dst += dstrd) + memset16(dst, bgc, w); + } + else { + for (; h > 0; h--, dst += dstrd) + memset(dst, bgc, w); // bgc? + } } if (to_screen) @@ -342,6 +356,7 @@ static void *fb_sync_thread(void *arg) ret = pthread_mutex_lock(&fb_mutex); wait_ret = pthread_cond_timedwait(&fb_cond, &fb_mutex, &ts); ret |= pthread_mutex_unlock(&fb_mutex); + if (ret != 0) { err("fb_thread: mutex error: %d\n", ret); sleep(1); @@ -468,6 +483,14 @@ out: static u32 xread32(u32 a) { u32 d = 0; + if ((a & 0xfff00000) == 0x7f000000) { + u32 a_ = a & 0xffff; + switch (a_) { + case 0x0a00: // TCOUNT, 1/7372800s + // TODO + break; + } + } if ((a & 0xfff00000) == 0x7f100000) { u32 *bl = &blitter.dstctrl; u32 a_ = a & 0xfff; @@ -843,7 +866,12 @@ int emu_read_gpiodev(void *buf, int count) return 4; } -void *emu_mmap_dev(unsigned int length, int prot, int flags, unsigned int offset) +struct dev_fd_t emu_interesting_fds[] = { + [IFD_SOUND] = { "/dev/dsp", -1 }, + { NULL, 0 }, +}; + +static void *emu_mmap_dev(unsigned int length, int prot, int flags, unsigned int offset) { struct uppermem_block *umem; char name[32]; @@ -887,6 +915,7 @@ void *emu_mmap_dev(unsigned int length, int prot, int flags, unsigned int offset err("failed, giving up\n"); close(fd); free(umem); + errno = EINVAL; return MAP_FAILED; } @@ -897,3 +926,111 @@ done: return umem->mem; } +void *emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int offset) +{ + if (fd == FAKEDEV_MEM) + return emu_mmap_dev(length, prot, flags, offset); + + if (fd == FAKEDEV_FB0) + return emu_mmap_dev(length, prot, flags, offset + 0x03101000); + + if (fd == FAKEDEV_FB1) + return emu_mmap_dev(length, prot, flags, offset + 0x03381000); + + err("bad/ni mmap(?, %d, %x, %x, %d, %08x)", length, prot, flags, fd, offset); + errno = EINVAL; + return MAP_FAILED; +} + +#include +#include + +static int emu_sound_ioctl(int fd, int request, void *argp) +{ + int *arg = argp; + +#if 0 + dbg("snd ioctl(%d, %08x, %p)", fd, request, argp); + if (arg != NULL) + dbg_c(" [%d]", *arg); + dbg_c("\n"); +#endif + + /* People set strange frag settings on GP2X, which even manage + * to break audio on pandora (causes writes to fail). + * Catch this and set to something that works. */ + if (request == SNDCTL_DSP_SPEED) { + int ret, bsize, frag; + + // ~4ms. gpSP wants small buffers or else it stutters + // because of it's audio thread sync stuff + bsize = *arg / 250 * 4; + for (frag = 0; bsize; bsize >>= 1, frag++) + ; + + frag |= 16 << 16; // fragment count + ret = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag); + if (ret != 0) { + err("snd ioctl SETFRAGMENT %08x: ", frag); + perror(NULL); + } + } + else if (request == SNDCTL_DSP_SETFRAGMENT) + return 0; + + return ioctl(fd, request, argp); +} + +#include + +int emu_do_ioctl(int fd, int request, void *argp) +{ + if (fd == emu_interesting_fds[IFD_SOUND].fd) + return emu_sound_ioctl(fd, request, argp); + + if (argp == NULL) + goto fail; + + if (fd == FAKEDEV_FB0 || fd == FAKEDEV_FB1) { + switch (request) { + case FBIOGET_FSCREENINFO: { + struct fb_fix_screeninfo *fix = argp; + + memset(fix, 0, sizeof(*fix)); + strcpy(fix->id, "mmsp2_RGB0"); + fix->type = FB_TYPE_PACKED_PIXELS; + fix->accel = FB_ACCEL_NONE; + fix->smem_start = (fd == FAKEDEV_FB0) ? 0x03101000 : 0x03381000; + fix->smem_len = 320*240*2; + return 0; + } + case FBIOGET_VSCREENINFO: { + struct fb_var_screeninfo *var = argp; + static const struct fb_bitfield fbb_red = { offset: 0, length: 4, }; + static const struct fb_bitfield fbb_green = { offset: 0, length: 4, }; + static const struct fb_bitfield fbb_blue = { offset: 0, length: 4, }; + + memset(var, 0, sizeof(*var)); + var->activate = FB_ACTIVATE_NOW; + var->xres = + var->xres_virtual = 320; + var->yres = + var->yres_virtual = 240; + var->width = + var->height = -1; + var->vmode = FB_VMODE_NONINTERLACED; + var->bits_per_pixel = 16; + var->red = fbb_red; + var->green = fbb_green; + var->blue = fbb_blue; + return 0; + } + } + } + +fail: + err("bad/ni ioctl(%d, %08x, %p)", fd, request, argp); + errno = EINVAL; + return -1; +} + diff --git a/loader/header.h b/loader/header.h index 8197664..f2f6a45 100644 --- a/loader/header.h +++ b/loader/header.h @@ -3,13 +3,39 @@ #define PFX "ginge: " #define err(f, ...) fprintf(stderr, PFX f, ##__VA_ARGS__) #define log(f, ...) fprintf(stdout, PFX f, ##__VA_ARGS__) +#if 1 +#define dbg log +#define dbg_c printf +#else +#define dbg(...) +#define dbg_c(...) +#endif void do_entry(unsigned long entry, void *stack_frame, int stack_frame_cnt, void *exitf); +struct dev_fd_t { + const char *name; + int fd; +}; +extern struct dev_fd_t emu_interesting_fds[]; +enum { + IFD_SOUND = 0, +}; + +enum { + FAKEDEV_MEM = 10001, + FAKEDEV_GPIO, + FAKEDEV_FB0, + FAKEDEV_FB1, + FAKEDEV_MMUHACK, + FAKEDEV_FD_BOUNDARY, +}; + void do_patches(void *ptr, unsigned int size); void emu_init(void *map_bottom); -void *emu_mmap_dev(unsigned int length, int prot, int flags, unsigned int offset); +void *emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int offset); +int emu_do_ioctl(int fd, int request, void *argp); int emu_read_gpiodev(void *buf, int count); int host_read_btns(void); diff --git a/loader/patches.c b/loader/patches.c index 402de84..f7e0b11 100644 --- a/loader/patches.c +++ b/loader/patches.c @@ -6,42 +6,57 @@ #include #include #include +#include #include "header.h" #include "sys_cacheflush.h" +#if 0 +#define strace printf +#else #define strace(...) -//#define strace printf +#endif + +// note: first mask must be always full for search algo +static const unsigned int sig_mask_all[] = { + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +}; static const unsigned int sig_open[] = { 0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900005 }; +#define sig_mask_open sig_mask_all static const unsigned int sig_mmap[] = { 0xe92d000f, 0xe1a0000d, 0xef90005a, 0xe28dd010 }; +#define sig_mask_mmap sig_mask_all static const unsigned int sig_mmap_[] = { 0xe52d5004, 0xe59d5008, 0xe52d4004, 0xe59d4008, 0xe1b0ca05, 0x1a000006, 0xe1a05625, 0xef9000c0 }; +#define sig_mask_mmap_ sig_mask_all static const unsigned int sig_read[] = { 0xe59fc080, 0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900003 }; +#define sig_mask_read sig_mask_all -enum { - FAKEDEV_MEM = 10001, - FAKEDEV_GPIO, - FAKEDEV_FB0, - FAKEDEV_FB1, - FAKEDEV_MMUHACK, +static const unsigned int sig_ioctl[] = { + 0xef900036, 0xe3700a01, 0x312fff1e }; +#define sig_mask_ioctl sig_mask_all -static const struct { - const char *name; - int fd; -} takeover_devs[] = { +static const unsigned int sig_sigaction[] = { + 0xe59f300c, 0xe3530000, 0x0a000000, 0xea000000, 0xea000000 +}; +static const unsigned int sig_mask_sigaction[] = { + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000 +}; + +static const struct dev_fd_t takeover_devs[] = { { "/dev/mem", FAKEDEV_MEM }, { "/dev/GPIO", FAKEDEV_GPIO }, { "/dev/fb0", FAKEDEV_FB0 }, @@ -65,6 +80,15 @@ static int w_open(const char *pathname, int flags, mode_t mode) if (i == ARRAY_SIZE(takeover_devs)) ret = open(pathname, flags, mode); + if (ret >= 0) { + for (i = 0; emu_interesting_fds[i].name != NULL; i++) { + if (strcmp(pathname, emu_interesting_fds[i].name) == 0) { + emu_interesting_fds[i].fd = ret; + break; + } + } + } + strace("open(%s) = %d\n", pathname, ret); return ret; } @@ -72,10 +96,10 @@ static int w_open(const char *pathname, int flags, mode_t mode) static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { void *ret; - if (fd != FAKEDEV_MEM) - ret = mmap(addr, length, prot, flags, fd, offset); + if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) + ret = emu_do_mmap(length, prot, flags, fd, offset); else - ret = emu_mmap_dev(length, prot, flags, offset); + ret = mmap(addr, length, prot, flags, fd, offset); // threads are using heap before they mmap their stack // printf needs valid stack for pthtead/errno @@ -85,21 +109,42 @@ static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_ } #define w_mmap_ w_mmap -ssize_t w_read(int fd, void *buf, size_t count) +static ssize_t w_read(int fd, void *buf, size_t count) { ssize_t ret; if (fd != FAKEDEV_GPIO) return read(fd, buf, count); ret = emu_read_gpiodev(buf, count); - //printf("read(%d, %p, %d) = %d\n", fd, buf, count, ret); + //strace("read(%d, %p, %d) = %d\n", fd, buf, count, ret); return ret; } -#define PATCH(f) { sig_##f, ARRAY_SIZE(sig_##f), w_##f } +static int w_ioctl(int fd, int request, void *argp) +{ + int ret; + + if ((FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) || + fd == emu_interesting_fds[IFD_SOUND].fd) + ret = emu_do_ioctl(fd, request, argp); + else + ret = ioctl(fd, request, argp); + + strace("ioctl(%d, %08x, %p) = %d\n", fd, request, argp, ret); + return ret; +} + +static int w_sigaction(int signum, const void *act, void *oldact) +{ + strace("sigaction(%d, %p, %p) = %d\n", signum, act, oldact, 0); + return 0; +} + +#define PATCH(f) { sig_##f, sig_mask_##f, ARRAY_SIZE(sig_##f), w_##f } static const struct { const unsigned int *sig; + const unsigned int *sig_mask; size_t sig_cnt; void *func; } patches[] = { @@ -107,6 +152,8 @@ static const struct { PATCH(mmap), PATCH(mmap_), // mmap using mmap2 syscall PATCH(read), + PATCH(ioctl), + PATCH(sigaction), }; void do_patches(void *ptr, unsigned int size) @@ -115,6 +162,7 @@ void do_patches(void *ptr, unsigned int size) for (i = 0; i < ARRAY_SIZE(patches); i++) { const unsigned int *sig = patches[i].sig; + const unsigned int *sig_mask = patches[i].sig_mask; unsigned int *seg = (void *)(((long)ptr + 3) & ~3); unsigned int *seg_end = seg + size / 4; unsigned int sig0 = sig[0]; @@ -124,7 +172,7 @@ void do_patches(void *ptr, unsigned int size) continue; for (s = 1; s < patches[i].sig_cnt; s++) - if (seg[s] != sig[s]) + if ((seg[s] ^ sig[s]) & sig_mask[s]) break; if (s == patches[i].sig_cnt) @@ -133,7 +181,7 @@ void do_patches(void *ptr, unsigned int size) continue; found: - printf(" patch #%i @ %08x\n", i, (int)seg); + dbg(" patch #%i @ %08x\n", i, (int)seg); seg[0] = 0xe59ff000; // ldr pc, [pc] seg[1] = 0; seg[2] = (unsigned int)patches[i].func; diff --git a/loader/tools/mcut.c b/loader/tools/mcut.c index 98a2d0a..9d58ceb 100644 --- a/loader/tools/mcut.c +++ b/loader/tools/mcut.c @@ -5,6 +5,11 @@ int main(int argc, char *argv[]) FILE *fi; int c, t; + if (argc < 4) { + printf("usage:\n%s \n", argv[0]); + return 1; + } + fi = fopen(argv[1], "rb"); fseek(fi, strtoul(argv[2], NULL, 0), SEEK_SET); c = atoi(argv[3]); @@ -13,6 +18,7 @@ int main(int argc, char *argv[]) fread(&t, 1, 4, fi); printf("0x%08x, ", t); } + printf("\n"); return 0; } diff --git a/loader/tools/static.c b/loader/tools/static.c index edf7139..50013c7 100644 --- a/loader/tools/static.c +++ b/loader/tools/static.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include int main(int argc, char *argv[]) { @@ -23,6 +25,8 @@ int main(int argc, char *argv[]) } memregs = mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + ioctl(-1, 0); + signal(7, SIG_DFL); for (i = 0; i < 2; i++) printf("%02x %04x %08x\n", ((char *)memregs)[0x2011], -- 2.39.5