abdc5935be
It handles exit() properly, calling the handler also when the plugin returns normally (also it makes exit() more standard compliant while at it). It also holds PLUGIN_HEADER, so that it doesn't need to be in each plugin anymore. To work better together with callbacks passed to rb->default_event_handler_ex introduce exit_on_usb() which will call the exit handler before showing the usb screen and exit() after it. In most cases it was passed a callback which was manually called at all other return points. This can now be done via atexit(). In future plugin_crt0.c could also handle clearing bss, initializing iram and more. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27862 a1c6a512-1295-4272-9138-f99709370657
314 lines
7 KiB
C
314 lines
7 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2009 Torne Wuff
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#include "plugin.h"
|
|
#include "dumb_frotz.h"
|
|
#include "lib/pluginlib_exit.h"
|
|
#include "lib/pluginlib_actions.h"
|
|
|
|
|
|
|
|
extern int frotz_main(void);
|
|
extern bool hot_key_quit(void);
|
|
|
|
f_setup_t f_setup;
|
|
extern char save_name[], auxilary_name[], script_name[], command_name[];
|
|
extern int story_fp, sfp, rfp, pfp;
|
|
|
|
static struct viewport vp[NB_SCREENS];
|
|
|
|
static void atexit_cleanup(void);
|
|
|
|
enum plugin_status plugin_start(const void* parameter)
|
|
{
|
|
int i;
|
|
char* ext;
|
|
|
|
atexit(atexit_cleanup);
|
|
|
|
if (!parameter)
|
|
return PLUGIN_ERROR;
|
|
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
#if LCD_DEPTH > 1
|
|
rb->lcd_set_backdrop(NULL);
|
|
#endif
|
|
rb->lcd_clear_display();
|
|
|
|
FOR_NB_SCREENS(i)
|
|
rb->viewport_set_defaults(&vp[i], i);
|
|
|
|
story_name = parameter;
|
|
strcpy(save_name, story_name);
|
|
ext = rb->strrchr(save_name, '.');
|
|
if (ext)
|
|
*ext = '\0';
|
|
strcpy(auxilary_name, save_name);
|
|
strcpy(script_name, save_name);
|
|
strcpy(command_name, save_name);
|
|
rb->strlcat(save_name, ".sav", MAX_PATH);
|
|
rb->strlcat(auxilary_name, ".aux", MAX_PATH);
|
|
rb->strlcat(script_name, ".scr", MAX_PATH);
|
|
rb->strlcat(command_name, ".rec", MAX_PATH);
|
|
|
|
frotz_main();
|
|
|
|
return PLUGIN_OK;
|
|
}
|
|
|
|
void atexit_cleanup()
|
|
{
|
|
if (story_fp != -1)
|
|
fclose(story_fp);
|
|
if (sfp != -1)
|
|
fclose(sfp);
|
|
if (rfp != -1)
|
|
fclose(rfp);
|
|
if (pfp != -1)
|
|
fclose(pfp);
|
|
}
|
|
|
|
MENUITEM_STRINGLIST(ingame_menu, "Frotz", NULL, "Resume", "Undo", "Restart",
|
|
"Toggle input recording", "Play back input",
|
|
"Debug options", "Exit");
|
|
|
|
zchar menu(void)
|
|
{
|
|
switch (rb->do_menu(&ingame_menu, NULL, vp, true))
|
|
{
|
|
case 0:
|
|
default:
|
|
dumb_dump_screen();
|
|
return ZC_BAD;
|
|
case 1:
|
|
return ZC_HKEY_UNDO;
|
|
case 2:
|
|
return ZC_HKEY_RESTART;
|
|
case 3:
|
|
return ZC_HKEY_RECORD;
|
|
case 4:
|
|
return ZC_HKEY_PLAYBACK;
|
|
case 5:
|
|
return ZC_HKEY_DEBUG;
|
|
case 6:
|
|
return ZC_HKEY_QUIT;
|
|
}
|
|
}
|
|
|
|
const struct button_mapping* plugin_contexts[]={pla_main_ctx};
|
|
|
|
void wait_for_key()
|
|
{
|
|
int action;
|
|
|
|
dumb_show_screen(false);
|
|
|
|
for (;;)
|
|
{
|
|
action = pluginlib_getaction(TIMEOUT_BLOCK, plugin_contexts,
|
|
ARRAYLEN(plugin_contexts));
|
|
switch (action)
|
|
{
|
|
case PLA_EXIT:
|
|
hot_key_quit();
|
|
break;
|
|
|
|
case PLA_SELECT:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
zchar do_input(int timeout, bool show_cursor)
|
|
{
|
|
int action;
|
|
long timeout_at;
|
|
zchar menu_ret;
|
|
|
|
dumb_show_screen(show_cursor);
|
|
|
|
/* Convert timeout (tenths of a second) to ticks */
|
|
if (timeout > 0)
|
|
timeout = (timeout * HZ) / 10;
|
|
else
|
|
timeout = TIMEOUT_BLOCK;
|
|
|
|
timeout_at = *rb->current_tick + timeout;
|
|
|
|
for (;;)
|
|
{
|
|
action = pluginlib_getaction(timeout, plugin_contexts,
|
|
ARRAYLEN(plugin_contexts));
|
|
switch (action)
|
|
{
|
|
case PLA_EXIT:
|
|
return ZC_HKEY_QUIT;
|
|
|
|
case PLA_CANCEL:
|
|
menu_ret = menu();
|
|
if (menu_ret != ZC_BAD)
|
|
return menu_ret;
|
|
timeout_at = *rb->current_tick + timeout;
|
|
break;
|
|
|
|
case PLA_SELECT:
|
|
return ZC_RETURN;
|
|
|
|
case PLA_DOWN:
|
|
return ZC_BAD;
|
|
|
|
default:
|
|
if (timeout != TIMEOUT_BLOCK &&
|
|
!TIME_BEFORE(*rb->current_tick, timeout_at))
|
|
return ZC_TIME_OUT;
|
|
}
|
|
}
|
|
}
|
|
|
|
zchar os_read_key(int timeout, bool show_cursor)
|
|
{
|
|
int r;
|
|
char inputbuf[5];
|
|
short key;
|
|
zchar zkey;
|
|
|
|
for(;;)
|
|
{
|
|
zkey = do_input(timeout, show_cursor);
|
|
if (zkey != ZC_BAD)
|
|
return zkey;
|
|
|
|
inputbuf[0] = '\0';
|
|
r = rb->kbd_input(inputbuf, 5);
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
dumb_dump_screen();
|
|
if (!r)
|
|
{
|
|
rb->utf8decode(inputbuf, &key);
|
|
if (key > 0 && key < 256)
|
|
return (zchar)key;
|
|
}
|
|
}
|
|
}
|
|
|
|
zchar os_read_line(int max, zchar *buf, int timeout, int width, int continued)
|
|
{
|
|
(void)continued;
|
|
int r;
|
|
char inputbuf[256];
|
|
const char *in;
|
|
char *out;
|
|
short key;
|
|
zchar zkey;
|
|
|
|
for(;;)
|
|
{
|
|
zkey = do_input(timeout, true);
|
|
if (zkey != ZC_BAD)
|
|
return zkey;
|
|
|
|
if (max > width)
|
|
max = width;
|
|
strcpy(inputbuf, buf);
|
|
r = rb->kbd_input(inputbuf, 256);
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
dumb_dump_screen();
|
|
if (!r)
|
|
{
|
|
in = inputbuf;
|
|
out = buf;
|
|
while (*in && max)
|
|
{
|
|
in = rb->utf8decode(in, &key);
|
|
if (key > 0 && key < 256)
|
|
{
|
|
*out++ = key;
|
|
max--;
|
|
}
|
|
}
|
|
*out = '\0';
|
|
os_display_string(buf);
|
|
return ZC_RETURN;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool read_yes_or_no(const char *s)
|
|
{
|
|
char message_line[50];
|
|
const char *message_lines[] = {message_line};
|
|
const struct text_message message = {message_lines, 1};
|
|
|
|
rb->strlcpy(message_line, s, 49);
|
|
rb->strcat(message_line, "?");
|
|
|
|
if (rb->gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
zchar os_read_mouse(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int os_read_file_name(char *file_name, const char *default_name, int flag)
|
|
{
|
|
(void)flag;
|
|
strcpy(file_name, default_name);
|
|
return TRUE;
|
|
}
|
|
|
|
void os_beep(int volume)
|
|
{
|
|
rb->splashf(HZ/2, "[%s-PITCHED BEEP]", (volume==1) ? "HIGH" : "LOW");
|
|
}
|
|
|
|
static unsigned char unget_buf;
|
|
static int unget_file;
|
|
|
|
int frotz_ungetc(int c, int f)
|
|
{
|
|
unget_file = f;
|
|
unget_buf = c;
|
|
return c;
|
|
}
|
|
|
|
int frotz_fgetc(int f)
|
|
{
|
|
unsigned char cb;
|
|
if (unget_file == f)
|
|
{
|
|
unget_file = -1;
|
|
return unget_buf;
|
|
}
|
|
if (rb->read(f, &cb, 1) != 1)
|
|
return EOF;
|
|
return cb;
|
|
}
|
|
|
|
int frotz_fputc(int c, int f)
|
|
{
|
|
unsigned char cb = c;
|
|
if (rb->write(f, &cb, 1) != 1)
|
|
return EOF;
|
|
return cb;
|
|
}
|