add the files to the commit...
This commit is contained in:
parent
5e2988a6bb
commit
44d2ab8f6c
6 changed files with 201 additions and 8 deletions
138
src/cli.c
Normal file
138
src/cli.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
#include "cli.h"
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "difficulty.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "stage.h"
|
||||
#include "plrmodes.h"
|
||||
|
||||
struct TsOption { struct option opt; const char *help; const char *argname;};
|
||||
|
||||
static void print_help(struct TsOption* opts) {
|
||||
tsfprintf(stdout, "Usage: taisei [OPTIONS]\nTaisei is an open source Touhou clone.\n\nOptions:\n");
|
||||
int margin = 20;
|
||||
for(struct TsOption *opt = opts; opt->opt.name; opt++) {
|
||||
tsfprintf(stdout, " -%c, --%s ",opt->opt.val,opt->opt.name);
|
||||
int length = margin-(int)strlen(opt->opt.name);
|
||||
if(opt->argname) {
|
||||
tsfprintf(stdout, opt->argname);
|
||||
length -= (int)strlen(opt->argname);
|
||||
}
|
||||
for(int i = 0; i < length; i++)
|
||||
tsfprintf(stdout, " ");
|
||||
if(opt->argname)
|
||||
tsfprintf(stdout, opt->help, opt->argname);
|
||||
else
|
||||
tsfprintf(stdout, opt->help);
|
||||
tsfprintf(stdout,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
int cli_args(int argc, char **argv, CLIAction *a) {
|
||||
struct TsOption taisei_opts[] =
|
||||
{{{"replay", required_argument, 0, 'r'}, "Play a replay from %s", "FILE"},
|
||||
#ifdef DEBUG
|
||||
{{"play", no_argument, 0, 'p'}, "Play a specific stage", 0},
|
||||
{{"sid", required_argument, 0, 'i'}, "Select stage by %s", "ID"},
|
||||
{{"diff", required_argument, 0, 'd'}, "Select a difficulty (Easy/Normal/Hard/Lunatic)", "DIFF"},
|
||||
/* {{"sname", required_argument, 0, 'n'}, "Select stage by %s", "NAME"},*/
|
||||
{{"shotmode", required_argument, 0, 's'}, "Select a shotmode (marisaA/youmuA/marisaB/youmuB)", "SMODE"},
|
||||
{{"dumpstages", no_argument, 0, 'u'}, "Print a list of all stages in the game", 0},
|
||||
{{"dumprestables", no_argument, 0, 't'}, "Print information about the resource hashtables", 0},
|
||||
#endif
|
||||
{{"help", no_argument, 0, 'h'}, "Display this help."},
|
||||
{{0,0,0,0},0,0}
|
||||
};
|
||||
|
||||
memset(a,0,sizeof(CLIAction));
|
||||
|
||||
int nopts = sizeof(taisei_opts)/sizeof(taisei_opts[0]);
|
||||
struct option opts[nopts];
|
||||
char optc[2*nopts+1];
|
||||
char *ptr = optc;
|
||||
|
||||
for(int i = 0; i < nopts; i++) {
|
||||
opts[i] = taisei_opts[i].opt;
|
||||
*ptr = opts[i].val;
|
||||
ptr++;
|
||||
if(opts[i].has_arg != no_argument) {
|
||||
*ptr = ':';
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
*ptr = 0;
|
||||
|
||||
|
||||
int c;
|
||||
int stageid = -1;
|
||||
Character cha = -1;
|
||||
ShotMode shot = -1;
|
||||
while((c = getopt_long(argc, argv, optc ,opts, 0)) != -1) {
|
||||
char *endptr;
|
||||
switch(c) {
|
||||
case 'h':
|
||||
case '?':
|
||||
print_help(taisei_opts);
|
||||
a->type = CLI_Quit;
|
||||
break;
|
||||
case 'r':
|
||||
a->type = CLI_PlayReplay;
|
||||
a->filename = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
a->type = CLI_SelectStage;
|
||||
break;
|
||||
case 'i':
|
||||
stageid = strtol(optarg,&endptr, 16);
|
||||
if(*optarg == 0 || *endptr != 0)
|
||||
log_fatal("stage id '%s' is not a number", optarg);
|
||||
break;
|
||||
case 'u':
|
||||
a->type = CLI_DumpStages;
|
||||
break;
|
||||
case 't':
|
||||
a->type = CLI_DumpResTables;
|
||||
break;
|
||||
case 'd':
|
||||
for(int i = D_Easy ; i <= NUM_SELECTABLE_DIFFICULTIES; i++) {
|
||||
if(strcmp(optarg,difficulty_name(i)) == 0) {
|
||||
a->diff = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if(plrmode_parse(optarg,&cha,&shot))
|
||||
log_fatal("Invalid shotmode '%s'",optarg);
|
||||
break;
|
||||
default:
|
||||
log_fatal("Unknown option (this shouldn’t happen)");
|
||||
}
|
||||
}
|
||||
|
||||
if(stageid != -1 && a->type != CLI_PlayReplay && a->type != CLI_SelectStage)
|
||||
log_warn("--sid was ignored");
|
||||
if(stageid != -1 && !stage_get(stageid))
|
||||
log_fatal("Invalid stage id: %x",stageid);
|
||||
|
||||
if(a->type != CLI_SelectStage && (cha != -1 || shot != -1))
|
||||
log_warn("--shotmode was ignored");
|
||||
|
||||
if(cha != -1 && shot != -1) {
|
||||
a->plrcha = cha;
|
||||
a->plrshot = shot;
|
||||
}
|
||||
|
||||
a->stageid = stageid;
|
||||
|
||||
if(a->type == CLI_SelectStage && stageid == -1)
|
||||
log_fatal("StageSelect mode, but no stage id was given");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_cli_action(CLIAction *a) {
|
||||
free(a->filename);
|
||||
}
|
31
src/cli.h
Normal file
31
src/cli.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef CLI_H
|
||||
#define CLI_H
|
||||
|
||||
#include "player.h"
|
||||
|
||||
typedef enum {
|
||||
CLI_RunNormally = 0,
|
||||
CLI_PlayReplay,
|
||||
CLI_SelectStage,
|
||||
CLI_DumpStages,
|
||||
CLI_DumpResTables,
|
||||
CLI_Quit,
|
||||
|
||||
CLI_ARGC = 4
|
||||
} CLIActionType;
|
||||
|
||||
typedef struct CLIAction CLIAction;
|
||||
struct CLIAction {
|
||||
CLIActionType type;
|
||||
char *filename;
|
||||
int stageid;
|
||||
int diff;
|
||||
|
||||
Character plrcha;
|
||||
ShotMode plrshot;
|
||||
};
|
||||
|
||||
int cli_args(int argc, char **argv, CLIAction *a);
|
||||
void free_cli_action(CLIAction *a);
|
||||
|
||||
#endif
|
|
@ -177,6 +177,7 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if(a.type == CLI_DumpResTables) {
|
||||
print_resource_hashtables();
|
||||
return 0;
|
||||
|
@ -203,12 +204,14 @@ int main(int argc, char **argv) {
|
|||
do {
|
||||
global.game_over = 0;
|
||||
init_player(&global.plr);
|
||||
global.plr.cha = a.plrcha;
|
||||
global.plr.shot = a.plrshot;
|
||||
stage_loop(stg);
|
||||
} while(global.game_over == GAMEOVER_RESTART);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
MenuData menu;
|
||||
create_main_menu(&menu);
|
||||
menu_loop(&menu);
|
||||
|
|
|
@ -575,3 +575,19 @@ int plrmode_repr(char *out, size_t outsize, Character pchar, ShotMode pshot) {
|
|||
|
||||
return snprintf(out, outsize, "%s%c", plr, sht);
|
||||
}
|
||||
|
||||
// Inverse of plrmode_repr. Sets cha/shot according to name. Returns 0 iff the name is valid.
|
||||
int plrmode_parse(const char *name, Character *cha, ShotMode *shot) {
|
||||
if(!strcmp(name,"marisaA")) {
|
||||
*cha = Marisa; *shot = MarisaLaser;
|
||||
} else if(!strcmp(name,"marisaB")) {
|
||||
*cha = Marisa; *shot = MarisaStar;
|
||||
} else if(!strcmp(name,"youmuA")) {
|
||||
*cha = Youmu; *shot = YoumuOpposite;
|
||||
} else if(!strcmp(name,"youmuB")) {
|
||||
*cha = Youmu; *shot = YoumuHoming;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,5 +31,6 @@ void marisa_power(Player *plr, short npow);
|
|||
|
||||
/* Misc */
|
||||
int plrmode_repr(char *out, size_t outsize, Character pchar, ShotMode pshot);
|
||||
int plrmode_parse(const char *name, Character *cha, ShotMode *shot);
|
||||
|
||||
#endif
|
||||
|
|
18
src/replay.c
18
src/replay.c
|
@ -633,23 +633,24 @@ int replay_test(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void replay_play(Replay *rpy, int firststage) {
|
||||
void replay_play(Replay *rpy, int firststageid) {
|
||||
if(rpy != &global.replay) {
|
||||
replay_copy(&global.replay, rpy, true);
|
||||
}
|
||||
|
||||
global.replaymode = REPLAY_PLAY;
|
||||
|
||||
if(global.replay.numstages == 1) {
|
||||
firststage = 0;
|
||||
}
|
||||
|
||||
for(int i = firststage; i < global.replay.numstages; ++i) {
|
||||
bool skip = true;
|
||||
for(int i = 0; i < global.replay.numstages; ++i) {
|
||||
ReplayStage *rstg = global.replay_stage = global.replay.stages+i;
|
||||
if(rstg->stage == firststageid)
|
||||
skip = false;
|
||||
if(skip)
|
||||
continue;
|
||||
StageInfo *gstg = stage_get(rstg->stage);
|
||||
|
||||
if(!gstg) {
|
||||
log_warn("Invalid stage %d in replay at %i skipped.\n", rstg->stage, i);
|
||||
log_warn("Invalid stage %x in replay at %i skipped.", rstg->stage, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -662,6 +663,9 @@ void replay_play(Replay *rpy, int firststage) {
|
|||
global.game_over = 0;
|
||||
}
|
||||
|
||||
if(skip == true)
|
||||
log_warn("Stage %x was not found in the replay", firststageid);
|
||||
|
||||
global.game_over = 0;
|
||||
global.replaymode = REPLAY_RECORD;
|
||||
replay_destroy(&global.replay);
|
||||
|
|
Loading…
Reference in a new issue