Convert many #ifdef SIMULATOR to #if (CONFIG_PLATFORM & PLATFORM_HOSTED) (and similar).
[kugel-rb.git] / apps / plugins / doom / rockdoom.c
blob042212812a6063431f065a478745de6b6351bfca
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 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
66 int my_open(const char *file, int flags, ...)
68 if(fpoint==8)
69 return -1;
70 #undef open
71 if (flags & O_CREAT)
73 va_list ap;
74 va_start(ap, flags);
75 filearray[fpoint]=rb->open(file, flags, va_arg(ap, unsigned int));
76 va_end(ap);
78 else
79 filearray[fpoint]=rb->open(file, flags);
80 if(filearray[fpoint]<0)
81 return filearray[fpoint];
83 fpoint++;
84 return filearray[fpoint-1];
87 int my_close(int id)
89 int i=0;
90 if(id<0)
91 return id;
92 while(filearray[i]!=id && i<8)
93 i++;
95 if(i==8)
97 printf("A requested FID did not exist!!!!");
98 return -9;
100 #undef close
101 rb->close(id);
103 for(; i<fpoint-1; i++)
104 filearray[i]=filearray[i+1];
106 fpoint--;
107 return 0;
109 #endif
110 #define MAXARGVS 100
112 bool noprintf=0; // Variable disables printf lcd updates to protect grayscale lib/direct lcd updates
114 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
115 // Here is a hacked up printf command to get the output from the game.
116 int printf(const char *fmt, ...)
118 static int p_xtpt;
119 char p_buf[50];
120 bool ok;
121 rb->yield();
122 va_list ap;
124 va_start(ap, fmt);
125 ok = vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
126 va_end(ap);
128 rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf);
129 if (!noprintf)
130 rb->lcd_update();
132 p_xtpt+=8;
133 if(p_xtpt>LCD_HEIGHT-8)
135 p_xtpt=0;
136 if (!noprintf)
137 rb->lcd_clear_display();
139 return 1;
141 #endif
143 char *my_strtok( char * s, const char * delim )
145 register char *spanp;
146 register int c, sc;
147 char *tok;
148 static char *lasts;
151 if (s == NULL && (s = lasts) == NULL)
152 return (NULL);
155 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
157 cont:
158 c = *s++;
159 for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
160 if (c == sc)
161 goto cont;
164 if (c == 0) { /* no non-delimiter characters */
165 lasts = NULL;
166 return (NULL);
168 tok = s - 1;
171 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
172 * Note that delim must have one NUL; we stop if we see that, too.
174 for (;;) {
175 c = *s++;
176 spanp = (char *)delim;
177 do {
178 if ((sc = *spanp++) == c) {
179 if (c == 0)
180 s = NULL;
181 else
182 s[-1] = 0;
183 lasts = s;
184 return (tok);
186 } while (sc != 0);
188 /* NOTREACHED */
191 struct argvlist
193 int timedemo; // 1 says there's a timedemo
194 int demonum;
195 int addonnum;
196 } argvlist;
198 const unsigned char versions_builtin[7][20] =
200 "Doom Shareware",
201 "Doom Registered",
202 "Ultimate Doom",
203 "Doom 2",
204 "Freedoom",
205 "Plutonia",
206 "TNT"
209 const unsigned char wads_builtin[7][30] =
211 GAMEBASE"doom1.wad",
212 GAMEBASE"doom.wad",
213 GAMEBASE"doomu.wad",
214 GAMEBASE"doom2.wad",
215 GAMEBASE"doomf.wad",
216 GAMEBASE"plutonia.wad",
217 GAMEBASE"tnt.wad"
220 int namemap[7];
221 static char **addons;
222 static char **demolmp;
223 char addon[200];
224 // This sets up the base game and builds up myargv/c
225 bool Dhandle_ver (int dver)
227 switch (dver) {
228 case 0: /* Doom Shareware */
229 gamemode = shareware;
230 gamemission = doom;
231 D_AddFile(wads_builtin[0],source_iwad);
232 break;
233 case 1: /* Doom registered */
234 gamemode = registered;
235 gamemission = doom;
236 D_AddFile(wads_builtin[1],source_iwad);
237 break;
238 case 2: /* Ultimate Doom */
239 gamemode = retail;
240 gamemission = doom;
241 D_AddFile(wads_builtin[2],source_iwad);
242 break;
243 case 3: /* Doom2 */
244 gamemode = commercial;
245 gamemission = doom2;
246 D_AddFile(wads_builtin[3],source_iwad);
247 break;
248 case 4: /* Doom2f */
249 gamemode = commercial;
250 gamemission = doom2;
251 D_AddFile(wads_builtin[4],source_iwad);
252 break;
253 case 5: /* Plutonia */
254 gamemode = commercial;
255 gamemission = pack_plut;
256 D_AddFile(wads_builtin[5],source_iwad);
257 break;
258 case 6: /* TNT */
259 gamemode = commercial;
260 gamemission = pack_tnt;
261 D_AddFile(wads_builtin[6],source_iwad);
262 break;
263 default:
264 gamemission = none;
265 return 0;
267 // Start adding to myargv
268 if(argvlist.timedemo && (gamemode == shareware))
270 singletics = true;
271 timingdemo = true; // show stats after quit
272 G_DeferedPlayDemo("demo3");
273 singledemo = true; // quit after one demo
276 if(argvlist.addonnum)
278 snprintf(addon,sizeof(addon),"%s%s", GAMEBASE"addons/", addons[argvlist.addonnum]);
279 D_AddFile(addon,source_pwad);
280 modifiedgame = true;
283 if(argvlist.demonum)
285 snprintf(addon, sizeof(addon),"%s%s", GAMEBASE"demos/", demolmp[argvlist.demonum]);
286 D_AddFile(addon, source_lmp);
287 G_DeferedPlayDemo(addon);
288 singledemo = true; // quit after one demo
290 return 1;
293 // This function builds up the basegame list for use in the options selection
294 // it also sets the defaults for the argvlist
295 // Now checking for rcokdoom.wad based on prboom.wad
296 int Dbuild_base (struct opt_items *names)
298 if ( fileexists(GAMEBASE"rockdoom.wad") )
299 return 0;
301 D_AddFile (GAMEBASE"rockdoom.wad", source_pwad);
303 int i=0, j;
304 /* Doom Shareware */
305 /* Doom registered */
306 /* Ultimate Doom */
307 /* Doom2 */
308 /* Doom2f */
309 /* Plutonia */
310 /* TNT */
311 for(j=0;j<7;j++)
312 if ( !fileexists (wads_builtin[j]) )
314 names[i].string=versions_builtin[j];
315 names[i].voice_id=-1;
316 namemap[i]=j;
317 i++;
319 // Set argvlist defaults
320 argvlist.timedemo=0;
322 return i;
325 // This is a general function that takes in a menu_item structure and makes a list
326 // of files within it based on matching the string stringmatch to the files.
327 int Dbuild_filelistm(char ***names, char *firstentry, char *directory, char *stringmatch)
329 int i=0;
330 DIR *filedir;
331 struct dirent *dptr;
332 char *startpt;
333 char **temp;
335 filedir=rb->opendir(directory);
337 if(filedir==NULL)
339 temp=malloc(sizeof(char *));
340 temp[0]=firstentry;
341 *names=temp;
342 return 1;
345 // Get the total number of entries
346 while((dptr=rb->readdir(filedir)))
347 i++;
349 // Reset the directory
350 rb->closedir(filedir);
351 filedir=rb->opendir(directory);
353 i++;
354 temp=malloc(i*sizeof(char *));
355 temp[0]=firstentry;
356 i=1;
358 while((dptr=rb->readdir(filedir)))
360 if(rb->strcasestr(dptr->d_name, stringmatch))
362 startpt=malloc(strlen(dptr->d_name)*sizeof(char));
363 strcpy(startpt,dptr->d_name);
364 temp[i]=startpt;
365 i++;
368 rb->closedir(filedir);
369 *names=temp;
370 return i;
373 static int translatekey(int key) __attribute__ ((noinline));
375 // This key configuration code is not the cleanest or the most efficient, but it works
376 static int translatekey(int key)
378 if (key<31)
380 switch(key)
382 case 0:
383 return 0;
384 case 1:
385 return KEY_RIGHTARROW;
386 case 2:
387 return KEY_LEFTARROW;
388 case 3:
389 return KEY_UPARROW;
390 case 4:
391 return KEY_DOWNARROW;
392 case 5:
393 return KEY_ENTER;
394 case 6:
395 return KEY_RCTRL;
396 case 7:
397 return ' ';
398 case 8:
399 return KEY_ESCAPE;
400 case 9:
401 return 'w';
402 case 10:
403 return KEY_TAB;
404 default:
405 return 0;
408 else
410 switch(key)
412 case 0:
413 return 0;
414 case KEY_RIGHTARROW:
415 return 1;
416 case KEY_LEFTARROW:
417 return 2;
418 case KEY_UPARROW:
419 return 3;
420 case KEY_DOWNARROW:
421 return 4;
422 case KEY_ENTER:
423 return 5;
424 case KEY_RCTRL:
425 return 6;
426 case ' ':
427 return 7;
428 case KEY_ESCAPE:
429 return 8;
430 case 'w':
431 return 9;
432 case KEY_TAB:
433 return 10;
434 default:
435 return 0;
440 // I havn't added configurable keys for enter or escape because this requires some modification to
441 // m_menu.c which hasn't been done yet.
443 int Oset_keys()
445 int selected=0, result;
446 int menuquit=0;
449 static const struct opt_items doomkeys[] = {
450 { "Unmapped", -1 },
451 { "Key Right", -1 },
452 { "Key Left", -1 },
453 { "Key Up", -1 },
454 { "Key Down", -1 },
455 { "Key Select", -1 },
456 #if defined(TOSHIBA_GIGABEAT_F)
457 { "Key A", -1 },
458 { "Key Menu", -1 },
459 { "Key Power", -1 },
460 { "Key Volume Down", -1 },
461 { "Key Volume Up", -1 },
462 #else
463 { "Key Record", -1 },
464 { "Key Mode", -1 },
465 { "Key Off", -1 },
466 { "Key On", -1 },
467 #endif
470 int *keys[]={
471 &key_right,
472 &key_left,
473 &key_up,
474 &key_down,
475 &key_fire,
476 &key_use,
477 &key_strafe,
478 &key_weapon,
479 &key_map
482 int numdoomkeys=sizeof(doomkeys) / sizeof(*doomkeys);
484 MENUITEM_STRINGLIST(menu, "Set Keys", NULL,
485 "Game Right", "Game Left", "Game Up", "Game Down",
486 "Game Shoot", "Game Open", "Game Strafe",
487 "Game Weapon", "Game Automap");
489 while(!menuquit)
491 result = rb->do_menu(&menu, &selected, NULL, false);
492 if(result<0)
493 menuquit=1;
494 else
496 *keys[result]=translatekey(*keys[result]);
497 rb->set_option(menu_[result], keys[result], INT, doomkeys, numdoomkeys, NULL );
498 *keys[result]=translatekey(*keys[result]);
502 return (1);
505 extern int fake_contrast;
507 static bool Doptions()
509 static const struct opt_items onoff[2] = {
510 { "Off", -1 },
511 { "On", -1 },
514 int selected=0, result;
515 int menuquit=0;
517 MENUITEM_STRINGLIST(menu, "Options", NULL,
518 "Set Keys", "Sound", "Timedemo", "Player Bobbing",
519 "Weapon Recoil", "Translucency", "Fake Contrast",
520 "Always Run", "Headsup Display", "Statusbar Always Red",
521 #if(LCD_HEIGHT>LCD_WIDTH)
522 "Rotate Screen 90 deg",
523 #endif
526 void *options[]={
527 &enable_sound,
528 &argvlist.timedemo,
529 &default_player_bobbing,
530 &default_weapon_recoil,
531 &default_translucency,
532 &fake_contrast,
533 &autorun,
534 &hud_displayed,
535 &sts_always_red,
536 #if(LCD_HEIGHT>LCD_WIDTH)
537 &rotate_screen,
538 #endif
541 while(!menuquit)
543 result = rb->do_menu(&menu, &selected, NULL, false);
544 if(result==0)
545 Oset_keys();
546 else if (result > 0)
547 rb->set_option(menu_[result], options[result-1], INT, onoff, 2, NULL );
548 else
549 menuquit=1;
552 return (1);
555 static const char* choice_get_name(int selected_item, void * data,
556 char * buffer, size_t buffer_len)
558 const char **names = (const char **) data;
559 (void) buffer;
560 (void) buffer_len;
561 return names[selected_item];
564 int list_action_callback(int action, struct gui_synclist *lists)
566 (void) lists;
567 if (action == ACTION_STD_OK)
568 return ACTION_STD_CANCEL;
569 return action;
572 bool menuchoice(char **names, int count, int *selected)
574 struct simplelist_info info;
575 rb->simplelist_info_init(&info, NULL, count, (void*)names);
576 info.selection = *selected;
577 info.get_name = choice_get_name;
578 info.action_callback = list_action_callback;
579 if(rb->simplelist_show_list(&info))
580 return true;
582 if(info.selection<count && info.selection>=0)
583 *selected = info.selection;
584 return false;
588 // Doom Menu
590 int doom_menu()
592 int selected=0, result;
593 int status;
594 int gamever;
595 bool menuquit=0;
597 static struct opt_items names[7];
599 MENUITEM_STRINGLIST(menu, "Doom Menu", NULL,
600 "Game", "Addons", "Demos",
601 "Options", "Play Game", "Quit");
603 if( (status=Dbuild_base(names)) == 0 ) // Build up the base wad files (select last added file)
605 rb->splash(HZ*2, "Missing Base WAD!");
606 return -2;
609 int numadd=Dbuild_filelistm(&addons, "No Addon", GAMEBASE"addons/", ".WAD" );
611 int numdemos=Dbuild_filelistm(&demolmp, "No Demo", GAMEBASE"demos/", ".LMP" );
613 argvlist.demonum=0;
614 argvlist.addonnum=0;
616 gamever=status-1;
618 /* Clean out the button Queue */
619 while (rb->button_get(false) != BUTTON_NONE)
620 rb->yield();
622 while(!menuquit)
624 result = rb->do_menu(&menu, &selected, NULL, false);
625 switch (result) {
626 case 0: /* Game picker */
627 rb->set_option("Game WAD", &gamever, INT, names, status, NULL );
628 break;
630 case 1: /* Addon picker */
631 menuchoice(addons,numadd,&argvlist.addonnum);
632 break;
634 case 2: /* Demos */
635 menuchoice(demolmp,numdemos,&argvlist.demonum);
636 break;
638 case 3: /* Options */
639 Doptions();
640 break;
642 case 4: /* Play Game */
643 menuquit=1;
644 break;
646 case 5: /* Quit */
647 menuquit=1;
648 gamever=-1;
649 break;
651 default:
652 break;
656 return (gamever);
659 extern int systemvol;
660 /* this is the plugin entry point */
661 enum plugin_status plugin_start(const void* parameter)
663 /* Disable all talking before initializing IRAM */
664 rb->talk_disable(true);
666 PLUGIN_IRAM_INIT(rb)
668 (void)parameter;
670 doomexit=0;
672 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
673 rb->cpu_boost(true);
674 #endif
676 rb->lcd_setfont(0);
678 // We're using doom's memory management since it implements a proper free (and re-uses the memory)
679 // and now with prboom's code: realloc and calloc
680 printf ("Z_Init: Init zone memory allocation daemon.\n");
681 Z_Init ();
683 printf ("M_LoadDefaults: Load system defaults.\n");
684 M_LoadDefaults (); // load before initing other systems
686 rb->splash(HZ*2, "Welcome to RockDoom");
688 myargv =0;
689 myargc=0;
691 rb->lcd_clear_display();
693 int result = doom_menu();
694 if (result < 0)
696 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
697 rb->cpu_boost(false);
698 #endif
699 rb->talk_disable(false);
700 if( result == -1 )
701 return PLUGIN_OK; // Quit was selected
702 else
703 return PLUGIN_ERROR; // Missing base wads
706 #if(LCD_HEIGHT>LCD_WIDTH)
707 if(rotate_screen)
709 SCREENHEIGHT=LCD_WIDTH;
710 SCREENWIDTH=LCD_HEIGHT;
712 else
714 SCREENHEIGHT=LCD_HEIGHT;
715 SCREENWIDTH=LCD_WIDTH;
717 #endif
719 Dhandle_ver( namemap[ result ] );
721 rb->lcd_setfont(0);
723 rb->lcd_clear_display();
725 int mod = (rb->sound_max(SOUND_VOLUME)-rb->sound_min(SOUND_VOLUME))/15;
726 if(mod == 0)
727 mod = rb->global_settings->volume;
728 systemvol= rb->global_settings->volume-rb->global_settings->volume%mod;
729 general_translucency = default_translucency; // phares
731 backlight_force_on();
732 #ifdef RB_PROFILE
733 rb->profile_thread();
734 #endif
736 #if LCD_DEPTH>1
737 rb->lcd_set_backdrop(NULL);
738 #endif
740 D_DoomMain ();
742 #ifdef RB_PROFILE
743 rb->profstop();
744 #endif
745 backlight_use_settings();
747 M_SaveDefaults ();
749 I_Quit(); // Make SURE everything was closed out right
751 printf("There were still: %d files open\n", fpoint);
752 while(fpoint>0)
754 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
755 close(filearray[fpoint]);
756 #else
757 rb->close(filearray[fpoint]);
758 #endif
759 fpoint--;
762 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
763 rb->cpu_boost(false);
764 #endif
766 rb->talk_disable(false);
767 return PLUGIN_OK;