X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftape.c;h=642ce5c399d814bac1b65a967fe35aa09b306390;hb=a047db7b385f7523ca97deb21fdc504f34a80c7e;hp=44bbc57bcbe440274f30575c61e5f462207c19ce;hpb=dfe534c10c9825cafd54961c60fc81a56691dc55;p=rocksndiamonds.git diff --git a/src/tape.c b/src/tape.c index 44bbc57b..642ce5c3 100644 --- a/src/tape.c +++ b/src/tape.c @@ -1,7 +1,7 @@ /*********************************************************** * Rocks'n'Diamonds -- McDuffin Strikes Back! * *----------------------------------------------------------* -* (c) 1995-2001 Artsoft Entertainment * +* (c) 1995-2002 Artsoft Entertainment * * Holger Schemel * * Detmolder Strasse 189 * * 33604 Bielefeld * @@ -14,6 +14,7 @@ #include "libgame/libgame.h" #include "tape.h" +#include "init.h" #include "game.h" #include "tools.h" #include "files.h" @@ -22,15 +23,20 @@ /* tape button identifiers */ #define TAPE_CTRL_ID_EJECT 0 -#define TAPE_CTRL_ID_STOP 1 -#define TAPE_CTRL_ID_PAUSE 2 -#define TAPE_CTRL_ID_RECORD 3 -#define TAPE_CTRL_ID_PLAY 4 +#define TAPE_CTRL_ID_INDEX 1 +#define TAPE_CTRL_ID_STOP 2 +#define TAPE_CTRL_ID_PAUSE 3 +#define TAPE_CTRL_ID_RECORD 4 +#define TAPE_CTRL_ID_PLAY 5 -#define NUM_TAPE_BUTTONS 5 +#define NUM_TAPE_BUTTONS 6 + +/* values for tape handling */ +#define TAPE_PAUSE_SECONDS_BEFORE_DEATH 5 /* forward declaration for internal use */ static void HandleTapeButtons(struct GadgetInfo *); +static void TapeStopIndexSearch(); static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS]; @@ -44,7 +50,7 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS]; #define VIDEO_DATE_LABEL_YPOS (VIDEO_DISPLAY1_YPOS) #define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE) #define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE) -#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS + 1) +#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS + 2) #define VIDEO_DATE_YPOS (VIDEO_DISPLAY1_YPOS + 14) #define VIDEO_DATE_XSIZE (VIDEO_DISPLAY_XSIZE) #define VIDEO_DATE_YSIZE 16 @@ -72,7 +78,7 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS]; #define VIDEO_PAUSE_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) #define VIDEO_PAUSE_SYMBOL_XSIZE 17 #define VIDEO_PAUSE_SYMBOL_YSIZE 13 -#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS + 38) +#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS + 39) #define VIDEO_TIME_YPOS (VIDEO_DISPLAY2_YPOS + 14) #define VIDEO_TIME_XSIZE 50 #define VIDEO_TIME_YSIZE 16 @@ -162,7 +168,7 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) { int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2; - BlitBitmap(pix[PIX_DOOR], drawto, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, cx + VIDEO_REC_LABEL_XPOS, cy + VIDEO_REC_LABEL_YPOS, VIDEO_PBEND_LABEL_XSIZE, @@ -171,7 +177,7 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) VY + VIDEO_REC_LABEL_YPOS); } - for(i=0;i<10;i++) + for (i = 0; i < 10; i++) { if (state & (1< STATE_OFF / PRESS_ON */ if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY) - BlitBitmap(pix[PIX_DOOR], drawto, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, cx + video_pos[pos][part_label][xpos], cy + video_pos[pos][part_label][ypos], video_pos[pos][part_label][xsize], @@ -191,7 +197,7 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) VX + video_pos[pos][part_label][xpos], VY + video_pos[pos][part_label][ypos]); if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY) - BlitBitmap(pix[PIX_DOOR], drawto, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, cx + video_pos[pos][part_symbol][xpos], cy + video_pos[pos][part_symbol][ypos], video_pos[pos][part_symbol][xsize], @@ -205,7 +211,7 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) { int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2; - BlitBitmap(pix[PIX_DOOR], drawto, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, cx + VIDEO_PLAY_SYMBOL_XPOS, cy + VIDEO_PLAY_SYMBOL_YPOS, VIDEO_PLAY_SYMBOL_XSIZE - 2, @@ -218,7 +224,7 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) { int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1; - BlitBitmap(pix[PIX_DOOR], drawto, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, cx + VIDEO_PBEND_LABEL_XPOS, cy + VIDEO_PBEND_LABEL_YPOS, VIDEO_PBEND_LABEL_XSIZE, @@ -233,12 +239,12 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) int monat = (value/100) % 100; int jahr = (value/10000); - DrawText(VX+VIDEO_DATE_XPOS,VY+VIDEO_DATE_YPOS, - int2str(tag,2),FS_SMALL,FC_SPECIAL1); - DrawText(VX+VIDEO_DATE_XPOS+27,VY+VIDEO_DATE_YPOS, - monatsname[monat],FS_SMALL,FC_SPECIAL1); - DrawText(VX+VIDEO_DATE_XPOS+64,VY+VIDEO_DATE_YPOS, - int2str(jahr,2),FS_SMALL,FC_SPECIAL1); + DrawText(VX + VIDEO_DATE_XPOS, VY + VIDEO_DATE_YPOS, + int2str(tag, 2), FONT_TAPE_RECORDER); + DrawText(VX + VIDEO_DATE_XPOS + 27, VY + VIDEO_DATE_YPOS, + monatsname[monat], FONT_TAPE_RECORDER); + DrawText(VX + VIDEO_DATE_XPOS + 64, VY + VIDEO_DATE_YPOS, + int2str(jahr, 2), FONT_TAPE_RECORDER); } if (state & VIDEO_STATE_TIME_ON) @@ -246,10 +252,10 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) int min = value / 60; int sec = value % 60; - DrawText(VX+VIDEO_TIME_XPOS,VY+VIDEO_TIME_YPOS, - int2str(min,2),FS_SMALL,FC_SPECIAL1); - DrawText(VX+VIDEO_TIME_XPOS+27,VY+VIDEO_TIME_YPOS, - int2str(sec,2),FS_SMALL,FC_SPECIAL1); + DrawText(VX + VIDEO_TIME_XPOS, VY + VIDEO_TIME_YPOS, + int2str(min, 2), FONT_TAPE_RECORDER); + DrawText(VX + VIDEO_TIME_XPOS + 27, VY + VIDEO_TIME_YPOS, + int2str(sec, 2), FONT_TAPE_RECORDER); } if (state & VIDEO_STATE_DATE) @@ -262,9 +268,10 @@ void DrawVideoDisplay(unsigned long state, unsigned long value) void DrawCompleteVideoDisplay() { - BlitBitmap(pix[PIX_DOOR], drawto, DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, + DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2, gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy); - BlitBitmap(pix[PIX_DOOR], drawto, + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, DOOR_GFX_PAGEX4 + VIDEO_CONTROL_XPOS, DOOR_GFX_PAGEY2 + VIDEO_CONTROL_YPOS, VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE, @@ -277,7 +284,7 @@ void DrawCompleteVideoDisplay() DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds); } - BlitBitmap(drawto, pix[PIX_DB_DOOR], gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize, + BlitBitmap(drawto, bitmap_db_door, gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2); } @@ -286,97 +293,156 @@ void DrawCompleteVideoDisplay() /* tape control functions */ /* ========================================================================= */ -void TapeStartRecording() +void TapeErase() { - time_t zeit1 = time(NULL); - struct tm *zeit2 = localtime(&zeit1); + time_t epoch_seconds = time(NULL); + struct tm *time = localtime(&epoch_seconds); int i; - if (!TAPE_IS_STOPPED(tape)) - TapeStop(); - - tape.level_nr = level_nr; tape.length = 0; tape.counter = 0; + + if (leveldir_current) + setString(&tape.level_identifier, leveldir_current->identifier); + + tape.level_nr = level_nr; tape.pos[tape.counter].delay = 0; - tape.recording = TRUE; - tape.playing = FALSE; - tape.pausing = FALSE; tape.changed = TRUE; - tape.date = 10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday; + + tape.date = 10000*(time->tm_year % 100) + 100*time->tm_mon + time->tm_mday; tape.random_seed = InitRND(NEW_RANDOMIZE); - for(i=0; i= MAX_TAPELEN-1) - { - TapeStopRecording(); - return; - } + TapeHaltRecording(); - for(i=0; i= MAX_TAPELEN-1) + if (tape.counter >= MAX_TAPELEN - 1) { TapeStopRecording(); return; } +#if 0 + printf("::: %05d: recording action: %d\n", FrameCounter, action[0]); +#endif + if (tape.pos[tape.counter].delay > 0) /* already stored action */ { boolean changed_events = FALSE; - for(i=0; i= MAX_TAPELEN) - { - TapeStopRecording(); - return; - } - - tape.pos[tape.counter].delay++; + printf("::: %05d: new sequence\n", FrameCounter); +#endif - if (tape.pos[tape.counter].delay >= 255) - { - for(i=0; i= tape.length) - { - TapeStop(); - return(NULL); - } - - if (tape.delay_played == tape.pos[tape.counter].delay) - { - tape.delay_played = 0; - tape.counter++; - - for(i=0; i tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH) { - TapeTogglePause(); + TapeTogglePause(TAPE_TOGGLE_MANUAL); return NULL; } } - if (tape.counter >= tape.length) + if (tape.counter >= tape.length) /* end of tape reached */ { - TapeStop(); + if (tape.index_search && !tape.auto_play) + TapeTogglePause(TAPE_TOGGLE_MANUAL); + else + TapeStop(); + return NULL; } - for(i=0; i tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH) - { - TapeTogglePause(); - return(FALSE); - } - } + for (i = 0; i < tape.length; i++) + tape_length += tape.pos[i].delay; + + return(tape_length * GAME_FRAME_DELAY / 1000); +} - if (tape.counter >= tape.length) +static void TapeStartIndexSearch() +{ + tape.index_search = TRUE; + + if (!tape.fast_forward || tape.pause_before_death) { - TapeStop(); - return(TRUE); + tape.pausing = FALSE; + + SetDrawDeactivationMask(REDRAW_FIELD); + audio.sound_deactivated = TRUE; } +} - if (tape.delay_played < tape.pos[tape.counter].delay) +static void TapeStopIndexSearch() +{ + tape.index_search = FALSE; + + SetDrawDeactivationMask(REDRAW_NONE); + audio.sound_deactivated = FALSE; + +#if 1 + if (game_status == GAME_MODE_PLAYING) +#endif { - tape.delay_played++; - return(TRUE); + RedrawPlayfield(TRUE, 0,0,0,0); + DrawGameDoorValues(); } - else - return(FALSE); } -#else - -boolean TapePlayDelay() +static void TapeSingleStep() { - return TRUE|FALSE; /* ...it doesn't matter at all */ + if (options.network) + return; + + if (!tape.pausing) + TapeTogglePause(TAPE_TOGGLE_MANUAL); + + tape.single_step = !tape.single_step; } -#endif -void TapeStop() +void TapeQuickSave() { - TapeStopRecording(); - TapeStopPlaying(); + if (game_status == GAME_MODE_PLAYING) + { + if (tape.recording) + TapeHaltRecording(); /* prepare tape for saving on-the-fly */ - DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0); - if (tape.date && tape.length) + if (TAPE_IS_EMPTY(tape)) + Request("No tape that can be saved !", REQ_CONFIRM); + else + SaveTape(tape.level_nr); + } + else if (game_status == GAME_MODE_MAIN) + Request("No game that can be saved !", REQ_CONFIRM); +} + +void TapeQuickLoad() +{ + if (game_status == GAME_MODE_PLAYING || game_status == GAME_MODE_MAIN) { - DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date); - DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds); + TapeStop(); + TapeErase(); + + LoadTape(level_nr); + if (!TAPE_IS_EMPTY(tape)) + { + TapeStartGamePlaying(); + TapeStartIndexSearch(); + + tape.quick_resume = TRUE; + } + else + Request("No tape for this level !", REQ_CONFIRM); } } -void TapeErase() +void InsertSolutionTape() { - tape.length = 0; + if (!TAPE_IS_EMPTY(tape)) + return; + + LoadSolutionTape(level_nr); + + if (TAPE_IS_EMPTY(tape)) + Request("No solution tape for this level !", REQ_CONFIRM); + + DrawCompleteVideoDisplay(); } -unsigned int GetTapeLength() + +/* ------------------------------------------------------------------------- * + * tape autoplay functions + * ------------------------------------------------------------------------- */ + +#define MAX_NUM_AUTOPLAY_LEVELS 1000 + +void AutoPlayTape() { - unsigned int tape_length = 0; + static LevelDirTree *autoplay_leveldir = NULL; + static boolean autoplay_initialized = FALSE; + static int autoplay_level_nr = -1; + static int num_levels_played = 0; + static int num_levels_solved = 0; + static boolean levels_failed[MAX_NUM_AUTOPLAY_LEVELS]; int i; - if (TAPE_IS_EMPTY(tape)) - return(0); + if (autoplay_initialized) + { + /* just finished auto-playing tape */ + printf("%s.\n", tape.auto_play_level_solved ? "solved" : "NOT SOLVED"); + + num_levels_played++; + if (tape.auto_play_level_solved) + num_levels_solved++; + else if (level_nr >= 0 && level_nr < MAX_NUM_AUTOPLAY_LEVELS) + levels_failed[level_nr] = TRUE; + } + else + { + DrawCompleteVideoDisplay(); + audio.sound_enabled = FALSE; - for(i=0;ifirst_level = global.autoplay_level_nr; + autoplay_leveldir->last_level = global.autoplay_level_nr; + } + + autoplay_level_nr = autoplay_leveldir->first_level; + + printf_line("=", 79); + printf("Automatically playing level tapes\n"); + printf_line("-", 79); + printf("Level series identifier: '%s'\n", autoplay_leveldir->identifier); + printf("Level series name: '%s'\n", autoplay_leveldir->name); + printf("Level series author: '%s'\n", autoplay_leveldir->author); + printf("Number of levels: %d\n", autoplay_leveldir->levels); + printf_line("=", 79); + printf("\n"); + + for (i = 0; i < MAX_NUM_AUTOPLAY_LEVELS; i++) + levels_failed[i] = FALSE; + + autoplay_initialized = TRUE; + } + + while (autoplay_level_nr <= autoplay_leveldir->last_level) + { + level_nr = autoplay_level_nr++; + + TapeErase(); + + printf("Level %03d: ", level_nr); + + LoadLevel(level_nr); + if (level.no_valid_file) + { + printf("(no level)\n"); + continue; + } + + LoadSolutionTape(level_nr); +#if 1 + if (tape.no_valid_file) +#else + if (TAPE_IS_EMPTY(tape)) +#endif + { + printf("(no tape)\n"); + continue; + } + + printf("playing tape ... "); + + TapeStartGamePlaying(); + TapeStartIndexSearch(); + + return; + } + + printf("\n"); + printf_line("=", 79); + printf("Number of levels played: %d\n", num_levels_played); + printf("Number of levels solved: %d (%d%%)\n", num_levels_solved, + (num_levels_played ? num_levels_solved * 100 / num_levels_played :0)); + printf_line("-", 79); + printf("Summary (for automatic parsing by scripts):\n"); + printf("LEVELDIR '%s', SOLVED %d/%d (%d%%)", + autoplay_leveldir->identifier, num_levels_solved, num_levels_played, + (num_levels_played ? num_levels_solved * 100 / num_levels_played :0)); + if (num_levels_played != num_levels_solved) + { + printf(", FAILED:"); + for (i = 0; i < MAX_NUM_AUTOPLAY_LEVELS; i++) + if (levels_failed[i]) + printf(" %03d", i); + } + printf("\n"); + printf_line("=", 79); + + CloseAllAndExit(0); } + /* ---------- new tape button stuff ---------------------------------------- */ /* graphic position values for tape buttons */ @@ -648,6 +865,7 @@ unsigned int GetTapeLength() #define TAPE_BUTTON_YPOS 77 #define TAPE_BUTTON_EJECT_XPOS (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE) +#define TAPE_BUTTON_INDEX_XPOS (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE) #define TAPE_BUTTON_STOP_XPOS (TAPE_BUTTON_XPOS + 1 * TAPE_BUTTON_XSIZE) #define TAPE_BUTTON_PAUSE_XPOS (TAPE_BUTTON_XPOS + 2 * TAPE_BUTTON_XSIZE) #define TAPE_BUTTON_RECORD_XPOS (TAPE_BUTTON_XPOS + 3 * TAPE_BUTTON_XSIZE) @@ -665,6 +883,11 @@ static struct TAPE_CTRL_ID_EJECT, "eject tape" }, + { + TAPE_BUTTON_INDEX_XPOS, TAPE_BUTTON_YPOS, + TAPE_CTRL_ID_INDEX, + "index mark" + }, { TAPE_BUTTON_STOP_XPOS, TAPE_BUTTON_YPOS, TAPE_CTRL_ID_STOP, @@ -691,9 +914,9 @@ void CreateTapeButtons() { int i; - for (i=0; icustom_id; - if (game_status != MAINMENU && game_status != PLAYING) + if (game_status != GAME_MODE_MAIN && game_status != GAME_MODE_PLAYING) return; switch (id) @@ -768,43 +1021,30 @@ static void HandleTapeButtons(struct GadgetInfo *gi) DrawCompleteVideoDisplay(); break; + case TAPE_CTRL_ID_INDEX: + if (tape.playing) + TapeStartIndexSearch(); + else if (tape.recording) + TapeSingleStep(); + break; + case TAPE_CTRL_ID_STOP: TapeStop(); break; case TAPE_CTRL_ID_PAUSE: - TapeTogglePause(); + TapeTogglePause(TAPE_TOGGLE_MANUAL); break; case TAPE_CTRL_ID_RECORD: if (TAPE_IS_STOPPED(tape)) - { - TapeStartRecording(); - -#if defined(PLATFORM_UNIX) - if (options.network) - SendToServer_StartPlaying(); - else -#endif - { - game_status = PLAYING; - StopAnimation(); - InitGame(); - } - } + TapeStartGameRecording(); else if (tape.pausing) { if (tape.playing) /* PLAYING -> PAUSING -> RECORDING */ - { - tape.pos[tape.counter].delay = tape.delay_played; - tape.playing = FALSE; - tape.recording = TRUE; - tape.changed = TRUE; - - DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON,0); - } + TapeAppendRecording(); else - TapeTogglePause(); + TapeTogglePause(TAPE_TOGGLE_MANUAL); } break; @@ -814,27 +1054,25 @@ static void HandleTapeButtons(struct GadgetInfo *gi) if (TAPE_IS_STOPPED(tape)) { - TapeStartPlaying(); - - game_status = PLAYING; - StopAnimation(); - InitGame(); + TapeStartGamePlaying(); } else if (tape.playing) { if (tape.pausing) /* PAUSE -> PLAY */ - TapeTogglePause(); + { + TapeTogglePause(TAPE_TOGGLE_MANUAL); + } else if (!tape.fast_forward) /* PLAY -> FAST FORWARD PLAY */ { tape.fast_forward = TRUE; DrawVideoDisplay(VIDEO_STATE_FFWD_ON, 0); } - else if (!tape.pause_before_death) /* FFWD PLAY -> + AUTO PAUSE */ + else if (!tape.pause_before_death) /* FFWD PLAY -> AUTO PAUSE */ { tape.pause_before_death = TRUE; DrawVideoDisplay(VIDEO_STATE_PBEND_ON, VIDEO_DISPLAY_LABEL_ONLY); } - else /* -> NORMAL PLAY */ + else /* AUTO PAUSE -> NORMAL PLAY */ { tape.fast_forward = FALSE; tape.pause_before_death = FALSE;