1
0
Fork 0
forked from len0rd/rockbox
foxbox/apps/plugins/doom/rockdoom.c
William Wilgus 7100090f99 Remove NVRAM infavor of a separate cfg file
remove nvram and use the existing settings framework for it

add a crc check to the user_settings data to see if we need to save
the user setting file or if we can just save the status file (resume.cfg)

move volume to the system_status struct so we don't write the whole settings file
over volume changes

allow user to still export volume with save sound settings

allow the user to also export pitch and speed

name the file .resume.cfg

Rename all the SYSTEM_STATUS save file variables to TLAs to save space and
discourage tinkering

Cleanup DEBUG_AVAIL_SETTINGS output

when saving user_settings it calls status_save as well this cause the resume
file to be written twice. instead remove the callback for status_save
when setting_save is called

remove header text when saving .resume.cfg

convert status_save() to status_save(bool force)
add SYSTEM_STATUS_UPDATE_TICKS

for ATA device set this to 5 minutes
since we arlready wait for the disk to be up before saving
we don't want to miss our window

for all other every 15 minutes

that way if the battery is too low by the time shutdown comes around you
don't lose much progress

Change-Id: I27214ffd6e5d5494ee5ca83b14f04a41ba426ad7
2025-01-21 00:04:32 -05:00

