/* term.cpp - Don Yang (uguu.org) The biggest inside joke in an inside joke? 12/31/00 */ #include"global.h" #include"bg.h" #include"game.h" #include"images.h" #include"input.h" #include"objinfo.h" #include"resource.h" #include"sprite.h" #include"term.h" #define LINE_HEIGHT (h_font / FONT_CHAR_COUNT) #define TERM_WIDTH ((APP_WIDTH - (2 * GRID_MARGIN)) / w_font) #define TERM_HEIGHT ((APP_HEIGHT - (2 * GRID_MARGIN)) / LINE_HEIGHT) #define ITEM_WIDTH 10 #define ITEM_COLUMNS 4 enum { TERMINAL_PROMPT, TERMINAL_EDIT, BLUE_SCREEN_OF_DEATH }; enum { ITEM_OBJECT, ITEM_PLAYER, ITEM_IMAGE, ITEM_MISC }; enum { ITEM_BG, ITEM_BGFX, ITEM_CREDITS, ITEM_CURRENT, ITEM_DD, ITEM_DISPLAY, ITEM_EXEC, ITEM_FONT, ITEM_FPS, ITEM_GAME, ITEM_GFX, ITEM_GLOBAL, ITEM_INPUT, ITEM_JOYSTICK, ITEM_LABEL0, ITEM_LABEL1, ITEM_LABEL2, ITEM_LABEL3, ITEM_LICENSE, ITEM_LOG, ITEM_MAIN, ITEM_NUMBERS, ITEM_OPTIONS, ITEM_PLAYER0, ITEM_PLAYER1, ITEM_PLAYER2, ITEM_PLAYER3, ITEM_PLAYER4, ITEM_PLAYER5, ITEM_PLAYER6, ITEM_PLAYER7, ITEM_PLAYER8, ITEM_PLAYER9, ITEM_SOUND, ITEM_SPRITE, ITEM_SPRITEFX, ITEM_STATE, ITEM_TERM, ITEM_TILES, ITEM_TITLE, ITEM_VERSION, ITEM_WINDOZE, ITEM_COUNT }; static ItemInfo Item[ITEM_COUNT] = { {"bg", ITEM_OBJECT}, // ITEM_BG {"bgfx", ITEM_OBJECT}, // ITEM_BGFX {"credits", ITEM_MISC}, // ITEM_CREDITS {"current", ITEM_PLAYER}, // ITEM_CURRENT {"dd", ITEM_OBJECT}, // ITEM_DD {"display", ITEM_MISC}, // ITEM_DISPLAY {"exec", ITEM_MISC}, // ITEM_EXEC {"font", ITEM_IMAGE}, // ITEM_FONT {"fps", ITEM_MISC}, // ITEM_FPS {"game", ITEM_OBJECT}, // ITEM_GAME {"gfx", ITEM_OBJECT}, // ITEM_GFX {"global", ITEM_OBJECT}, // ITEM_GLOBAL {"input", ITEM_OBJECT}, // ITEM_INPUT {"joystick", ITEM_MISC}, // ITEM_JOYSTICK {"label0", ITEM_IMAGE}, // ITEM_LABEL0 {"label1", ITEM_IMAGE}, // ITEM_LABEL1 {"label2", ITEM_IMAGE}, // ITEM_LABEL2 {"label3", ITEM_IMAGE}, // ITEM_LABEL3 {"license", ITEM_MISC}, // ITEM_LICENSE {"log", ITEM_OBJECT}, // ITEM_LOG {"main", ITEM_OBJECT}, // ITEM_MAIN {"numbers", ITEM_IMAGE}, // ITEM_NUMBERS {"options", ITEM_MISC}, // ITEM_OPTIONS {"player0", ITEM_PLAYER}, // ITEM_PLAYER0 {"player1", ITEM_PLAYER}, // ITEM_PLAYER1 {"player2", ITEM_PLAYER}, // ITEM_PLAYER2 {"player3", ITEM_PLAYER}, // ITEM_PLAYER3 {"player4", ITEM_PLAYER}, // ITEM_PLAYER4 {"player5", ITEM_PLAYER}, // ITEM_PLAYER5 {"player6", ITEM_PLAYER}, // ITEM_PLAYER6 {"player7", ITEM_PLAYER}, // ITEM_PLAYER7 {"player8", ITEM_PLAYER}, // ITEM_PLAYER8 {"player9", ITEM_PLAYER}, // ITEM_PLAYER9 {"sound", ITEM_OBJECT}, // ITEM_SOUND {"sprite", ITEM_OBJECT}, // ITEM_SPRITE {"spritefx", ITEM_OBJECT}, // ITEM_SPRITEFX {"state", ITEM_MISC}, // ITEM_STATE {"term", ITEM_OBJECT}, // ITEM_TERM {"tiles", ITEM_IMAGE}, // ITEM_TILES {"title", ITEM_IMAGE}, // ITEM_TITLE {"version", ITEM_MISC}, // ITEM_VERSION {"windoze", ITEM_OBJECT} }; // ITEM_WINDOZE static ObjInfo Object[OBJ_COUNT]; static ImgInfo Image[IMG_COUNT]; static char TermScreen[TERM_HEIGHT][64]; static int TermTop = 0; static int TermTop0 = -1; static int PromptLen = 2; static int TermState = TERMINAL_PROMPT; static void CmdCat(char *cmd); static void CmdDate(void); static void CmdEd(char *cmd); static void CmdLs(char *cmd); static void CmdRank(char *cmd); static char *GetCmdArg(char *cmd); static void InfoImage(int index); static void InfoMisc(int index); static int InfoObject(int index); static void InfoPlayer(int index); static void PrintLine(char *text); static void ProcessCmd(char *text); static void ScrollTerm(void); static void ShowPrompt(char *prompt); /****************************************************************** InitTerm Initialize terminal. */ void InitTerm(void) { int i, j; for(i = 0; i < TERM_HEIGHT; i++) for(j = 0; j < 64; TermScreen[i][j++] = 0); TermTop = 0; TermTop0 = -1; TermState = TERMINAL_PROMPT; Object[0].name = Item[ITEM_BG].name; Object[1].name = Item[ITEM_BGFX].name; Object[2].name = Item[ITEM_DD].name; Object[3].name = Item[ITEM_GAME].name; Object[4].name = Item[ITEM_GFX].name; Object[5].name = Item[ITEM_GLOBAL].name; Object[6].name = Item[ITEM_INPUT].name; Object[7].name = Item[ITEM_LOG].name; Object[8].name = Item[ITEM_MAIN].name; Object[9].name = Item[ITEM_SOUND].name; Object[10].name = Item[ITEM_SPRITE].name; Object[11].name = Item[ITEM_SPRITEFX].name; Object[12].name = Item[ITEM_TERM].name; Object[13].name = Item[ITEM_WINDOZE].name; Object[0].time = BgObjTime; Object[0].lines = BgObjLines; Object[1].time = BgfxObjTime; Object[1].lines = BgfxObjLines; Object[2].time = DdObjTime; Object[2].lines = DdObjLines; Object[3].time = GameObjTime; Object[3].lines = GameObjLines; Object[4].time = GfxObjTime; Object[4].lines = GfxObjLines; Object[5].time = GlobalObjTime; Object[5].lines = GlobalObjLines; Object[6].time = InputObjTime; Object[6].lines = InputObjLines; Object[7].time = LogObjTime; Object[7].lines = LogObjLines; Object[8].time = MainObjTime; Object[8].lines = MainObjLines; Object[9].time = SoundObjTime; Object[9].lines = SoundObjLines; Object[10].time = SpriteObjTime; Object[10].lines = SpriteObjLines; Object[11].time = SpritefxObjTime; Object[11].lines = SpritefxObjLines; Object[12].time = TermObjTime; Object[12].lines = TermObjLines; Object[13].time = WindozeObjTime; Object[13].lines = WindozeObjLines; Image[0].name = Item[ITEM_FONT].name; Image[1].name = Item[ITEM_LABEL0].name; Image[2].name = Item[ITEM_LABEL1].name; Image[3].name = Item[ITEM_LABEL2].name; Image[4].name = Item[ITEM_LABEL3].name; Image[5].name = Item[ITEM_NUMBERS].name; Image[6].name = Item[ITEM_TILES].name; Image[7].name = Item[ITEM_TITLE].name; Image[0].width = w_font; Image[0].height = h_font; Image[1].width = w_label0; Image[1].height = h_label0; Image[2].width = w_label1; Image[2].height = h_label1; Image[3].width = w_label2; Image[3].height = h_label2; Image[4].width = w_label3; Image[4].height = h_label3; Image[5].width = w_numbers; Image[5].height = h_numbers; Image[6].width = w_tiles; Image[6].height = h_tiles; Image[7].width = w_title; Image[7].height = h_title; PrintLine(APP_VERSION); PrintLine("Ruri-ruri mode"); PrintLine(""); ShowPrompt(PROMPT_STRING); } // InitTerm() /**************************************************************** RenderTerm Render terminal screen. */ void RenderTerm(DWORD screen) { int i; if( TermState == BLUE_SCREEN_OF_DEATH ) { AnimateBackground(); PaintBackground(screen); } else { if( (FrameCount & BG_CHANGE_FREQ) == 0 ) AnimateBackground(); if( RedrawAll || TermTop0 != TermTop ) { // Redraw terminal completely PaintBackground(screen); for(i = 0; i < TERM_HEIGHT; i++) { DrawText(screen, GRID_MARGIN, GRID_MARGIN + i * LINE_HEIGHT, TermScreen[(TermTop + i) % TERM_HEIGHT]); } TermTop0 = TermTop; RedrawAll = FALSE; } else { // Redraw just the last line RepaintBackgroundA(screen, GRID_MARGIN, GRID_MARGIN + (TERM_HEIGHT - 1) * LINE_HEIGHT, APP_WIDTH - GRID_MARGIN * 2, LINE_HEIGHT); DrawText(screen, GRID_MARGIN, GRID_MARGIN + (TERM_HEIGHT - 1) * LINE_HEIGHT, TermScreen[(TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT]); } } } // RenderTerm() /************************************************************ TermKeyRelease Process keyboard input. */ void TermKeyRelease(int key) { int s, i; i = (TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT; s = strlen(TermScreen[i = ((TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT)]); if( TermState != BLUE_SCREEN_OF_DEATH ) { switch( key ) { case VK_RETURN: ScrollTerm(); ProcessCmd(TermScreen[i]); break; case VK_BACK: if( s > PromptLen ) TermScreen[i][s - 1] = 0; break; case KEY_TERMINAL: GameState = ResumeState; RedrawAll = TRUE; ShiftState = FALSE; break; default: if( s < TERM_WIDTH ) { key = Vk2Ascii(key); // (input.cpp) TermScreen[i][s] = (char)key; TermScreen[i][s + 1] = 0; } break; } } else { TermState = TERMINAL_PROMPT; ShowPrompt(PROMPT_STRING); } } // TermKeyRelease() /******************************************************************** CmdCat Show item information. */ static void CmdCat(char *cmd) { char text[64]; char *arg; int i, count, lines; // Glob object if( (arg = GetCmdArg(cmd)) == NULL ) { PrintLine("missing arg"); return; } // Show info on all matched objects for(i = count = lines = 0; i < ITEM_COUNT; i++) { if( !memcmp(Item[i].name, arg, strlen(arg)) ) { count++; sprintf(text, "%s:", Item[i].name); PrintLine(text); switch( Item[i].type ) { case ITEM_OBJECT: // Source object lines += InfoObject(i); break; case ITEM_PLAYER: // Player score InfoPlayer(i); break; case ITEM_IMAGE: // Image object InfoImage(i); break; default: // etc InfoMisc(i); break; } } } if( count == 0 ) { PrintLine("no match"); return; } if( count > 1 ) { sprintf(text, "%d objects", count); PrintLine(text); if( lines > 0 ) { sprintf(text, "\t\tlines = %d", lines); PrintLine(text); } } } // CmdCat() /******************************************************************* CmdDate Show current date and time. */ static void CmdDate(void) { time_t gtime; struct tm *ltime; time(>ime); ltime = localtime(>ime); PrintLine(asctime(ltime)); } // CmdDate() /********************************************************************* CmdEd Edit item values. */ static void CmdEd(char *cmd) { static PlayerEntry *p; static int EditObject = 0; static int EditParam = 0; char text[64]; char *arg; int i; if( TermState == TERMINAL_PROMPT ) { // Start editing if( (arg = GetCmdArg(cmd)) == NULL ) { PrintLine("missing arg"); return; } for(i = 0; i < ITEM_COUNT; i++) { if( !strcmp(Item[i].name, arg) ) { sprintf(text, "%s:", Item[i].name); PrintLine(text); EditObject = i; if( Item[i].type == ITEM_PLAYER ) { if( i == ITEM_CURRENT ) p = &CurrentPlayer; else p = &History[i - ITEM_PLAYER0]; EditParam = -1; TermState = TERMINAL_EDIT; ShowPrompt("\t\tname =\t"); } else if( i == ITEM_OPTIONS ) { TermState = TERMINAL_EDIT; ShowPrompt("\t\toptions =\t"); } else if( i == ITEM_FPS ) { TermState = TERMINAL_EDIT; ShowPrompt("\t\texpected fps =\t"); } else if( i == ITEM_EXEC ) { TermState = TERMINAL_EDIT; ShowPrompt("\t\texec count =\t"); } else { PrintLine("\t\tPermission denied"); } return; } } PrintLine("no match"); } else { // Edit current values i = atoi(cmd); if( EditObject == ITEM_OPTIONS ) // Game options { if( *cmd ) { GameOptions = (i < 0) ? OPTION_DEFAULT : (DWORD)i; InitSprites(); // (sprite.cpp) InitBackground(); // (bg.cpp) } InfoMisc(ITEM_OPTIONS); TermState = TERMINAL_PROMPT; ShowPrompt(PROMPT_STRING); } else if( EditObject == ITEM_FPS ) // Expected frame rate { if( !(*cmd) ) i = ExpectedFPS; if( i < 2 ) { PrintLine("\t\tinvalid value"); return; } MaxFrames = (ExpectedFPS = i) * 6000; InfoMisc(ITEM_FPS); TermState = TERMINAL_PROMPT; ShowPrompt(PROMPT_STRING); } else if( EditObject == ITEM_EXEC ) // Execution count { if( !(*cmd) ) i = ExecCount; if( i < 0 ) { PrintLine("\t\tinvalid value"); return; } ExecCount = i; InfoMisc(ITEM_EXEC); TermState = TERMINAL_PROMPT; ShowPrompt(PROMPT_STRING); } else // Score entry { switch( EditParam ) { case HISTORY_SCORE: if( *cmd ) p->data[HISTORY_SCORE] = (DWORD)i; if( p->data[HISTORY_SCORE] > MAX_SCORE ) p->data[HISTORY_SCORE] = MAX_SCORE; EditParam = HISTORY_CELLS; ShowPrompt("\t\tcells =\t"); break; case HISTORY_CELLS: if( *cmd ) p->data[HISTORY_CELLS] = (DWORD)i; EditParam = HISTORY_BLOCKS; ShowPrompt("\t\tblocks =\t"); break; case HISTORY_BLOCKS: if( *cmd ) p->data[HISTORY_BLOCKS] = (DWORD)i; EditParam = HISTORY_CLUSTER; ShowPrompt("\t\tclusters =\t"); break; case HISTORY_CLUSTER: if( *cmd ) p->data[HISTORY_CLUSTER] = (DWORD)i; EditParam = HISTORY_MAX_CHAIN; ShowPrompt("\t\tmax chain =\t"); break; case HISTORY_MAX_CHAIN: if( *cmd ) p->data[HISTORY_MAX_CHAIN] = (DWORD)i; EditParam = HISTORY_MAX_CLUSTER; ShowPrompt("\t\tmax cluster =\t"); break; case HISTORY_MAX_CLUSTER: if( *cmd ) p->data[HISTORY_MAX_CLUSTER] = (DWORD)i; EditParam = HISTORY_TIME; ShowPrompt("\t\ttime =\t"); break; case HISTORY_TIME: if( *cmd ) p->data[HISTORY_TIME] = (DWORD)i; SetCRC(p); // (game.cpp) sprintf(text, "\t\tcrc = 0x%08x", p->data[HISTORY_CRC]); PrintLine(text); TermState = TERMINAL_PROMPT; ShowPrompt(PROMPT_STRING); break; default: // name if( *cmd ) strncpy(p->n.name, cmd, MAX_NAME_LENGTH); EditParam = HISTORY_SCORE; ShowPrompt("\t\tscore =\t"); break; } } } } // CmdEd() /******************************************************************* CmdRank Show history table. */ static void CmdRank(char *cmd) { char text[64], string[64]; char *arg; int i, j, x; // Select display column arg = GetCmdArg(cmd); x = HISTORY_SCORE; if( arg != NULL ) { if( strstr(arg, "max") ) { if( strstr(arg, "cluster") ) x = HISTORY_MAX_CLUSTER; if( strstr(arg, "chain") ) x = HISTORY_MAX_CHAIN; } else { if( strstr(arg, "cell") ) x = HISTORY_CELLS; if( strstr(arg, "block") ) x = HISTORY_BLOCKS; if( strstr(arg, "cluster") ) x = HISTORY_CLUSTER; if( strstr(arg, "chain") ) x = HISTORY_MAX_CHAIN; if( strstr(arg, "time") ) x = HISTORY_TIME; if( strstr(arg, "crc") ) x = HISTORY_CRC; } } // Display label strcpy(text, "\t\t\t\t\t\tname" "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"); switch( x ) { case HISTORY_CELLS: strcat(text, "cells"); break; case HISTORY_BLOCKS: strcat(text, "blocks"); break; case HISTORY_CLUSTER: strcat(text, "cluster"); break; case HISTORY_MAX_CHAIN: strcat(text, "max chain"); break; case HISTORY_MAX_CLUSTER: strcat(text, "max cluster"); break; case HISTORY_TIME: strcat(text, "time"); break; case HISTORY_CRC: strcat(text, "crc"); break; default: strcat(text, "score"); x = HISTORY_SCORE; break; } PrintLine(text); // Show table for(i = 0; i < 10; i++) { for(j = 0; j < TERM_WIDTH - 1; text[j++] = '\t'); text[j] = 0; sprintf(string, "\t\t%2d.\t%s", i + 1, History[i].n.name); for(j = 0; string[j]; text[j++] = string[j]); sprintf(string, x == HISTORY_CRC ? "0x%08X" : "%u", History[i].data[x]); for(j = 0; string[j]; text[32 + j++] = string[j]); PrintLine(text); } } // CmdRank() /********************************************************************* CmdLs List items. */ static void CmdLs(char *cmd) { static char list[16][64]; char *arg; int i, r, c, match, rows; arg = GetCmdArg(cmd); // Count items for(i = match = 0; i < ITEM_COUNT; i++) { if( arg == NULL || !memcmp(Item[i].name, arg, strlen(arg)) ) match++; } if( match == 0 ) { PrintLine("no match"); return; } // Print items (column formatted) rows = match / ITEM_COLUMNS + ((match % ITEM_COLUMNS) ? 1 : 0); for(r = 0; r < rows; r++) { for(c = 0; c < TERM_WIDTH - 1; c++) list[r][c] = '\t'; list[r][c] = 0; } for(i = c = r = 0; i < ITEM_COUNT; i++) { if( arg == NULL || !memcmp(Item[i].name, arg, strlen(arg)) ) { memcpy(list[r] + c, Item[i].name, strlen(Item[i].name)); r++; if( r >= rows ) { r = 0; c += ITEM_WIDTH; } } } for(i = 0; i < rows; i++) PrintLine(list[i]); } // CmdLs() /***************************************************************** GetCmdArg Get command argument. */ static char *GetCmdArg(char *cmd) { static char token[64]; int i, j; for(i = PromptLen; cmd[i] && (cmd[i] != ' '); i++); if( !cmd[i] ) return NULL; memset(token, 0, 64); for(j = 0; cmd[i]; i++) { if( isalnum(cmd[i]) ) token[j++] = (char)tolower(cmd[i]); } return token; } // GetCmdArg() /***************************************************************** InfoImage Show image item information. */ static void InfoImage(int index) { char text[64]; int i; for(i = 0; i < IMG_COUNT; i++) { if( Image[i].name == Item[index].name ) { sprintf(text, "\t\twidth = %d", Image[i].width); PrintLine(text); sprintf(text, "\t\theight = %d", Image[i].height); PrintLine(text); return; } } } // InfoImage() /****************************************************************** InfoMisc Show in game parameter information. */ static void InfoMisc(int index) { char text[64]; switch( index ) { case ITEM_CREDITS: PrintLine("\t\tMany thanks to the people who tested"); PrintLine("\t\tOtika, including:"); PrintLine("\t\t\t\tSean Yang"); PrintLine("\t\t\t\tElliott Lee"); PrintLine("\t\t\t\tAdam Pace"); PrintLine("\t\t\t\tTom Weeks"); PrintLine("\t\t\t\tLinda Lu"); PrintLine(""); PrintLine("\t\tNadesico is copyrighted by Xebec"); break; case ITEM_DISPLAY: sprintf(text, "\t\tsize = (%d, %d)", ScreenWidth, ScreenHeight); PrintLine(text); strcpy(text, "\t\tpixel format = "); switch( PixelFormat ) { case PIXEL_1555: strcat(text, "1:5:5:5 (16bit)"); break; case PIXEL_565: strcat(text, "5:6:5 (16bit)"); break; case PIXEL_888: strcat(text, "8:8:8 (24bit)"); break; case PIXEL_8888: strcat(text, "8:8:8:8 (32bit)"); break; default: break; } PrintLine(text); break; case ITEM_EXEC: sprintf(text, "\t\texecute count = %d", ExecCount); PrintLine(text); break; case ITEM_FPS: sprintf(text, "\t\texpected fps = %d", ExpectedFPS); PrintLine(text); sprintf(text, "\t\tmaximum frames = %d", MaxFrames); PrintLine(text); sprintf(text, "\t\tactual fps = %d, %d, %d, %d", ActualFPS[ActualFPSindex], ActualFPS[(ActualFPSindex + 1) & 3], ActualFPS[(ActualFPSindex + 2) & 3], ActualFPS[(ActualFPSindex + 3) & 3]); PrintLine(text); break; case ITEM_JOYSTICK: if( JoystickCaptured ) { if( JoystickID == JOYSTICKID1 ) PrintLine("\t\tjoystick 1 captured"); else PrintLine("\t\tjoystick 2 captured"); } else { if( JoystickAvailable ) PrintLine("\t\tjoystick not captured"); else PrintLine("\t\tjoystick not available"); } break; case ITEM_OPTIONS: sprintf(text, "\t\toptions = %d", GameOptions); PrintLine(text); strcpy(text, "\t\tsound enabled (1) =\t\t\t\t\t\t\t\t\t\t"); strcat(text, (GameOptions & OPTION_SND_ALL) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\tblip sound enabled (2) =\t\t\t\t\t"); strcat(text, (GameOptions & OPTION_SND_BLIP) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\tclear sound enabled (4) =\t\t\t\t"); strcat(text, (GameOptions & OPTION_SND_CLEAR) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\tspecial sound enabled (8) =\t\t"); strcat(text, (GameOptions & OPTION_SND_SPECIAL) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\ttransparency enabled (16) =\t\t"); strcat(text, (GameOptions & OPTION_SPR_TRANSPARENT) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\ttranslucency enabled (32) =\t\t"); strcat(text, (GameOptions & OPTION_SPR_TRANSLUCENT) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\tbackground enabled (64) =\t\t\t\t"); strcat(text, (GameOptions & OPTION_BG_BACKGROUND) ? "yes" : "no"); PrintLine(text); strcpy(text, "\t\tanimated bg (128, 256) =\t\t\t\t\t"); switch( GameOptions & OPTION_BG_FX ) { case OPTION_BG_FRACTAL: strcat(text, "fractal"); break; case OPTION_BG_DUST: strcat(text, "dust"); break; case OPTION_BG_SWARM: strcat(text, "swarm"); break; default: strcat(text, "none"); break; } PrintLine(text); strcpy(text, "\t\twhite particles (512) =\t\t\t\t\t\t"); strcat(text, (GameOptions & OPTION_BG_WHITE_PARTICLE) ? "yes" : "no"); PrintLine(text); break; case ITEM_LICENSE: InfoMisc(ITEM_VERSION); PrintLine(""); PrintLine("\t\tThis program is free software, you can"); PrintLine("\t\tredistribute it and/or modify it under"); PrintLine("\t\tthe terms of the GNU General Public"); PrintLine("\t\tLicense as published by the Free"); PrintLine("\t\tSoftware Foundation; either version 2"); PrintLine("\t\tor any later version."); break; case ITEM_STATE: strcpy(text, "\t\tstate = "); switch( ResumeState ) { case GAME_STATE_WAIT_START: strcat(text, "WAIT_START"); break; case GAME_STATE_SHOW_HISTORY: strcat(text, "SHOW_HISTORY"); break; case GAME_STATE_GENERATE_BLOCK: strcat(text, "GENERATE_BLOCK"); break; case GAME_STATE_INPUT_LOOP: strcat(text, "INPUT_LOOP"); break; case GAME_STATE_CLEAR_SPECIAL: strcat(text, "CLEAR_SPECIAL"); break; case GAME_STATE_REMOVE_CLUSTER: strcat(text, "REMOVE_CLUSTER"); break; case GAME_STATE_MARK_CLUSTER: strcat(text, "MARK_CLUSTER"); break; case GAME_STATE_GAME_OVER0: strcat(text, "GAME_OVER0"); break; case GAME_STATE_GAME_OVER1: strcat(text, "GAME_OVER1"); break; case GAME_STATE_GAME_OVER2: strcat(text, "GAME_OVER2"); break; case GAME_STATE_GAME_OVER3: strcat(text, "GAME_OVER3"); break; case GAME_STATE_ENTER_NAME: strcat(text, "ENTER_NAME"); break; case GAME_STATE_SHOW_STATS: strcat(text, "SHOW_STATS"); break; default: strcat(text, "SYS_STATE"); break; } PrintLine(text); break; case ITEM_VERSION: PrintLine("\t\t" APP_VERSION); PrintLine("\t\t" APP_AUTHOR); break; default: // never reached break; } } // InfoMisc() /**************************************************************** InfoObject Show source object information. */ static int InfoObject(int index) { char text[64]; int i; for(i = 0; i < OBJ_COUNT; i++) { if( Object[i].name == Item[index].name ) { sprintf(text, "\t\ttime = %s", Object[i].time); PrintLine(text); sprintf(text, "\t\tlines = %d", Object[i].lines); PrintLine(text); return Object[i].lines; } } return 0; } // InfoObject() /**************************************************************** InfoPlayer Show score/statistics information. */ static void InfoPlayer(int index) { char text[64]; PlayerEntry *p; if( index == ITEM_CURRENT ) p = &CurrentPlayer; else p = &History[index - ITEM_PLAYER0]; sprintf(text, "\t\tname = %s", p->n.name); PrintLine(text); sprintf(text, "\t\tscore = %d", p->data[HISTORY_SCORE]); PrintLine(text); sprintf(text, "\t\tcells = %d", p->data[HISTORY_CELLS]); PrintLine(text); sprintf(text, "\t\tblocks = %d", p->data[HISTORY_BLOCKS]); PrintLine(text); sprintf(text, "\t\tclusters = %d", p->data[HISTORY_CLUSTER]); PrintLine(text); sprintf(text, "\t\tmax chain = %d", p->data[HISTORY_MAX_CHAIN]); PrintLine(text); sprintf(text, "\t\tmax cluster = %d", p->data[HISTORY_MAX_CLUSTER]); PrintLine(text); sprintf(text, "\t\ttime = %d", p->data[HISTORY_TIME]); PrintLine(text); sprintf(text, "\t\tcrc = 0x%08x", p->data[HISTORY_CRC]); PrintLine(text); } // InfoPlayer() /***************************************************************** PrintLine Write line of text to bottom of terminal, then scroll up. */ static void PrintLine(char *text) { strcpy(TermScreen[(TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT], text); TermTop = (TermTop + 1) % TERM_HEIGHT; TermScreen[(TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT][0] = 0; } // PrintLine() /**************************************************************** ProcessCmd Process command. */ static void ProcessCmd(char *text) { static char LastCmd[64] = "???"; if( TermState == TERMINAL_PROMPT ) { // Process terminal command LogMessage(text + 2); if( text[2] != '1' && text[2] != '!' ) strcpy(LastCmd, text); switch( text[2] ) { case 'B': // Blue screen of death TermState = BLUE_SCREEN_OF_DEATH; break; case 'C': // Show item information case 'I': if( strstr(text, "CLEAR") ) InitTerm(); else CmdCat(text); break; case 'D': // Current date/time case 'T': CmdDate(); break; case 'L': // List items CmdLs(text); break; case 'E': // Edit value case 'V': if( strstr(text, "EXIT") ) DestroyWindow(AppWindow); // Exit else CmdEd(text); break; case 'S': // Start game GameState = SYS_STATE_INIT; break; case 'R': // Ranking if( strstr(text, "RESET") ) { ResetOptions(); GameOptions = OPTION_DEFAULT; InitSprites(); } else { CmdRank(text); } break; case 'G': // Resume game GameState = ResumeState; RedrawAll = TRUE; break; case 'Q': // Exit game DestroyWindow(AppWindow); break; case '!': case '1': PrintLine(LastCmd + 2); ProcessCmd(LastCmd); break; default: PrintLine("\t\t!!\t\t\t\t\tdate\t\tgo\t\t\t\tquit\t\t\tstart"); PrintLine("\t\tcat\t\t\t\ted\t\t\t\tinfo\t\trank\t\t\ttime"); PrintLine("\t\tclear\t\texit\t\tls\t\t\t\treset\t\tvi"); PrintLine("\t\tblue screen of death"); break; } if( TermState == TERMINAL_PROMPT ) ShowPrompt(PROMPT_STRING); } else { // Edit item value CmdEd((char*)(text + PromptLen)); } } // ProcessCmd() /**************************************************************** ScrollTerm Scroll terminal screen. */ static void ScrollTerm(void) { TermTop = (TermTop + 1) % TERM_HEIGHT; TermScreen[(TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT][0] = 0; } // ScrollTerm() /**************************************************************** ShowPrompt Show command prompt symbol. */ static void ShowPrompt(char *prompt) { strcpy(TermScreen[(TermTop + TERM_HEIGHT - 1) % TERM_HEIGHT], prompt); PromptLen = strlen(prompt); } // ShowPrompt() char *TermObjTime = __TIME__ " " __DATE__; int TermObjLines = __LINE__;