01313d5039
* Add backlight_force_on() which forces to turn on backlight even when the setting is set to Off. use this in lamp. No functional change except lamp. See aslo FS#9883. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29128 a1c6a512-1295-4272-9138-f99709370657
763 lines
18 KiB
C
763 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];
|
|
bool ok;
|
|
rb->yield();
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
ok = 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], 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], 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, 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(0);
|
|
|
|
// 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(0);
|
|
|
|
rb->lcd_clear_display();
|
|
|
|
int mod = (rb->sound_max(SOUND_VOLUME)-rb->sound_min(SOUND_VOLUME))/15;
|
|
if(mod == 0)
|
|
mod = rb->global_settings->volume;
|
|
systemvol= rb->global_settings->volume-rb->global_settings->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;
|
|
}
|