765 lines
18 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2005 Karl Kurbjun
*
* 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.
*
* H300 Port by Karl Kurbjun
* IPod port by Dave Chapman and Paul Louden
* Additional code contributed by Thom Johansen
* Based off work by: Digita Doom, IDoom, Prboom, lSDLDoom, LxDoom,
* MBF, Boom, DosDoom,
* and of course Original Doom by ID Software
* See: http://prboom.sourceforge.net/about.html for the history
*
*
****************************************************************************/
#include "d_main.h"
#include "doomdef.h"
#include "settings.h"
#include "m_fixed.h"
#include "m_argv.h"
#include "m_misc.h"
#include "g_game.h"
#include "rockmacros.h"
#include "doomstat.h"
#include "i_system.h"
#include "hu_stuff.h"
#include "st_stuff.h"
#include "lib/helper.h"
extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
int filearray[9];
int fpoint=1; // save 0 for closing
int fileexists(const char * fname)
{
int fd;
fd = open(fname,O_RDONLY);
if (fd>=0)
{
close(fd);
return 0;
}
return -1;
}
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
int my_open(const char *file, int flags, ...)
{
if(fpoint==8)
return -1;
#undef open
if (flags & O_CREAT)
{
va_list ap;
va_start(ap, flags);
filearray[fpoint]=rb->open(file, flags, va_arg(ap, unsigned int));
va_end(ap);
}
else
filearray[fpoint]=rb->open(file, flags);
if(filearray[fpoint]<0)
return filearray[fpoint];
fpoint++;
return filearray[fpoint-1];
}
int my_close(int id)
{
int i=0;
if(id<0)
return id;
while(filearray[i]!=id && i<8)
i++;
if(i==8)
{
printf("A requested FID did not exist!!!!");
return -9;
}
#undef close
rb->close(id);
for(; i<fpoint-1; i++)
filearray[i]=filearray[i+1];
fpoint--;
return 0;
}
#endif
#define MAXARGVS 100
bool noprintf=0; // Variable disables printf lcd updates to protect grayscale lib/direct lcd updates
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
// Here is a hacked up printf command to get the output from the game.
int printf(const char *fmt, ...)
{
static int p_xtpt;
char p_buf[50];
rb->yield();
va_list ap;
va_start(ap, fmt);
vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
va_end(ap);
rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf);
if (!noprintf)
rb->lcd_update();
p_xtpt+=8;
if(p_xtpt>LCD_HEIGHT-8)
{
p_xtpt=0;
if (!noprintf)
rb->lcd_clear_display();
}
return 1;
}
#endif
char *my_strtok( char * s, const char * delim )
{
register char *spanp;
register int c, sc;
char *tok;
static char *lasts;
if (s == NULL && (s = lasts) == NULL)
return (NULL);
/*
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
*/
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
if (c == 0) { /* no non-delimiter characters */
lasts = NULL;
return (NULL);
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
lasts = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
struct argvlist
{
int timedemo; // 1 says there's a timedemo
int demonum;
int addonnum;
} argvlist;
const unsigned char versions_builtin[7][20] =
{
"Doom Shareware",
"Doom Registered",
"Ultimate Doom",
"Doom 2",
"Freedoom",
"Plutonia",
"TNT"
};
const unsigned char wads_builtin[7][30] =
{
GAMEBASE"doom1.wad",
GAMEBASE"doom.wad",
GAMEBASE"doomu.wad",
GAMEBASE"doom2.wad",
GAMEBASE"doomf.wad",
GAMEBASE"plutonia.wad",
GAMEBASE"tnt.wad"
};
int namemap[7];
static char **addons;
static char **demolmp;
char addon[200];
// This sets up the base game and builds up myargv/c
bool Dhandle_ver (int dver)
{
switch (dver) {
case 0: /* Doom Shareware */
gamemode = shareware;
gamemission = doom;
D_AddFile(wads_builtin[0],source_iwad);
break;
case 1: /* Doom registered */
gamemode = registered;
gamemission = doom;
D_AddFile(wads_builtin[1],source_iwad);
break;
case 2: /* Ultimate Doom */
gamemode = retail;
gamemission = doom;
D_AddFile(wads_builtin[2],source_iwad);
break;
case 3: /* Doom2 */
gamemode = commercial;
gamemission = doom2;
D_AddFile(wads_builtin[3],source_iwad);
break;
case 4: /* Doom2f */
gamemode = commercial;
gamemission = doom2;
D_AddFile(wads_builtin[4],source_iwad);
break;
case 5: /* Plutonia */
gamemode = commercial;
gamemission = pack_plut;
D_AddFile(wads_builtin[5],source_iwad);
break;
case 6: /* TNT */
gamemode = commercial;
gamemission = pack_tnt;
D_AddFile(wads_builtin[6],source_iwad);
break;
default:
gamemission = none;
return 0;
}
// Start adding to myargv
if(argvlist.timedemo && (gamemode == shareware))
{
singletics = true;
timingdemo = true; // show stats after quit
G_DeferedPlayDemo("demo3");
singledemo = true; // quit after one demo
}
if(argvlist.addonnum)
{
snprintf(addon,sizeof(addon),"%s%s", GAMEBASE"addons/", addons[argvlist.addonnum]);
D_AddFile(addon,source_pwad);
modifiedgame = true;
}
if(argvlist.demonum)
{
snprintf(addon, sizeof(addon),"%s%s", GAMEBASE"demos/", demolmp[argvlist.demonum]);
D_AddFile(addon, source_lmp);
G_DeferedPlayDemo(addon);
singledemo = true; // quit after one demo
}
return 1;
}
// This function builds up the basegame list for use in the options selection
// it also sets the defaults for the argvlist
// Now checking for rcokdoom.wad based on prboom.wad
int Dbuild_base (struct opt_items *names)
{
if ( fileexists(GAMEBASE"rockdoom.wad") )
return 0;
D_AddFile (GAMEBASE"rockdoom.wad", source_pwad);
int i=0, j;
/* Doom Shareware */
/* Doom registered */
/* Ultimate Doom */
/* Doom2 */
/* Doom2f */
/* Plutonia */
/* TNT */
for(j=0;j<7;j++)
if ( !fileexists (wads_builtin[j]) )
{
names[i].string=versions_builtin[j];
names[i].voice_id=-1;
namemap[i]=j;
i++;
}
// Set argvlist defaults
argvlist.timedemo=0;
return i;
}
// This is a general function that takes in a menu_item structure and makes a list
// of files within it based on matching the string stringmatch to the files.
int Dbuild_filelistm(char ***names, char *firstentry, char *directory, char *stringmatch)
{
int i=0;
DIR *filedir;
struct dirent *dptr;
char *startpt;
char **temp;
filedir=rb->opendir(directory);
if(filedir==NULL)
{
temp=malloc(sizeof(char *));
temp[0]=firstentry;
*names=temp;
return 1;
}
// Get the total number of entries
while((dptr=rb->readdir(filedir)))
i++;
// Reset the directory
rb->closedir(filedir);
filedir=rb->opendir(directory);
i++;
temp=malloc(i*sizeof(char *));
temp[0]=firstentry;
i=1;
while((dptr=rb->readdir(filedir)))
{
if(rb->strcasestr(dptr->d_name, stringmatch))
{
startpt=malloc(strlen(dptr->d_name)*sizeof(char));
strcpy(startpt,dptr->d_name);
temp[i]=startpt;
i++;
}
}
rb->closedir(filedir);
*names=temp;
return i;
}
static int translatekey(int key) __attribute__ ((noinline));
// This key configuration code is not the cleanest or the most efficient, but it works
static int translatekey(int key)
{
if (key<31)
{
switch(key)
{
case 0:
return 0;
case 1:
return KEY_RIGHTARROW;
case 2:
return KEY_LEFTARROW;
case 3:
return KEY_UPARROW;
case 4:
return KEY_DOWNARROW;
case 5:
return KEY_ENTER;
case 6:
return KEY_RCTRL;
case 7:
return ' ';
case 8:
return KEY_ESCAPE;
case 9:
return 'w';
case 10:
return KEY_TAB;
default:
return 0;
}
}
else
{
switch(key)
{
case 0:
return 0;
case KEY_RIGHTARROW:
return 1;
case KEY_LEFTARROW:
return 2;
case KEY_UPARROW:
return 3;
case KEY_DOWNARROW:
return 4;
case KEY_ENTER:
return 5;
case KEY_RCTRL:
return 6;
case ' ':
return 7;
case KEY_ESCAPE:
return 8;
case 'w':
return 9;
case KEY_TAB:
return 10;
default:
return 0;
}
}
}
// I havn't added configurable keys for enter or escape because this requires some modification to
// m_menu.c which hasn't been done yet.
int Oset_keys()
{
int selected=0, result;
int menuquit=0;
static const struct opt_items doomkeys[] = {
{ "Unmapped", -1 },
{ "Key Right", -1 },
{ "Key Left", -1 },
{ "Key Up", -1 },
{ "Key Down", -1 },
{ "Key Select", -1 },
#if defined(TOSHIBA_GIGABEAT_F)
{ "Key A", -1 },
{ "Key Menu", -1 },
{ "Key Power", -1 },
{ "Key Volume Down", -1 },
{ "Key Volume Up", -1 },
#else
{ "Key Record", -1 },
{ "Key Mode", -1 },
{ "Key Off", -1 },
{ "Key On", -1 },
#endif
};
int *keys[]={
&key_right,
&key_left,
&key_up,
&key_down,
&key_fire,
&key_use,
&key_strafe,
&key_weapon,
&key_map
};
int numdoomkeys=sizeof(doomkeys) / sizeof(*doomkeys);
MENUITEM_STRINGLIST(menu, "Set Keys", NULL,
"Game Right", "Game Left", "Game Up", "Game Down",
"Game Shoot", "Game Open", "Game Strafe",
"Game Weapon", "Game Automap");
while(!menuquit)
{
result = rb->do_menu(&menu, &selected, NULL, false);
if(result<0)
menuquit=1;
else
{
*keys[result]=translatekey(*keys[result]);
rb->set_option(menu_[result], keys[result], RB_INT, doomkeys, numdoomkeys, NULL );
*keys[result]=translatekey(*keys[result]);
}
}
return (1);
}
extern int fake_contrast;
static bool Doptions()
{
static const struct opt_items onoff[2] = {
{ "Off", -1 },
{ "On", -1 },
};
int selected=0, result;
int menuquit=0;
MENUITEM_STRINGLIST(menu, "Options", NULL,
"Set Keys", "Sound", "Timedemo", "Player Bobbing",
"Weapon Recoil", "Translucency", "Fake Contrast",
"Always Run", "Headsup Display", "Statusbar Always Red",
#if(LCD_HEIGHT>LCD_WIDTH)
"Rotate Screen 90 deg",
#endif
);
void *options[]={
&enable_sound,
&argvlist.timedemo,
&default_player_bobbing,
&default_weapon_recoil,
&default_translucency,
&fake_contrast,
&autorun,
&hud_displayed,
&sts_always_red,
#if(LCD_HEIGHT>LCD_WIDTH)
&rotate_screen,
#endif
};
while(!menuquit)
{
result = rb->do_menu(&menu, &selected, NULL, false);
if(result==0)
Oset_keys();
else if (result > 0)
rb->set_option(menu_[result], options[result-1], RB_INT, onoff, 2, NULL );
else
menuquit=1;
}
return (1);
}
static const char* choice_get_name(int selected_item, void * data,
char * buffer, size_t buffer_len)
{
const char **names = (const char **) data;
(void) buffer;
(void) buffer_len;
return names[selected_item];
}
int list_action_callback(int action, struct gui_synclist *lists)
{
(void) lists;
if (action == ACTION_STD_OK)
return ACTION_STD_CANCEL;
return action;
}
bool menuchoice(char **names, int count, int *selected)
{
struct simplelist_info info;
rb->simplelist_info_init(&info, NULL, count, (void*)names);
info.selection = *selected;
info.get_name = choice_get_name;
info.action_callback = list_action_callback;
if(rb->simplelist_show_list(&info))
return true;
if(info.selection<count && info.selection>=0)
*selected = info.selection;
return false;
}
//
// Doom Menu
//
int doom_menu()
{
int selected=0, result;
int status;
int gamever;
bool menuquit=0;
static struct opt_items names[7];
MENUITEM_STRINGLIST(menu, "Doom Menu", NULL,
"Game", "Addons", "Demos",
"Options", "Play Game", "Quit");
if( (status=Dbuild_base(names)) == 0 ) // Build up the base wad files (select last added file)
{
rb->splash(HZ*2, "Missing Base WAD!");
return -2;
}
int numadd=Dbuild_filelistm(&addons, "No Addon", GAMEBASE"addons/", ".WAD" );
int numdemos=Dbuild_filelistm(&demolmp, "No Demo", GAMEBASE"demos/", ".LMP" );
argvlist.demonum=0;
argvlist.addonnum=0;
gamever=status-1;
/* Clean out the button Queue */
while (rb->button_get(false) != BUTTON_NONE)
rb->yield();
while(!menuquit)
{
result = rb->do_menu(&menu, &selected, NULL, false);
switch (result) {
case 0: /* Game picker */
rb->set_option("Game WAD", &gamever, RB_INT, names, status, NULL );
break;
case 1: /* Addon picker */
menuchoice(addons,numadd,&argvlist.addonnum);
break;
case 2: /* Demos */
menuchoice(demolmp,numdemos,&argvlist.demonum);
break;
case 3: /* Options */
Doptions();
break;
case 4: /* Play Game */
menuquit=1;
break;
case 5: /* Quit */
menuquit=1;
gamever=-1;
break;
default:
break;
}
}
return (gamever);
}
extern int systemvol;
/* this is the plugin entry point */
enum plugin_status plugin_start(const void* parameter)
{
/* Disable all talking before initializing IRAM */
rb->talk_disable(true);
(void)parameter;
doomexit=0;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true);
#endif
rb->lcd_setfont(FONT_SYSFIXED);
// We're using doom's memory management since it implements a proper free (and re-uses the memory)
// and now with prboom's code: realloc and calloc
printf ("Z_Init: Init zone memory allocation daemon.\n");
Z_Init ();
printf ("M_LoadDefaults: Load system defaults.\n");
M_LoadDefaults (); // load before initing other systems
rb->splash(HZ*2, "Welcome to RockDoom");
myargv =0;
myargc=0;
rb->lcd_clear_display();
int result = doom_menu();
if (result < 0)
{
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
rb->talk_disable(false);
if( result == -1 )
return PLUGIN_OK; // Quit was selected
else
return PLUGIN_ERROR; // Missing base wads
}
#if(LCD_HEIGHT>LCD_WIDTH)
if(rotate_screen)
{
SCREENHEIGHT=LCD_WIDTH;
SCREENWIDTH=LCD_HEIGHT;
}
else
{
SCREENHEIGHT=LCD_HEIGHT;
SCREENWIDTH=LCD_WIDTH;
}
#endif
Dhandle_ver( namemap[ result ] );
rb->lcd_setfont(FONT_SYSFIXED);
rb->lcd_clear_display();
int mod = (rb->sound_max(SOUND_VOLUME)-rb->sound_min(SOUND_VOLUME))/15;
if(mod == 0)
mod = rb->global_status->volume;
systemvol= rb->global_status->volume-rb->global_status->volume%mod;
general_translucency = default_translucency; // phares
backlight_ignore_timeout();
#ifdef RB_PROFILE
rb->profile_thread();
#endif
#if LCD_DEPTH>1
rb->lcd_set_backdrop(NULL);
#endif
D_DoomMain ();
#ifdef RB_PROFILE
rb->profstop();
#endif
backlight_use_settings();
M_SaveDefaults ();
I_Quit(); // Make SURE everything was closed out right
printf("There were still: %d files open\n", fpoint);
while(fpoint>0)
{
#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
close(filearray[fpoint]);
#else
rb->close(filearray[fpoint]);
#endif
fpoint--;
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
rb->talk_disable(false);
return PLUGIN_OK;
}