Correct beast manual install instructions in Windows.
[kugel-rb.git] / apps / plugins / doom / rockdoom.c
bloba76c9379b39072cf6f179d2a69bc0b98818bfc2c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2005 Karl Kurbjun
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 * H300 Port by Karl Kurbjun
20 * IPod port by Dave Chapman and Paul Louden
21 * Additional code contributed by Thom Johansen
22 * Based off work by: Digita Doom, IDoom, Prboom, lSDLDoom, LxDoom,
23 * MBF, Boom, DosDoom,
24 * and of course Original Doom by ID Software
25 * See: http://prboom.sourceforge.net/about.html for the history
28 ****************************************************************************/
30 #include "d_main.h"
31 #include "doomdef.h"
32 #include "settings.h"
33 #include "m_fixed.h"
34 #include "m_argv.h"
35 #include "m_misc.h"
36 #include "g_game.h"
37 #include "rockmacros.h"
38 #include "doomstat.h"
39 #include "i_system.h"
40 #include "hu_stuff.h"
41 #include "st_stuff.h"
42 #include "lib/helper.h"
44 PLUGIN_HEADER
45 PLUGIN_IRAM_DECLARE
47 extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
49 int filearray[9];
50 int fpoint=1; // save 0 for closing
52 int fileexists(const char * fname)
54 int fd;
55 fd = open(fname,O_RDONLY);
57 if (fd>=0)
59 close(fd);
60 return 0;
62 return -1;
65 #ifndef SIMULATOR
66 int my_open(const char *file, int flags)
68 if(fpoint==8)
69 return -1;
70 #undef open
71 filearray[fpoint]=rb->open(file, flags);
73 if(filearray[fpoint]<0)
74 return filearray[fpoint];
76 fpoint++;
77 return filearray[fpoint-1];
80 int my_close(int id)
82 int i=0;
83 if(id<0)
84 return id;
85 while(filearray[i]!=id && i<8)
86 i++;
88 if(i==8)
90 printf("A requested FID did not exist!!!!");
91 return -9;
93 #undef close
94 rb->close(id);
96 for(; i<fpoint-1; i++)
97 filearray[i]=filearray[i+1];
99 fpoint--;
100 return 0;
102 #endif
103 #define MAXARGVS 100
105 bool noprintf=0; // Variable disables printf lcd updates to protect grayscale lib/direct lcd updates
107 #ifndef SIMULATOR
108 // Here is a hacked up printf command to get the output from the game.
109 int printf(const char *fmt, ...)
111 static int p_xtpt;
112 char p_buf[50];
113 bool ok;
114 rb->yield();
115 va_list ap;
117 va_start(ap, fmt);
118 ok = vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
119 va_end(ap);
121 rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf);
122 if (!noprintf)
123 rb->lcd_update();
125 p_xtpt+=8;
126 if(p_xtpt>LCD_HEIGHT-8)
128 p_xtpt=0;
129 if (!noprintf)
130 rb->lcd_clear_display();
132 return 1;
134 #endif
136 char *my_strtok( char * s, const char * delim )
138 register char *spanp;
139 register int c, sc;
140 char *tok;
141 static char *lasts;
144 if (s == NULL && (s = lasts) == NULL)
145 return (NULL);
148 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
150 cont:
151 c = *s++;
152 for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
153 if (c == sc)
154 goto cont;
157 if (c == 0) { /* no non-delimiter characters */
158 lasts = NULL;
159 return (NULL);
161 tok = s - 1;
164 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
165 * Note that delim must have one NUL; we stop if we see that, too.
167 for (;;) {
168 c = *s++;
169 spanp = (char *)delim;
170 do {
171 if ((sc = *spanp++) == c) {
172 if (c == 0)
173 s = NULL;
174 else
175 s[-1] = 0;
176 lasts = s;
177 return (tok);
179 } while (sc != 0);
181 /* NOTREACHED */
184 struct argvlist
186 int timedemo; // 1 says there's a timedemo
187 int demonum;
188 int addonnum;
189 } argvlist;
191 const unsigned char versions_builtin[7][20] =
193 "Doom Shareware",
194 "Doom Registered",
195 "Ultimate Doom",
196 "Doom 2",
197 "Freedoom",
198 "Plutonia",
199 "TNT"
202 const unsigned char wads_builtin[7][30] =
204 GAMEBASE"doom1.wad",
205 GAMEBASE"doom.wad",
206 GAMEBASE"doomu.wad",
207 GAMEBASE"doom2.wad",
208 GAMEBASE"doomf.wad",
209 GAMEBASE"plutonia.wad",
210 GAMEBASE"tnt.wad"
213 int namemap[7];
214 static char **addons;
215 static char **demolmp;
216 char addon[200];
217 // This sets up the base game and builds up myargv/c
218 bool Dhandle_ver (int dver)
220 switch (dver) {
221 case 0: /* Doom Shareware */
222 gamemode = shareware;
223 gamemission = doom;
224 D_AddFile(wads_builtin[0],source_iwad);
225 break;
226 case 1: /* Doom registered */
227 gamemode = registered;
228 gamemission = doom;
229 D_AddFile(wads_builtin[1],source_iwad);
230 break;
231 case 2: /* Ultimate Doom */
232 gamemode = retail;
233 gamemission = doom;
234 D_AddFile(wads_builtin[2],source_iwad);
235 break;
236 case 3: /* Doom2 */
237 gamemode = commercial;
238 gamemission = doom2;
239 D_AddFile(wads_builtin[3],source_iwad);
240 break;
241 case 4: /* Doom2f */
242 gamemode = commercial;
243 gamemission = doom2;
244 D_AddFile(wads_builtin[4],source_iwad);
245 break;
246 case 5: /* Plutonia */
247 gamemode = commercial;
248 gamemission = pack_plut;
249 D_AddFile(wads_builtin[5],source_iwad);
250 break;
251 case 6: /* TNT */
252 gamemode = commercial;
253 gamemission = pack_tnt;
254 D_AddFile(wads_builtin[6],source_iwad);
255 break;
256 default:
257 gamemission = none;
258 return 0;
260 // Start adding to myargv
261 if(argvlist.timedemo && (gamemode == shareware))
263 singletics = true;
264 timingdemo = true; // show stats after quit
265 G_DeferedPlayDemo("demo3");
266 singledemo = true; // quit after one demo
269 if(argvlist.addonnum)
271 snprintf(addon,sizeof(addon),"%s%s", GAMEBASE"addons/", addons[argvlist.addonnum]);
272 D_AddFile(addon,source_pwad);
273 modifiedgame = true;
276 if(argvlist.demonum)
278 snprintf(addon, sizeof(addon),"%s%s", GAMEBASE"demos/", demolmp[argvlist.demonum]);
279 D_AddFile(addon, source_lmp);
280 G_DeferedPlayDemo(addon);
281 singledemo = true; // quit after one demo
283 return 1;
286 // This function builds up the basegame list for use in the options selection
287 // it also sets the defaults for the argvlist
288 // Now checking for rcokdoom.wad based on prboom.wad
289 int Dbuild_base (struct opt_items *names)
291 if ( fileexists(GAMEBASE"rockdoom.wad") )
292 return 0;
294 D_AddFile (GAMEBASE"rockdoom.wad", source_pwad);
296 int i=0, j;
297 /* Doom Shareware */
298 /* Doom registered */
299 /* Ultimate Doom */
300 /* Doom2 */
301 /* Doom2f */
302 /* Plutonia */
303 /* TNT */
304 for(j=0;j<7;j++)
305 if ( !fileexists (wads_builtin[j]) )
307 names[i].string=versions_builtin[j];
308 names[i].voice_id=-1;
309 namemap[i]=j;
310 i++;
312 // Set argvlist defaults
313 argvlist.timedemo=0;
315 return i;
318 // This is a general function that takes in a menu_item structure and makes a list
319 // of files within it based on matching the string stringmatch to the files.
320 int Dbuild_filelistm(char ***names, char *firstentry, char *directory, char *stringmatch)
322 int i=0;
323 DIR *filedir;
324 struct dirent *dptr;
325 char *startpt;
326 char **temp;
328 filedir=rb->opendir(directory);
330 if(filedir==NULL)
332 temp=malloc(sizeof(char *));
333 temp[0]=firstentry;
334 *names=temp;
335 return 1;
338 // Get the total number of entries
339 while((dptr=rb->readdir(filedir)))
340 i++;
342 // Reset the directory
343 rb->closedir(filedir);
344 filedir=rb->opendir(directory);
346 i++;
347 temp=malloc(i*sizeof(char *));
348 temp[0]=firstentry;
349 i=1;
351 while((dptr=rb->readdir(filedir)))
353 if(rb->strcasestr(dptr->d_name, stringmatch))
355 startpt=malloc(strlen(dptr->d_name)*sizeof(char));
356 strcpy(startpt,dptr->d_name);
357 temp[i]=startpt;
358 i++;
361 rb->closedir(filedir);
362 *names=temp;
363 return i;
366 static int translatekey(int key) __attribute__ ((noinline));
368 // This key configuration code is not the cleanest or the most efficient, but it works
369 static int translatekey(int key)
371 if (key<31)
373 switch(key)
375 case 0:
376 return 0;
377 case 1:
378 return KEY_RIGHTARROW;
379 case 2:
380 return KEY_LEFTARROW;
381 case 3:
382 return KEY_UPARROW;
383 case 4:
384 return KEY_DOWNARROW;
385 case 5:
386 return KEY_ENTER;
387 case 6:
388 return KEY_RCTRL;
389 case 7:
390 return ' ';
391 case 8:
392 return KEY_ESCAPE;
393 case 9:
394 return 'w';
395 case 10:
396 return KEY_TAB;
397 default:
398 return 0;
401 else
403 switch(key)
405 case 0:
406 return 0;
407 case KEY_RIGHTARROW:
408 return 1;
409 case KEY_LEFTARROW:
410 return 2;
411 case KEY_UPARROW:
412 return 3;
413 case KEY_DOWNARROW:
414 return 4;
415 case KEY_ENTER:
416 return 5;
417 case KEY_RCTRL:
418 return 6;
419 case ' ':
420 return 7;
421 case KEY_ESCAPE:
422 return 8;
423 case 'w':
424 return 9;
425 case KEY_TAB:
426 return 10;
427 default:
428 return 0;
433 // I havn't added configurable keys for enter or escape because this requires some modification to
434 // m_menu.c which hasn't been done yet.
436 int Oset_keys()
438 int selected=0, result;
439 int menuquit=0;
442 static const struct opt_items doomkeys[] = {
443 { "Unmapped", -1 },
444 { "Key Right", -1 },
445 { "Key Left", -1 },
446 { "Key Up", -1 },
447 { "Key Down", -1 },
448 { "Key Select", -1 },
449 #if defined(TOSHIBA_GIGABEAT_F)
450 { "Key A", -1 },
451 { "Key Menu", -1 },
452 { "Key Power", -1 },
453 { "Key Volume Down", -1 },
454 { "Key Volume Up", -1 },
455 #else
456 { "Key Record", -1 },
457 { "Key Mode", -1 },
458 { "Key Off", -1 },
459 { "Key On", -1 },
460 #endif
463 int *keys[]={
464 &key_right,
465 &key_left,
466 &key_up,
467 &key_down,
468 &key_fire,
469 &key_use,
470 &key_strafe,
471 &key_weapon,
472 &key_map
475 int numdoomkeys=sizeof(doomkeys) / sizeof(*doomkeys);
477 MENUITEM_STRINGLIST(menu, "Set Keys", NULL,
478 "Game Right", "Game Left", "Game Up", "Game Down",
479 "Game Shoot", "Game Open", "Game Strafe",
480 "Game Weapon", "Game Automap");
482 while(!menuquit)
484 result = rb->do_menu(&menu, &selected, NULL, false);
485 if(result<0)
486 menuquit=1;
487 else
489 *keys[result]=translatekey(*keys[result]);
490 rb->set_option(menu_[result], keys[result], INT, doomkeys, numdoomkeys, NULL );
491 *keys[result]=translatekey(*keys[result]);
495 return (1);
498 extern int fake_contrast;
500 static bool Doptions()
502 static const struct opt_items onoff[2] = {
503 { "Off", -1 },
504 { "On", -1 },
507 int selected=0, result;
508 int menuquit=0;
510 MENUITEM_STRINGLIST(menu, "Options", NULL,
511 "Set Keys", "Sound", "Timedemo", "Player Bobbing",
512 "Weapon Recoil", "Translucency", "Fake Contrast",
513 "Always Run", "Headsup Display", "Statusbar Always Red",
514 #if(LCD_HEIGHT>LCD_WIDTH)
515 "Rotate Screen 90 deg",
516 #endif
519 void *options[]={
520 &enable_sound,
521 &argvlist.timedemo,
522 &default_player_bobbing,
523 &default_weapon_recoil,
524 &default_translucency,
525 &fake_contrast,
526 &autorun,
527 &hud_displayed,
528 &sts_always_red,
529 #if(LCD_HEIGHT>LCD_WIDTH)
530 &rotate_screen,
531 #endif
534 while(!menuquit)
536 result = rb->do_menu(&menu, &selected, NULL, false);
537 if(result==0)
538 Oset_keys();
539 else if (result > 0)
540 rb->set_option(menu_[result], options[result-1], INT, onoff, 2, NULL );
541 else
542 menuquit=1;
545 return (1);
548 static const char* choice_get_name(int selected_item, void * data,
549 char * buffer, size_t buffer_len)
551 const char **names = (const char **) data;
552 (void) buffer;
553 (void) buffer_len;
554 return names[selected_item];
557 int list_action_callback(int action, struct gui_synclist *lists)
559 (void) lists;
560 if (action == ACTION_STD_OK)
561 return ACTION_STD_CANCEL;
562 return action;
565 bool menuchoice(char **names, int count, int *selected)
567 struct simplelist_info info;
568 rb->simplelist_info_init(&info, NULL, count, (void*)names);
569 info.selection = *selected;
570 info.get_name = choice_get_name;
571 info.action_callback = list_action_callback;
572 if(rb->simplelist_show_list(&info))
573 return true;
575 if(info.selection<count && info.selection>=0)
576 *selected = info.selection;
577 return false;
581 // Doom Menu
583 int doom_menu()
585 int selected=0, result;
586 int status;
587 int gamever;
588 bool menuquit=0;
590 static struct opt_items names[7];
592 MENUITEM_STRINGLIST(menu, "Doom Menu", NULL,
593 "Game", "Addons", "Demos",
594 "Options", "Play Game", "Quit");
596 if( (status=Dbuild_base(names)) == 0 ) // Build up the base wad files (select last added file)
598 rb->splash(HZ*2, "Missing Base WAD!");
599 return -2;
602 int numadd=Dbuild_filelistm(&addons, "No Addon", GAMEBASE"addons/", ".WAD" );
604 int numdemos=Dbuild_filelistm(&demolmp, "No Demo", GAMEBASE"demos/", ".LMP" );
606 argvlist.demonum=0;
607 argvlist.addonnum=0;
609 gamever=status-1;
611 /* Clean out the button Queue */
612 while (rb->button_get(false) != BUTTON_NONE)
613 rb->yield();
615 while(!menuquit)
617 result = rb->do_menu(&menu, &selected, NULL, false);
618 switch (result) {
619 case 0: /* Game picker */
620 rb->set_option("Game WAD", &gamever, INT, names, status, NULL );
621 break;
623 case 1: /* Addon picker */
624 menuchoice(addons,numadd,&argvlist.addonnum);
625 break;
627 case 2: /* Demos */
628 menuchoice(demolmp,numdemos,&argvlist.demonum);
629 break;
631 case 3: /* Options */
632 Doptions();
633 break;
635 case 4: /* Play Game */
636 menuquit=1;
637 break;
639 case 5: /* Quit */
640 menuquit=1;
641 gamever=-1;
642 break;
644 default:
645 break;
649 return (gamever);
652 extern int systemvol;
653 /* this is the plugin entry point */
654 enum plugin_status plugin_start(const void* parameter)
656 PLUGIN_IRAM_INIT(rb)
658 (void)parameter;
660 doomexit=0;
662 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
663 rb->cpu_boost(true);
664 #endif
666 rb->lcd_setfont(0);
668 // We're using doom's memory management since it implements a proper free (and re-uses the memory)
669 // and now with prboom's code: realloc and calloc
670 printf ("Z_Init: Init zone memory allocation daemon.\n");
671 Z_Init ();
673 printf ("M_LoadDefaults: Load system defaults.\n");
674 M_LoadDefaults (); // load before initing other systems
676 rb->splash(HZ*2, "Welcome to RockDoom");
678 myargv =0;
679 myargc=0;
681 rb->lcd_clear_display();
683 int result = doom_menu();
684 if (result < 0)
686 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
687 rb->cpu_boost(false);
688 #endif
689 if( result == -1 )
690 return PLUGIN_OK; // Quit was selected
691 else
692 return PLUGIN_ERROR; // Missing base wads
695 #if(LCD_HEIGHT>LCD_WIDTH)
696 if(rotate_screen)
698 SCREENHEIGHT=LCD_WIDTH;
699 SCREENWIDTH=LCD_HEIGHT;
701 else
703 SCREENHEIGHT=LCD_HEIGHT;
704 SCREENWIDTH=LCD_WIDTH;
706 #endif
708 Dhandle_ver( namemap[ result ] );
710 rb->lcd_setfont(0);
712 rb->lcd_clear_display();
714 int mod = (rb->sound_max(SOUND_VOLUME)-rb->sound_min(SOUND_VOLUME))/15;
715 if(mod == 0)
716 mod = rb->global_settings->volume;
717 systemvol= rb->global_settings->volume-rb->global_settings->volume%mod;
718 general_translucency = default_translucency; // phares
720 backlight_force_on();
721 #ifdef RB_PROFILE
722 rb->profile_thread();
723 #endif
725 #if LCD_DEPTH>1
726 rb->lcd_set_backdrop(NULL);
727 #endif
729 D_DoomMain ();
731 #ifdef RB_PROFILE
732 rb->profstop();
733 #endif
734 backlight_use_settings();
736 M_SaveDefaults ();
738 I_Quit(); // Make SURE everything was closed out right
740 printf("There were still: %d files open\n", fpoint);
741 while(fpoint>0)
743 #ifdef SIMULATOR
744 close(filearray[fpoint]);
745 #else
746 rb->close(filearray[fpoint]);
747 #endif
748 fpoint--;
751 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
752 rb->cpu_boost(false);
753 #endif
755 return PLUGIN_OK;