#include "warm.h"
static volatile unsigned short *memregs;
-static volatile unsigned long *memregl;
+static volatile unsigned int *memregl;
int memdev = -1;
#define FB_BUF_COUNT 4
fprintf(stderr, "could not make fb buferable.\n");
}
- printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]);
+ // printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]);
for (i = 1; i < FB_BUF_COUNT; i++)
{
fb_paddr[i] = fb_paddr[i-1] + 320*240*2;
gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2;
- printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]);
+ // printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]);
}
fb_work_buf = 0;
g_screen_ptr = gp2x_screens[0];
void vout_gp2x_finish(void)
{
- memregl[0x406C>>2] = fb_paddr[0];
- memregl[0x4058>>2] |= 0x10;
- close(fbdev);
+ if (memregl != NULL) {
+ if (memregl[0x4058>>2] & 0x10)
+ usleep(100000);
+ if (memregl[0x4058>>2] & 0x10)
+ printf("MLCCONTROL1 dirty? %08x %08x\n",
+ memregl[0x406C>>2], memregl[0x4058>>2]);
+
+ memregl[0x406C>>2] = fb_paddr[0];
+ memregl[0x4058>>2] |= 0x10;
+ munmap((void *)memregs, 0x20000);
+ memregs = NULL;
+ memregl = NULL;
+ }
- munmap((void *)memregs, 0x20000);
+ close(fbdev);
close(memdev);
warm_finish();
return p;
}
+static void fb_text_exit(void)
+{
+ if (!init_done)
+ return;
+
+ host_video_finish();
+ init_done = 0;
+}
+
static void fb_text_init(void)
{
int ret = host_video_init(&fb_stride, 1);
fb_x = 4;
fb_y = 4;
init_done = 1;
+ atexit(fb_text_exit);
}
static void fb_syms_out(void *fbi, int x, int y, int dotsz, int stride, const char *text, int count)
fb_text_out(buff);
}
-#define msg(fmt, ...) fbprintf(0, fmt, #__VA_ARGS__)
-#define err(fmt, ...) fbprintf(1, fmt, #__VA_ARGS__)
+#define msg(fmt, ...) fbprintf(0, fmt, ##__VA_ARGS__)
+#define err(fmt, ...) fbprintf(1, fmt, ##__VA_ARGS__)
static int id_elf(const char *fname)
{
return ret;
}
-static void dump_args(FILE *fout, int argc, char * const argv[])
+static void dump_args(FILE *fout, char * const argv[])
{
const char *p;
int i;
- for (i = 0; i < argc; i++) {
+ for (i = 0; argv[i] != NULL; i++) {
if (i != 0)
fputc(' ', fout);
fputc('"', fout);
{
static const char out_script[] = "/tmp/ginge_conv.sh";
char root_path[512], cwd[512];
+ char **argv_app = NULL;
int have_cramfs = 0;
int rerun_gp2xmenu = 1;
+ int quit_if_no_app = 0;
FILE *fin, *fout;
- int ret;
+ int i, ret;
+
+ for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1] == '-'; i++) {
+ if (strcmp(argv[i], "--cleanup") == 0) {
+ // as loader may crash eny time, restore screen for the menu
+ host_video_init(NULL, 1);
+ host_video_finish();
+ quit_if_no_app = 1;
+ continue;
+ }
+ if (strcmp(argv[i], "--nomenu") == 0) {
+ rerun_gp2xmenu = 0;
+ continue;
+ }
+ if (strcmp(argv[i], "--") == 0) {
+ i++;
+ break;
+ }
- if (argc < 2) {
- err("usage: %s <script|program> [args]\n", argv[0]);
- return 1;
+ fprintf(stderr, PFX "ignoring unknown option \"%s\"\n", argv[i]);
}
- if (strcmp(argv[1], "--cleanup") == 0) {
- // as loader may crash eny time, restore screen for them menu
- host_video_init(NULL, 0);
- host_video_finish();
- return 0;
+ if (argc <= i) {
+ if (quit_if_no_app)
+ return 0;
+ err("usage: %s [opts] <script|program> [args]\n", argv[0]);
+ err(" --cleanup - restore framebuffer state\n");
+ err(" --nomenu - don't run menu on exit\n");
+ return 1;
}
+ argv_app = &argv[i];
if (getcwd(cwd, sizeof(cwd)) == NULL) {
err(PFX "failed to get cwd\n");
fprintf(fout, "#!/bin/sh\n");
- ret = id_elf(argv[1]);
+ ret = id_elf(argv_app[0]);
if (ret == 1 || ret == 2) {
- if (cmd_in_blacklist(argv[1])) {
- fprintf(stderr, "blacklisted: %s\n", argv[1]);
+ if (cmd_in_blacklist(argv_app[0])) {
+ fprintf(stderr, "blacklisted: %s\n", argv_app[0]);
goto no_in_script;
}
}
case 1:
fprintf(fout, WRAP_APP "%s%s ", root_path, LOADER_STATIC);
- dump_args(fout, argc - 1, &argv[1]);
+ dump_args(fout, argv_app);
fprintf(fout, "\n");
goto no_in_script;
case 2:
fprintf(fout, WRAP_APP "%s%s \"%s\" ", root_path, LOADER_DYNAMIC, root_path);
- dump_args(fout, argc - 1, &argv[1]);
+ dump_args(fout, argv_app);
fprintf(fout, "\n");
goto no_in_script;
}
// assume script
- fin = fopen(argv[1], "r");
+ fin = fopen(argv_app[0], "r");
if (fin == NULL)
return 1;
no_in_script:
#ifdef WIZ
fprintf(fout, "sync\n");
+ // since we don't know if loader manages to do proper cleanup,
+ // need to wait for it's threads to die
+ fprintf(fout, "sleep 1\n");
fprintf(fout, "%sginge_prep --cleanup\n", root_path);
#endif
if (rerun_gp2xmenu) {
system("echo ---; cat /tmp/ginge_conv.sh; echo ---");
chmod(out_script, S_IRWXU|S_IRWXG|S_IRWXO);
chdir(cwd);
+ fb_text_exit();
execlp(out_script, out_script, NULL);
perror("run out_script");
\r
GINGE - Ginge Is Not GP2X Emulator\r
-release 1\r
+release 2\r
\r
(C) notaz, 2010\r
http://notaz.gp2x.de/\r
it does is running ginge_prep on GP2X .gpe program, ginge_prep handles the rest.\r
\r
\r
+Changelog\r
+---------\r
+\r
+r2\r
+* improved exit handling\r
+* Wiz: should now return to Wiz menu after gp2xmenu exit\r
+\r
+r1 - initial release\r
++ icons provided by Inder\r
+\r
+\r
License\r
-------\r
\r
\r
Ginge may come with some libraries. Those libraries are unmodified copies\r
of ones found in root filesystems in GP2X and Wiz and are included to more\r
-accurately reproduce environment on GP2X. Their source code may or may not be\r
-available, I do not have it nor did I use it.\r
+accurately reproduce environment found on GP2X. Their source code may or may\r
+not be available, I did not I use it, but whatever I found is mirrored here:\r
+http://notaz.gp2x.de/downloads/gp2x/src/410_all/\r
\r
Remaining portion is released under custom closed source license. It is not\r
derived from gp2xmenu and is completely standalone, the menu is only included\r
* The program in any of it's forms is not sold or used as part of any\r
commercial package, including pre-installed or included in any kind of\r
portable device.\r
- * It is not bundled or distributed with any GP2X program without respective\r
+ * It is not bundled and distributed with any GP2X program without respective\r
program's author's permission.\r
\r
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r