home *** CD-ROM | disk | FTP | other *** search
/ GameStar Special 2004 August / GSSH0804.iso / Geschicklichkeit / RocksnDiamonds / rocksndiamonds.exe / rocksndiamonds-3.1.0 / src / tape.c < prev    next >
C/C++ Source or Header  |  2004-06-06  |  40KB  |  1,585 lines

  1. /***********************************************************
  2. * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
  3. *----------------------------------------------------------*
  4. * (c) 1995-2002 Artsoft Entertainment                      *
  5. *               Holger Schemel                             *
  6. *               Detmolder Strasse 189                      *
  7. *               33604 Bielefeld                            *
  8. *               Germany                                    *
  9. *               e-mail: info@artsoft.org                   *
  10. *----------------------------------------------------------*
  11. * tape.c                                                   *
  12. ***********************************************************/
  13.  
  14. #include "libgame/libgame.h"
  15.  
  16. #include "tape.h"
  17. #include "init.h"
  18. #include "game.h"
  19. #include "tools.h"
  20. #include "files.h"
  21. #include "network.h"
  22. #include "cartoons.h"
  23.  
  24. /* tape button identifiers */
  25. #define TAPE_CTRL_ID_EJECT            0
  26. #define TAPE_CTRL_ID_EXTRA            1
  27. #define TAPE_CTRL_ID_STOP            2
  28. #define TAPE_CTRL_ID_PAUSE            3
  29. #define TAPE_CTRL_ID_RECORD            4
  30. #define TAPE_CTRL_ID_PLAY            5
  31.  
  32. #define NUM_TAPE_BUTTONS            6
  33.  
  34. /* values for tape handling */
  35. #define TAPE_PAUSE_SECONDS_BEFORE_DEATH        5
  36.  
  37. /* forward declaration for internal use */
  38. static void HandleTapeButtons(struct GadgetInfo *);
  39. static void TapeStopWarpForward();
  40.  
  41. static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
  42.  
  43.  
  44. /* ========================================================================= */
  45. /* video tape definitions                                                    */
  46. /* ========================================================================= */
  47.  
  48. /* some positions in the video tape control window */
  49. #define VIDEO_DATE_LABEL_XPOS        (VIDEO_DISPLAY1_XPOS)
  50. #define VIDEO_DATE_LABEL_YPOS        (VIDEO_DISPLAY1_YPOS)
  51. #define VIDEO_DATE_LABEL_XSIZE        (VIDEO_DISPLAY_XSIZE)
  52. #define VIDEO_DATE_LABEL_YSIZE        (VIDEO_DISPLAY_YSIZE)
  53. #define VIDEO_DATE_XPOS            (VIDEO_DISPLAY1_XPOS + 2)
  54. #define VIDEO_DATE_YPOS            (VIDEO_DISPLAY1_YPOS + 14)
  55. #define VIDEO_DATE_XSIZE        (VIDEO_DISPLAY_XSIZE)
  56. #define VIDEO_DATE_YSIZE        16
  57. #define VIDEO_REC_LABEL_XPOS        (VIDEO_DISPLAY2_XPOS)
  58. #define VIDEO_REC_LABEL_YPOS        (VIDEO_DISPLAY2_YPOS)
  59. #define VIDEO_REC_LABEL_XSIZE        20
  60. #define VIDEO_REC_LABEL_YSIZE        12
  61. #define VIDEO_REC_SYMBOL_XPOS        (VIDEO_DISPLAY2_XPOS + 20)
  62. #define VIDEO_REC_SYMBOL_YPOS        (VIDEO_DISPLAY2_YPOS)
  63. #define VIDEO_REC_SYMBOL_XSIZE        16
  64. #define VIDEO_REC_SYMBOL_YSIZE        16
  65. #define VIDEO_PLAY_LABEL_XPOS        (VIDEO_DISPLAY2_XPOS + 65)
  66. #define VIDEO_PLAY_LABEL_YPOS        (VIDEO_DISPLAY2_YPOS)
  67. #define VIDEO_PLAY_LABEL_XSIZE        22
  68. #define VIDEO_PLAY_LABEL_YSIZE        12
  69. #define VIDEO_PLAY_SYMBOL_XPOS        (VIDEO_DISPLAY2_XPOS + 52)
  70. #define VIDEO_PLAY_SYMBOL_YPOS        (VIDEO_DISPLAY2_YPOS)
  71. #define VIDEO_PLAY_SYMBOL_XSIZE        11
  72. #define VIDEO_PLAY_SYMBOL_YSIZE        13
  73. #define VIDEO_PAUSE_LABEL_XPOS        (VIDEO_DISPLAY2_XPOS)
  74. #define VIDEO_PAUSE_LABEL_YPOS        (VIDEO_DISPLAY2_YPOS + 20)
  75. #define VIDEO_PAUSE_LABEL_XSIZE        35
  76. #define VIDEO_PAUSE_LABEL_YSIZE        8
  77. #define VIDEO_PAUSE_SYMBOL_XPOS        (VIDEO_DISPLAY2_XPOS + 35)
  78. #define VIDEO_PAUSE_SYMBOL_YPOS        (VIDEO_DISPLAY2_YPOS)
  79. #define VIDEO_PAUSE_SYMBOL_XSIZE    17
  80. #define VIDEO_PAUSE_SYMBOL_YSIZE    13
  81. #define VIDEO_TIME_XPOS            (VIDEO_DISPLAY2_XPOS + 39)
  82. #define VIDEO_TIME_YPOS            (VIDEO_DISPLAY2_YPOS + 14)
  83. #define VIDEO_TIME_XSIZE        50
  84. #define VIDEO_TIME_YSIZE        16
  85.  
  86. /* some default values for tape labels and symbols */
  87. #define VIDEO_LABEL_XPOS        5
  88. #define VIDEO_LABEL_YPOS        42
  89. #define VIDEO_LABEL_XSIZE        40
  90. #define VIDEO_LABEL_YSIZE        28
  91. #define VIDEO_SYMBOL_XPOS        39
  92. #define VIDEO_SYMBOL_YPOS        42
  93. #define VIDEO_SYMBOL_XSIZE        56
  94. #define VIDEO_SYMBOL_YSIZE        13
  95.  
  96. /* values for certain tape labels and symbols */
  97. #define VIDEO_FFWD_LABEL_XPOS        VIDEO_LABEL_XPOS
  98. #define VIDEO_FFWD_LABEL_YPOS        193
  99. #define VIDEO_FFWD_LABEL_XSIZE        VIDEO_LABEL_XSIZE
  100. #define VIDEO_FFWD_LABEL_YSIZE        VIDEO_LABEL_YSIZE
  101. #define VIDEO_FFWD_SYMBOL_XPOS        VIDEO_SYMBOL_XPOS
  102. #define VIDEO_FFWD_SYMBOL_YPOS        193
  103. #define VIDEO_FFWD_SYMBOL_XSIZE        27
  104. #define VIDEO_FFWD_SYMBOL_YSIZE        VIDEO_SYMBOL_YSIZE
  105.  
  106. #define VIDEO_PBEND_LABEL_XPOS        VIDEO_LABEL_XPOS
  107. #define VIDEO_PBEND_LABEL_YPOS        221
  108. #define VIDEO_PBEND_LABEL_XSIZE        VIDEO_LABEL_XSIZE
  109. #define VIDEO_PBEND_LABEL_YSIZE        VIDEO_LABEL_YSIZE
  110. #define VIDEO_PBEND_SYMBOL_XPOS        VIDEO_SYMBOL_XPOS
  111. #define VIDEO_PBEND_SYMBOL_YPOS        221
  112. #define VIDEO_PBEND_SYMBOL_XSIZE    27
  113. #define VIDEO_PBEND_SYMBOL_YSIZE    VIDEO_SYMBOL_YSIZE
  114.  
  115. #define VIDEO_WARP_LABEL_XPOS        VIDEO_LABEL_XPOS
  116. #define VIDEO_WARP_LABEL_YPOS        165
  117. #define VIDEO_WARP_LABEL_XSIZE        VIDEO_LABEL_XSIZE
  118. #define VIDEO_WARP_LABEL_YSIZE        VIDEO_LABEL_YSIZE
  119. #define VIDEO_WARP_SYMBOL_XPOS        VIDEO_SYMBOL_XPOS
  120. #define VIDEO_WARP_SYMBOL_YPOS        165
  121. #define VIDEO_WARP_SYMBOL_XSIZE        27
  122. #define VIDEO_WARP_SYMBOL_YSIZE        VIDEO_SYMBOL_YSIZE
  123. #define VIDEO_WARP2_SYMBOL_XPOS        VIDEO_SYMBOL_XPOS
  124. #define VIDEO_WARP2_SYMBOL_YPOS        152
  125. #define VIDEO_WARP2_SYMBOL_XSIZE    27
  126. #define VIDEO_WARP2_SYMBOL_YSIZE    VIDEO_SYMBOL_YSIZE
  127.  
  128. #define VIDEO_1STEP_SYMBOL_XPOS        (VIDEO_SYMBOL_XPOS + 18)
  129. #define VIDEO_1STEP_SYMBOL_YPOS        139
  130. #define VIDEO_1STEP_SYMBOL_XSIZE    (VIDEO_SYMBOL_XSIZE - 18)
  131. #define VIDEO_1STEP_SYMBOL_YSIZE    VIDEO_SYMBOL_YSIZE
  132.  
  133. #define PG_X3(x)            (DOOR_GFX_PAGEX3 + (x))
  134. #define PG_X4(x)            (DOOR_GFX_PAGEX4 + (x))
  135. #define PG_X5(x)            (DOOR_GFX_PAGEX5 + (x))
  136. #define PG_X6(x)            (DOOR_GFX_PAGEX6 + (x))
  137.  
  138. #define PG_Y1(y)            (DOOR_GFX_PAGEY1 + (y))
  139. #define PG_Y2(y)            (DOOR_GFX_PAGEY2 + (y))
  140.  
  141. #define VIDEO_INFO_OFF            (VIDEO_STATE_DATE_OFF    |    \
  142.                      VIDEO_STATE_TIME_OFF)
  143. #define VIDEO_STATE_OFF            (VIDEO_STATE_PLAY_OFF    |    \
  144.                      VIDEO_STATE_REC_OFF    |    \
  145.                      VIDEO_STATE_PAUSE_OFF    |    \
  146.                      VIDEO_STATE_FFWD_OFF    |    \
  147.                      VIDEO_STATE_PBEND_OFF    |    \
  148.                      VIDEO_STATE_1STEP_OFF)
  149. #define VIDEO_PRESS_OFF            (VIDEO_PRESS_PLAY_OFF    |    \
  150.                      VIDEO_PRESS_REC_OFF    |    \
  151.                      VIDEO_PRESS_PAUSE_OFF    |    \
  152.                      VIDEO_PRESS_STOP_OFF    |    \
  153.                      VIDEO_PRESS_EJECT_OFF)
  154. #define VIDEO_ALL_OFF            (VIDEO_INFO_OFF        |    \
  155.                       VIDEO_STATE_OFF    |    \
  156.                       VIDEO_PRESS_OFF)
  157.  
  158. #define VIDEO_INFO_ON            (VIDEO_STATE_DATE_ON    |    \
  159.                      VIDEO_STATE_TIME_ON)
  160. #define VIDEO_STATE_ON            (VIDEO_STATE_PLAY_ON    |    \
  161.                      VIDEO_STATE_REC_ON    |    \
  162.                      VIDEO_STATE_PAUSE_ON    |    \
  163.                      VIDEO_STATE_FFWD_ON    |    \
  164.                      VIDEO_STATE_PBEND_ON    |    \
  165.                      VIDEO_STATE_1STEP_ON)
  166. #define VIDEO_PRESS_ON            (VIDEO_PRESS_PLAY_ON    |    \
  167.                      VIDEO_PRESS_REC_ON    |    \
  168.                      VIDEO_PRESS_PAUSE_ON    |    \
  169.                      VIDEO_PRESS_STOP_ON    |    \
  170.                      VIDEO_PRESS_EJECT_ON)
  171. #define VIDEO_ALL_ON            (VIDEO_INFO_ON        |    \
  172.                       VIDEO_STATE_ON        |    \
  173.                       VIDEO_PRESS_ON)
  174.  
  175. #define VIDEO_INFO            (VIDEO_INFO_ON | VIDEO_INFO_OFF)
  176. #define VIDEO_STATE            (VIDEO_STATE_ON | VIDEO_STATE_OFF)
  177. #define VIDEO_PRESS            (VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
  178. #define VIDEO_ALL            (VIDEO_ALL_ON | VIDEO_ALL_OFF)
  179.  
  180. #define NUM_TAPE_FUNCTIONS        10
  181. #define NUM_TAPE_FUNCTION_PARTS        2
  182. #define NUM_TAPE_FUNCTION_STATES    2
  183.  
  184.  
  185. /* ========================================================================= */
  186. /* video display functions                                                   */
  187. /* ========================================================================= */
  188.  
  189. void DrawVideoDisplay(unsigned long state, unsigned long value)
  190. {
  191.   int i, j, k;
  192.   static char *monatsname[12] =
  193.   {
  194.     "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  195.     "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
  196.   };
  197.   static struct
  198.   {
  199.     int gd_x1, gd_y1;
  200.     int gd_x2, gd_y2;
  201.     int x, y;
  202.     int width, height;
  203.   }
  204.   video_pos[NUM_TAPE_FUNCTIONS][NUM_TAPE_FUNCTION_PARTS] =
  205.   {
  206.     {
  207.       {
  208.     PG_X4(VIDEO_PLAY_LABEL_XPOS),    PG_Y2(VIDEO_PLAY_LABEL_YPOS),
  209.     PG_X3(VIDEO_PLAY_LABEL_XPOS),    PG_Y2(VIDEO_PLAY_LABEL_YPOS),
  210.     VIDEO_PLAY_LABEL_XPOS,        VIDEO_PLAY_LABEL_YPOS,
  211.     VIDEO_PLAY_LABEL_XSIZE,        VIDEO_PLAY_LABEL_YSIZE
  212.       },
  213.       {
  214.     PG_X4(VIDEO_PLAY_SYMBOL_XPOS),    PG_Y2(VIDEO_PLAY_SYMBOL_YPOS),
  215.     PG_X3(VIDEO_PLAY_SYMBOL_XPOS),    PG_Y2(VIDEO_PLAY_SYMBOL_YPOS),
  216.     VIDEO_PLAY_SYMBOL_XPOS,        VIDEO_PLAY_SYMBOL_YPOS,
  217.     VIDEO_PLAY_SYMBOL_XSIZE,    VIDEO_PLAY_SYMBOL_YSIZE
  218.       }
  219.     },
  220.     {
  221.       {
  222.     PG_X4(VIDEO_REC_LABEL_XPOS),    PG_Y2(VIDEO_REC_LABEL_YPOS),
  223.     PG_X3(VIDEO_REC_LABEL_XPOS),    PG_Y2(VIDEO_REC_LABEL_YPOS),
  224.     VIDEO_REC_LABEL_XPOS,        VIDEO_REC_LABEL_YPOS,
  225.     VIDEO_REC_LABEL_XSIZE,        VIDEO_REC_LABEL_YSIZE
  226.       },
  227.       {
  228.     PG_X4(VIDEO_REC_SYMBOL_XPOS),    PG_Y2(VIDEO_REC_SYMBOL_YPOS),
  229.     PG_X3(VIDEO_REC_SYMBOL_XPOS),    PG_Y2(VIDEO_REC_SYMBOL_YPOS),
  230.     VIDEO_REC_SYMBOL_XPOS,        VIDEO_REC_SYMBOL_YPOS,
  231.     VIDEO_REC_SYMBOL_XSIZE,        VIDEO_REC_SYMBOL_YSIZE
  232.       }
  233.     },
  234.     {
  235.       {
  236.     PG_X4(VIDEO_PAUSE_LABEL_XPOS),    PG_Y2(VIDEO_PAUSE_LABEL_YPOS),
  237.     PG_X3(VIDEO_PAUSE_LABEL_XPOS),    PG_Y2(VIDEO_PAUSE_LABEL_YPOS),
  238.     VIDEO_PAUSE_LABEL_XPOS,        VIDEO_PAUSE_LABEL_YPOS,
  239.     VIDEO_PAUSE_LABEL_XSIZE,    VIDEO_PAUSE_LABEL_YSIZE
  240.       },
  241.       {
  242.     PG_X4(VIDEO_PAUSE_SYMBOL_XPOS),    PG_Y2(VIDEO_PAUSE_SYMBOL_YPOS),
  243.     PG_X3(VIDEO_PAUSE_SYMBOL_XPOS),    PG_Y2(VIDEO_PAUSE_SYMBOL_YPOS),
  244.     VIDEO_PAUSE_SYMBOL_XPOS,    VIDEO_PAUSE_SYMBOL_YPOS,
  245.     VIDEO_PAUSE_SYMBOL_XSIZE,    VIDEO_PAUSE_SYMBOL_YSIZE
  246.       }
  247.     },
  248.     {
  249.       {
  250.     PG_X4(VIDEO_DATE_LABEL_XPOS),    PG_Y2(VIDEO_DATE_LABEL_YPOS),
  251.     PG_X3(VIDEO_DATE_LABEL_XPOS),    PG_Y2(VIDEO_DATE_LABEL_YPOS),
  252.     VIDEO_DATE_LABEL_XPOS,        VIDEO_DATE_LABEL_YPOS,
  253.     VIDEO_DATE_LABEL_XSIZE,        VIDEO_DATE_LABEL_YSIZE
  254.       },
  255.       {
  256.     PG_X4(VIDEO_DATE_XPOS),        PG_Y2(VIDEO_DATE_YPOS),
  257.     PG_X3(VIDEO_DATE_XPOS),        PG_Y2(VIDEO_DATE_YPOS),
  258.     VIDEO_DATE_XPOS,        VIDEO_DATE_YPOS,
  259.     VIDEO_DATE_XSIZE,        VIDEO_DATE_YSIZE
  260.       }
  261.     },
  262.     {
  263.       {
  264.     -1,                -1,
  265.     -1,                -1,
  266.     -1,                -1,
  267.     -1,                -1
  268.       },
  269.       {
  270.     PG_X4(VIDEO_TIME_XPOS),        PG_Y2(VIDEO_TIME_YPOS),
  271.     PG_X3(VIDEO_TIME_XPOS),        PG_Y2(VIDEO_TIME_YPOS),
  272.     VIDEO_TIME_XPOS,        VIDEO_TIME_YPOS,
  273.     VIDEO_TIME_XSIZE,        VIDEO_TIME_YSIZE
  274.       }
  275.     },
  276.     {
  277.       {
  278.     PG_X6(VIDEO_FFWD_LABEL_XPOS),    PG_Y1(VIDEO_FFWD_LABEL_YPOS),
  279.     PG_X3(VIDEO_LABEL_XPOS),    PG_Y2(VIDEO_LABEL_YPOS),
  280.     VIDEO_LABEL_XPOS,        VIDEO_LABEL_YPOS,
  281.     VIDEO_LABEL_XSIZE,        VIDEO_LABEL_YSIZE
  282.       },
  283.       {
  284.     PG_X6(VIDEO_FFWD_SYMBOL_XPOS),    PG_Y1(VIDEO_FFWD_SYMBOL_YPOS),
  285.     PG_X3(VIDEO_FFWD_SYMBOL_XPOS),    PG_Y2(VIDEO_SYMBOL_YPOS),
  286.     VIDEO_SYMBOL_XPOS,        VIDEO_SYMBOL_YPOS,
  287.     VIDEO_FFWD_SYMBOL_XSIZE,    VIDEO_FFWD_SYMBOL_YSIZE
  288.       }
  289.     },
  290.     {
  291.       {
  292.     PG_X6(VIDEO_PBEND_LABEL_XPOS),    PG_Y1(VIDEO_PBEND_LABEL_YPOS),
  293.     PG_X3(VIDEO_LABEL_XPOS),    PG_Y2(VIDEO_LABEL_YPOS),
  294.     VIDEO_LABEL_XPOS,        VIDEO_LABEL_YPOS,
  295.     VIDEO_LABEL_XSIZE,        VIDEO_LABEL_YSIZE
  296.       },
  297.       {
  298.     PG_X6(VIDEO_PBEND_SYMBOL_XPOS),    PG_Y1(VIDEO_PBEND_SYMBOL_YPOS),
  299.     PG_X3(VIDEO_PBEND_SYMBOL_XPOS),    PG_Y2(VIDEO_SYMBOL_YPOS),
  300.     VIDEO_SYMBOL_XPOS,        VIDEO_SYMBOL_YPOS,
  301.     VIDEO_PBEND_SYMBOL_XSIZE,    VIDEO_PBEND_SYMBOL_YSIZE
  302.       }
  303.     },
  304.     {
  305.       {
  306.     PG_X6(VIDEO_WARP_LABEL_XPOS),    PG_Y1(VIDEO_WARP_LABEL_YPOS),
  307.     PG_X3(VIDEO_LABEL_XPOS),    PG_Y2(VIDEO_LABEL_YPOS),
  308.     VIDEO_LABEL_XPOS,        VIDEO_LABEL_YPOS,
  309.     VIDEO_LABEL_XSIZE,        VIDEO_LABEL_YSIZE
  310.       },
  311.       {
  312.     PG_X6(VIDEO_WARP_SYMBOL_XPOS),    PG_Y1(VIDEO_WARP_SYMBOL_YPOS),
  313.     PG_X3(VIDEO_WARP_SYMBOL_XPOS),    PG_Y2(VIDEO_SYMBOL_YPOS),
  314.     VIDEO_SYMBOL_XPOS,        VIDEO_SYMBOL_YPOS,
  315.     VIDEO_WARP_SYMBOL_XSIZE,    VIDEO_WARP_SYMBOL_YSIZE
  316.       }
  317.     },
  318.     {
  319.       {
  320.     -1,                -1,
  321.     -1,                -1,
  322.     -1,                -1,
  323.     -1,                -1
  324.       },
  325.       {
  326.     PG_X6(VIDEO_WARP2_SYMBOL_XPOS),    PG_Y1(VIDEO_WARP2_SYMBOL_YPOS),
  327.     PG_X3(VIDEO_WARP2_SYMBOL_XPOS),    PG_Y2(VIDEO_SYMBOL_YPOS),
  328.     VIDEO_SYMBOL_XPOS,        VIDEO_SYMBOL_YPOS,
  329.     VIDEO_WARP2_SYMBOL_XSIZE,    VIDEO_WARP2_SYMBOL_YSIZE
  330.       }
  331.     },
  332.     {
  333.       {
  334.     -1,                -1,
  335.     -1,                -1,
  336.     -1,                -1,
  337.     -1,                -1
  338.       },
  339.       {
  340.     PG_X6(VIDEO_1STEP_SYMBOL_XPOS),    PG_Y1(VIDEO_1STEP_SYMBOL_YPOS),
  341.     PG_X3(VIDEO_1STEP_SYMBOL_XPOS),    PG_Y2(VIDEO_SYMBOL_YPOS),
  342.     VIDEO_1STEP_SYMBOL_XPOS,    VIDEO_SYMBOL_YPOS,
  343.     VIDEO_1STEP_SYMBOL_XSIZE,    VIDEO_1STEP_SYMBOL_YSIZE
  344.       }
  345.     },
  346.   };
  347.  
  348. #if 0
  349.   if (state & VIDEO_STATE_FFWD_OFF)
  350.   {
  351. #if 1
  352.     int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
  353.  
  354.     if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
  355.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  356.          cx + VIDEO_LABEL_XPOS,
  357.          cy + VIDEO_LABEL_YPOS,
  358.          VIDEO_LABEL_XSIZE,
  359.          VIDEO_LABEL_YSIZE,
  360.          VX + VIDEO_LABEL_XPOS,
  361.          VY + VIDEO_LABEL_YPOS);
  362.  
  363.     cx = DOOR_GFX_PAGEX3;
  364.     cy = DOOR_GFX_PAGEY2;
  365.  
  366.     if (value != VIDEO_DISPLAY_LABEL_ONLY)
  367.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  368.          cx + VIDEO_FFWD_SYMBOL_XPOS,
  369.          cy + VIDEO_SYMBOL_YPOS,
  370.          VIDEO_FFWD_SYMBOL_XSIZE,
  371.          VIDEO_FFWD_SYMBOL_YSIZE,
  372.          VX + VIDEO_SYMBOL_XPOS,
  373.          VY + VIDEO_SYMBOL_YPOS);
  374. #else
  375.     int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
  376.  
  377.     BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  378.            cx + VIDEO_PLAY_SYMBOL_XPOS - 9,
  379.            cy + VIDEO_PLAY_SYMBOL_YPOS,
  380.            VIDEO_PLAY_SYMBOL_XSIZE - 2,
  381.            VIDEO_PLAY_SYMBOL_YSIZE,
  382.            VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
  383.            VY + VIDEO_PLAY_SYMBOL_YPOS);
  384. #endif
  385.   }
  386. #endif
  387.  
  388. #if 0
  389.   if (state & VIDEO_STATE_PBEND_OFF)
  390.   {
  391. #if 1
  392.     int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
  393.  
  394.     if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
  395.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  396.          cx + VIDEO_LABEL_XPOS,
  397.          cy + VIDEO_LABEL_YPOS,
  398.          VIDEO_LABEL_XSIZE,
  399.          VIDEO_LABEL_YSIZE,
  400.          VX + VIDEO_LABEL_XPOS,
  401.          VY + VIDEO_LABEL_YPOS);
  402.  
  403.     cx = DOOR_GFX_PAGEX3;
  404.     cy = DOOR_GFX_PAGEY2;
  405.  
  406.     if (value != VIDEO_DISPLAY_LABEL_ONLY)
  407.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  408.          cx + VIDEO_PBEND_SYMBOL_XPOS,
  409.          cy + VIDEO_SYMBOL_YPOS,
  410.          VIDEO_PBEND_SYMBOL_XSIZE,
  411.          VIDEO_PBEND_SYMBOL_YSIZE,
  412.          VX + VIDEO_PBEND_SYMBOL_XPOS,
  413.          VY + VIDEO_SYMBOL_YPOS);
  414. #else
  415.     int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
  416.  
  417.     BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  418.            cx + VIDEO_REC_LABEL_XPOS,
  419.            cy + VIDEO_REC_LABEL_YPOS,
  420.            VIDEO_PBEND_LABEL_XSIZE,
  421.            VIDEO_PBEND_LABEL_YSIZE,
  422.            VX + VIDEO_REC_LABEL_XPOS,
  423.            VY + VIDEO_REC_LABEL_YPOS);
  424. #endif
  425.   }
  426. #endif
  427.  
  428. #if 0
  429.   if (state & VIDEO_STATE_1STEP_OFF)
  430.   {
  431.     int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2;
  432.  
  433.     if (value != VIDEO_DISPLAY_LABEL_ONLY)
  434.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  435.          cx + VIDEO_1STEP_SYMBOL_XPOS,
  436.          cy + VIDEO_SYMBOL_YPOS,
  437.          VIDEO_1STEP_SYMBOL_XSIZE,
  438.          VIDEO_1STEP_SYMBOL_YSIZE,
  439.          VX + VIDEO_1STEP_SYMBOL_XPOS,
  440.          VY + VIDEO_SYMBOL_YPOS);
  441.   }
  442. #endif
  443.  
  444.   for (k = 0; k < NUM_TAPE_FUNCTION_STATES; k++)    /* on or off states */
  445.   {
  446.     for (i = 0; i < NUM_TAPE_FUNCTIONS; i++)        /* record, play, ... */
  447.     {
  448.       for (j = 0; j < NUM_TAPE_FUNCTION_PARTS; j++)    /* label or symbol */
  449.       {
  450.     if (state & (1 << (i * 2 + k)))
  451.     {
  452.       int gd_x, gd_y;
  453.       int skip_value =
  454.         (j == 0 ? VIDEO_DISPLAY_SYMBOL_ONLY : VIDEO_DISPLAY_LABEL_ONLY);
  455.  
  456.       if (k == 1)        /* on */
  457.       {
  458.         gd_x = video_pos[i][j].gd_x1;
  459.         gd_y = video_pos[i][j].gd_y1;
  460.       }
  461.       else            /* off */
  462.       {
  463.         gd_x = video_pos[i][j].gd_x2;
  464.         gd_y = video_pos[i][j].gd_y2;
  465.       }
  466.  
  467.       if (video_pos[i][j].x != -1 && value != skip_value)
  468.         BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  469.                gd_x, gd_y,
  470.                video_pos[i][j].width,
  471.                video_pos[i][j].height,
  472.                VX + video_pos[i][j].x,
  473.                VY + video_pos[i][j].y);
  474.     }
  475.       }
  476.     }
  477.   }
  478.  
  479. #if 0
  480.   if (state & VIDEO_STATE_FFWD_ON)
  481.   {
  482. #if 1
  483.     int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
  484.  
  485.     if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
  486.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  487.          cx + VIDEO_FFWD_LABEL_XPOS,
  488.          cy + VIDEO_FFWD_LABEL_YPOS,
  489.          VIDEO_LABEL_XSIZE,
  490.          VIDEO_LABEL_YSIZE,
  491.          VX + VIDEO_LABEL_XPOS,
  492.          VY + VIDEO_LABEL_YPOS);
  493.  
  494.     cx = DOOR_GFX_PAGEX6;
  495.     cy = DOOR_GFX_PAGEY1;
  496.  
  497.     if (value != VIDEO_DISPLAY_LABEL_ONLY)
  498.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  499.          cx + VIDEO_FFWD_SYMBOL_XPOS,
  500.          cy + VIDEO_FFWD_SYMBOL_YPOS,
  501.          VIDEO_FFWD_SYMBOL_XSIZE,
  502.          VIDEO_FFWD_SYMBOL_YSIZE,
  503.          VX + VIDEO_SYMBOL_XPOS,
  504.          VY + VIDEO_SYMBOL_YPOS);
  505. #else
  506.     int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2;
  507.  
  508.     BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  509.            cx + VIDEO_PLAY_SYMBOL_XPOS,
  510.            cy + VIDEO_PLAY_SYMBOL_YPOS,
  511.            VIDEO_PLAY_SYMBOL_XSIZE - 2,
  512.            VIDEO_PLAY_SYMBOL_YSIZE,
  513.            VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
  514.            VY + VIDEO_PLAY_SYMBOL_YPOS);
  515. #endif
  516.   }
  517. #endif
  518.  
  519. #if 0
  520.   if (state & VIDEO_STATE_PBEND_ON)
  521.   {
  522. #if 1
  523.     int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
  524.  
  525.     if (value != VIDEO_DISPLAY_SYMBOL_ONLY)
  526.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  527.          cx + VIDEO_PBEND_LABEL_XPOS,
  528.          cy + VIDEO_PBEND_LABEL_YPOS,
  529.          VIDEO_LABEL_XSIZE,
  530.          VIDEO_LABEL_YSIZE,
  531.          VX + VIDEO_LABEL_XPOS,
  532.          VY + VIDEO_LABEL_YPOS);
  533.  
  534.     cx = DOOR_GFX_PAGEX6;
  535.     cy = DOOR_GFX_PAGEY1;
  536.  
  537.     if (value != VIDEO_DISPLAY_LABEL_ONLY)
  538.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  539.          cx + VIDEO_PBEND_SYMBOL_XPOS,
  540.          cy + VIDEO_PBEND_SYMBOL_YPOS,
  541.          VIDEO_PBEND_SYMBOL_XSIZE,
  542.          VIDEO_PBEND_SYMBOL_YSIZE,
  543.          VX + VIDEO_SYMBOL_XPOS,
  544.          VY + VIDEO_SYMBOL_YPOS);
  545. #else
  546.     int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
  547.  
  548.     BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  549.            cx + VIDEO_PBEND_LABEL_XPOS,
  550.            cy + VIDEO_PBEND_LABEL_YPOS,
  551.            VIDEO_PBEND_LABEL_XSIZE,
  552.            VIDEO_PBEND_LABEL_YSIZE,
  553.            VX + VIDEO_REC_LABEL_XPOS,
  554.            VY + VIDEO_REC_LABEL_YPOS);
  555. #endif
  556.   }
  557. #endif
  558.  
  559. #if 0
  560.   if (state & VIDEO_STATE_1STEP_ON)
  561.   {
  562.     int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
  563.  
  564.     if (value != VIDEO_DISPLAY_LABEL_ONLY)
  565.       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  566.          cx + VIDEO_1STEP_SYMBOL_XPOS,
  567.          cy + VIDEO_1STEP_SYMBOL_YPOS,
  568.          VIDEO_1STEP_SYMBOL_XSIZE,
  569.          VIDEO_1STEP_SYMBOL_YSIZE,
  570.          VX + VIDEO_1STEP_SYMBOL_XPOS,
  571.          VY + VIDEO_SYMBOL_YPOS);
  572.   }
  573. #endif
  574.  
  575.   if (state & VIDEO_STATE_DATE_ON)
  576.   {
  577.     int tag = value % 100;
  578.     int monat = (value/100) % 100;
  579.     int jahr = (value/10000);
  580.  
  581.     DrawText(VX + VIDEO_DATE_XPOS, VY + VIDEO_DATE_YPOS,
  582.          int2str(tag, 2), FONT_TAPE_RECORDER);
  583.     DrawText(VX + VIDEO_DATE_XPOS + 27, VY + VIDEO_DATE_YPOS,
  584.          monatsname[monat], FONT_TAPE_RECORDER);
  585.     DrawText(VX + VIDEO_DATE_XPOS + 64, VY + VIDEO_DATE_YPOS,
  586.          int2str(jahr, 2), FONT_TAPE_RECORDER);
  587.   }
  588.  
  589.   if (state & VIDEO_STATE_TIME_ON)
  590.   {
  591.     int min = value / 60;
  592.     int sec = value % 60;
  593.  
  594.     DrawText(VX + VIDEO_TIME_XPOS, VY + VIDEO_TIME_YPOS,
  595.          int2str(min, 2), FONT_TAPE_RECORDER);
  596.     DrawText(VX + VIDEO_TIME_XPOS + 27, VY + VIDEO_TIME_YPOS,
  597.          int2str(sec, 2), FONT_TAPE_RECORDER);
  598.   }
  599.  
  600. #if 1
  601.   redraw_mask |= REDRAW_DOOR_2;
  602. #else
  603.   if (state & VIDEO_STATE_DATE)
  604.     redraw_mask |= REDRAW_VIDEO_1;
  605.   if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE)
  606.     redraw_mask |= REDRAW_VIDEO_2;
  607.   if (state & VIDEO_PRESS)
  608.     redraw_mask |= REDRAW_VIDEO_3;
  609. #endif
  610. }
  611.  
  612. void DrawCompleteVideoDisplay()
  613. {
  614.   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  615.          DOOR_GFX_PAGEX3, DOOR_GFX_PAGEY2,
  616.          gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy);
  617.   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
  618.          DOOR_GFX_PAGEX4 + VIDEO_CONTROL_XPOS,
  619.          DOOR_GFX_PAGEY2 + VIDEO_CONTROL_YPOS,
  620.          VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
  621.          gfx.vx + VIDEO_CONTROL_XPOS, gfx.vy + VIDEO_CONTROL_YPOS);
  622.  
  623.   DrawVideoDisplay(VIDEO_ALL_OFF, 0);
  624.   if (tape.date && tape.length)
  625.   {
  626.     DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
  627.     DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
  628.   }
  629.  
  630.   BlitBitmap(drawto, bitmap_db_door, gfx.vx, gfx.vy, gfx.vxsize, gfx.vysize,
  631.          DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
  632. }
  633.  
  634. void TapeDeactivateDisplayOn()
  635. {
  636.   SetDrawDeactivationMask(REDRAW_FIELD);
  637.   audio.sound_deactivated = TRUE;
  638. }
  639.  
  640. void TapeDeactivateDisplayOff(boolean redraw_display)
  641. {
  642.   SetDrawDeactivationMask(REDRAW_NONE);
  643.   audio.sound_deactivated = FALSE;
  644.  
  645.   if (redraw_display)
  646.   {
  647.     RedrawPlayfield(TRUE, 0,0,0,0);
  648.     DrawGameDoorValues();
  649.   }
  650. }
  651.  
  652.  
  653. /* ========================================================================= */
  654. /* tape control functions                                                    */
  655. /* ========================================================================= */
  656.  
  657. static void TapeSetDate()
  658. {
  659.   time_t epoch_seconds = time(NULL);
  660.   struct tm *now = localtime(&epoch_seconds);
  661.  
  662.   tape.date = 10000 * (now->tm_year % 100) + 100 * now->tm_mon + now->tm_mday;
  663. }
  664.  
  665. void TapeErase()
  666. {
  667.   int i;
  668.  
  669.   tape.length = 0;
  670.   tape.counter = 0;
  671.  
  672.   if (leveldir_current)
  673.     setString(&tape.level_identifier, leveldir_current->identifier);
  674.  
  675.   tape.level_nr = level_nr;
  676.   tape.pos[tape.counter].delay = 0;
  677.   tape.changed = TRUE;
  678.  
  679.   tape.random_seed = InitRND(NEW_RANDOMIZE);
  680.  
  681.   tape.file_version = FILE_VERSION_ACTUAL;
  682.   tape.game_version = GAME_VERSION_ACTUAL;
  683.   tape.engine_version = level.game_version;
  684.  
  685.   TapeSetDate();
  686.  
  687. #if 0
  688.   printf("::: tape.engine_version = level.game_version = %d \n",
  689.      level.game_version);
  690. #endif
  691.  
  692.   for (i = 0; i < MAX_PLAYERS; i++)
  693.     tape.player_participates[i] = FALSE;
  694. }
  695.  
  696. static void TapeRewind()
  697. {
  698.   tape.counter = 0;
  699.   tape.delay_played = 0;
  700.   tape.pause_before_death = FALSE;
  701.   tape.recording = FALSE;
  702.   tape.playing = FALSE;
  703.   tape.fast_forward = FALSE;
  704.   tape.warp_forward = FALSE;
  705.   tape.deactivate_display = FALSE;
  706.   tape.auto_play = (global.autoplay_leveldir != NULL);
  707.   tape.auto_play_level_solved = FALSE;
  708.   tape.quick_resume = FALSE;
  709.   tape.single_step = FALSE;
  710.  
  711.   InitRND(tape.random_seed);
  712. }
  713.  
  714. void TapeStartRecording()
  715. {
  716.   if (!TAPE_IS_STOPPED(tape))
  717.     TapeStop();
  718.  
  719.   TapeErase();
  720.   TapeRewind();
  721.  
  722.   tape.recording = TRUE;
  723.  
  724.   DrawVideoDisplay(VIDEO_STATE_REC_ON, 0);
  725.   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
  726.   DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
  727.   MapTapeWarpButton();
  728.  
  729.   SetDrawDeactivationMask(REDRAW_NONE);
  730.   audio.sound_deactivated = FALSE;
  731. }
  732.  
  733. static void TapeStartGameRecording()
  734. {
  735.   TapeStartRecording();
  736.  
  737. #if defined(NETWORK_AVALIABLE)
  738.   if (options.network)
  739.     SendToServer_StartPlaying();
  740.   else
  741. #endif
  742.   {
  743.     game_status = GAME_MODE_PLAYING;
  744.     StopAnimation();
  745.     InitGame();
  746.   }
  747. }
  748.  
  749. static void TapeAppendRecording()
  750. {
  751.   if (!tape.playing || !tape.pausing)
  752.     return;
  753.  
  754.   tape.pos[tape.counter].delay = tape.delay_played;
  755.   tape.playing = FALSE;
  756.   tape.recording = TRUE;
  757.   tape.changed = TRUE;
  758.  
  759.   TapeSetDate();
  760.  
  761.   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
  762.   DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON, 0);
  763. }
  764.  
  765. void TapeHaltRecording()
  766. {
  767.   if (!tape.recording)
  768.     return;
  769.  
  770.   tape.counter++;
  771.   tape.pos[tape.counter].delay = 0;
  772.  
  773.   tape.length = tape.counter;
  774.   tape.length_seconds = GetTapeLength();
  775. }
  776.  
  777. void TapeStopRecording()
  778. {
  779.   if (!tape.recording)
  780.     return;
  781.  
  782.   TapeHaltRecording();
  783.  
  784.   tape.recording = FALSE;
  785.   tape.pausing = FALSE;
  786.  
  787.   DrawVideoDisplay(VIDEO_STATE_REC_OFF, 0);
  788.   MapTapeEjectButton();
  789. }
  790.  
  791. void TapeRecordAction(byte action[MAX_PLAYERS])
  792. {
  793.   int i;
  794.  
  795. #if 1
  796.   if (!tape.recording)        /* record action even when tape is paused! */
  797.     return;
  798. #else
  799.   if (!tape.recording || tape.pausing)
  800.     return;
  801. #endif
  802.  
  803.   if (tape.counter >= MAX_TAPELEN - 1)
  804.   {
  805.     TapeStopRecording();
  806.     return;
  807.   }
  808.  
  809. #if 0
  810.   printf("::: %05d: recording action: %d\n", FrameCounter, action[0]);
  811. #endif
  812.  
  813.   if (tape.pos[tape.counter].delay > 0)        /* already stored action */
  814.   {
  815.     boolean changed_events = FALSE;
  816.  
  817.     for (i = 0; i < MAX_PLAYERS; i++)
  818.       if (tape.pos[tape.counter].action[i] != action[i])
  819.     changed_events = TRUE;
  820.  
  821.     if (changed_events || tape.pos[tape.counter].delay >= 255)
  822.     {
  823.       tape.counter++;
  824.       tape.pos[tape.counter].delay = 0;
  825.     }
  826.     else
  827.       tape.pos[tape.counter].delay++;
  828.   }
  829.  
  830.   if (tape.pos[tape.counter].delay == 0)    /* store new action */
  831.   {
  832.  
  833. #if 0
  834.     printf("::: %05d: new sequence\n", FrameCounter);
  835. #endif
  836.  
  837.     for (i = 0; i < MAX_PLAYERS; i++)
  838.       tape.pos[tape.counter].action[i] = action[i];
  839.  
  840.     tape.pos[tape.counter].delay++;
  841.   }
  842. }
  843.  
  844. void TapeTogglePause(boolean toggle_manual)
  845. {
  846.   int state = 0;
  847.  
  848. #if 0
  849.   if (!tape.recording && !tape.playing)
  850.     return;
  851. #endif
  852.  
  853.   if (tape.pause_before_death)
  854.     state |= VIDEO_STATE_PBEND_OFF;
  855.   else if (tape.fast_forward)
  856.     state |= VIDEO_STATE_FFWD_OFF;
  857.  
  858.   tape.pausing = !tape.pausing;
  859.   tape.fast_forward = FALSE;
  860.   tape.pause_before_death = FALSE;
  861.  
  862.   if (tape.single_step && toggle_manual)
  863.     tape.single_step = FALSE;
  864.  
  865.   state |= (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
  866.   if (tape.playing)
  867.     state |= VIDEO_STATE_PLAY_ON;
  868.   else
  869.     state |= (tape.single_step ? VIDEO_STATE_1STEP_ON : VIDEO_STATE_1STEP_OFF);
  870.  
  871.   DrawVideoDisplay(state, 0);
  872.  
  873. #if 0
  874.   if (tape.pausing)
  875.     DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, 0);
  876. #endif
  877.  
  878.   if (tape.warp_forward)
  879.   {
  880.     TapeStopWarpForward();
  881.  
  882.     if (tape.quick_resume)
  883.     {
  884.       tape.quick_resume = FALSE;
  885.  
  886.       TapeAppendRecording();
  887. #if 0
  888.       TapeTogglePause(toggle_manual);
  889. #endif
  890.     }
  891.   }
  892. }
  893.  
  894. void TapeStartPlaying()
  895. {
  896.   if (TAPE_IS_EMPTY(tape))
  897.     return;
  898.  
  899.   if (!TAPE_IS_STOPPED(tape))
  900.     TapeStop();
  901.  
  902.   TapeRewind();
  903.  
  904.   tape.playing = TRUE;
  905.  
  906.   DrawVideoDisplay(VIDEO_STATE_PLAY_ON, 0);
  907.   DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
  908.   DrawVideoDisplay(VIDEO_STATE_TIME_ON, 0);
  909.   MapTapeWarpButton();
  910.  
  911.   SetDrawDeactivationMask(REDRAW_NONE);
  912.   audio.sound_deactivated = FALSE;
  913. }
  914.  
  915. static void TapeStartGamePlaying()
  916. {
  917.   TapeStartPlaying();
  918.  
  919.   game_status = GAME_MODE_PLAYING;
  920.   StopAnimation();
  921.   InitGame();
  922. }
  923.  
  924. void TapeStopPlaying()
  925. {
  926.   if (!tape.playing)
  927.     return;
  928.  
  929.   tape.playing = FALSE;
  930.   tape.pausing = FALSE;
  931.  
  932.   if (tape.warp_forward)
  933.     TapeStopWarpForward();
  934.  
  935.   DrawVideoDisplay(VIDEO_STATE_PLAY_OFF, 0);
  936.   MapTapeEjectButton();
  937. }
  938.  
  939. byte *TapePlayAction()
  940. {
  941.   static byte action[MAX_PLAYERS];
  942.   int i;
  943.  
  944.   if (!tape.playing || tape.pausing)
  945.     return NULL;
  946.  
  947.   if (tape.pause_before_death)    /* STOP 10s BEFORE PLAYER GETS KILLED... */
  948.   {
  949.     if (!(FrameCounter % 20))
  950.     {
  951.       if ((FrameCounter / 20) % 2)
  952.     DrawVideoDisplay(VIDEO_STATE_PBEND_ON, VIDEO_DISPLAY_LABEL_ONLY);
  953.       else
  954.     DrawVideoDisplay(VIDEO_STATE_PBEND_OFF, VIDEO_DISPLAY_LABEL_ONLY);
  955.     }
  956.  
  957.     if (tape.warp_forward)
  958.     {
  959.       if (tape.deactivate_display)
  960.     DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
  961.       else
  962.     DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
  963.     }
  964.  
  965.     if (TapeTime > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
  966.     {
  967.       TapeTogglePause(TAPE_TOGGLE_MANUAL);
  968.       return NULL;
  969.     }
  970.   }
  971.   else if (tape.fast_forward)
  972.   {
  973.     if ((FrameCounter / 20) % 2)
  974.       DrawVideoDisplay(VIDEO_STATE_FFWD_ON, VIDEO_DISPLAY_LABEL_ONLY);
  975.     else
  976.       DrawVideoDisplay(VIDEO_STATE_FFWD_OFF, VIDEO_DISPLAY_LABEL_ONLY);
  977.  
  978.     if (tape.warp_forward)
  979.     {
  980.       if (tape.deactivate_display)
  981.     DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
  982.       else
  983.     DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
  984.     }
  985.   }
  986. #if 0
  987.   /* !!! this makes things much slower !!! */
  988.   else if (tape.warp_forward)
  989.   {
  990.     if ((FrameCounter / 20) % 2)
  991.       DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_LABEL_ONLY);
  992.     else
  993.       DrawVideoDisplay(VIDEO_STATE_WARP_OFF, VIDEO_DISPLAY_LABEL_ONLY);
  994.  
  995.     DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
  996.   }
  997. #endif
  998.  
  999.   if (tape.counter >= tape.length)    /* end of tape reached */
  1000.   {
  1001.     if (tape.warp_forward && !tape.auto_play)
  1002.       TapeTogglePause(TAPE_TOGGLE_MANUAL);
  1003.     else
  1004.       TapeStop();
  1005.  
  1006.     return NULL;
  1007.   }
  1008.  
  1009.   for (i = 0; i < MAX_PLAYERS; i++)
  1010.     action[i] = tape.pos[tape.counter].action[i];
  1011.  
  1012.   tape.delay_played++;
  1013.   if (tape.delay_played >= tape.pos[tape.counter].delay)
  1014.   {
  1015.     tape.counter++;
  1016.     tape.delay_played = 0;
  1017.   }
  1018.  
  1019. #if 0
  1020.   printf("::: %05d: replaying action: %d\n", FrameCounter, action[0]);
  1021. #endif
  1022.  
  1023.   return action;
  1024. }
  1025.  
  1026. void TapeStop()
  1027. {
  1028. #if 0
  1029.   if (tape.recording)
  1030.     printf("::: stopped recording: %d\n", FrameCounter);
  1031.   else if (tape.playing)
  1032.     printf("::: stopped playing:   %d\n\n", FrameCounter);
  1033. #endif
  1034.  
  1035.   TapeStopRecording();
  1036.   TapeStopPlaying();
  1037.  
  1038.   DrawVideoDisplay(VIDEO_STATE_OFF, 0);
  1039.  
  1040.   if (tape.date && tape.length)
  1041.   {
  1042.     DrawVideoDisplay(VIDEO_STATE_DATE_ON, tape.date);
  1043.     DrawVideoDisplay(VIDEO_STATE_TIME_ON, tape.length_seconds);
  1044.   }
  1045.  
  1046. #if 0
  1047.   if (tape.auto_play)
  1048.     AutoPlayTape();    /* continue automatically playing next tape */
  1049. #endif
  1050. }
  1051.  
  1052. unsigned int GetTapeLength()
  1053. {
  1054.   unsigned int tape_length = 0;
  1055.   int i;
  1056.  
  1057.   if (TAPE_IS_EMPTY(tape))
  1058.     return(0);
  1059.  
  1060.   for (i = 0; i < tape.length; i++)
  1061.     tape_length += tape.pos[i].delay;
  1062.  
  1063.   return(tape_length * GAME_FRAME_DELAY / 1000);
  1064. }
  1065.  
  1066. static void TapeStartWarpForward()
  1067. {
  1068.   tape.warp_forward = TRUE;
  1069.  
  1070. #if 1
  1071.   if (!tape.fast_forward && !tape.pause_before_death)
  1072.   {
  1073.     tape.pausing = FALSE;
  1074.     tape.deactivate_display = TRUE;
  1075.  
  1076.     TapeDeactivateDisplayOn();
  1077.   }
  1078. #else
  1079.   if (!tape.fast_forward || tape.pause_before_death)
  1080.   {
  1081.     tape.pausing = FALSE;
  1082.     tape.deactivate_display = TRUE;
  1083.  
  1084.     TapeDeactivateDisplayOn();
  1085.   }
  1086. #endif
  1087.  
  1088.   if (tape.fast_forward || tape.pause_before_death)
  1089.     DrawVideoDisplay(VIDEO_STATE_WARP_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
  1090.   else
  1091.     DrawVideoDisplay(VIDEO_STATE_WARP_ON, 0);
  1092. }
  1093.  
  1094. static void TapeStopWarpForward()
  1095. {
  1096.   int state = (tape.pausing ? VIDEO_STATE_PAUSE_ON : VIDEO_STATE_PAUSE_OFF);
  1097.  
  1098.   tape.warp_forward = FALSE;
  1099.   tape.deactivate_display = FALSE;
  1100.  
  1101.   TapeDeactivateDisplayOff(game_status == GAME_MODE_PLAYING);
  1102.  
  1103. #if 0
  1104. #if 1
  1105.   if (game_status == GAME_MODE_PLAYING)
  1106. #endif
  1107.   {
  1108.     RedrawPlayfield(TRUE, 0,0,0,0);
  1109.     DrawGameDoorValues();
  1110.   }
  1111. #endif
  1112.  
  1113.   if (tape.pause_before_death)
  1114.     state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_PBEND_ON;
  1115.   else if (tape.fast_forward)
  1116.     state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_FFWD_ON;
  1117.   else
  1118.     state |= VIDEO_STATE_WARP_OFF | VIDEO_STATE_PLAY_ON;
  1119.  
  1120.   DrawVideoDisplay(state, 0);
  1121. }
  1122.  
  1123. static void TapeSingleStep()
  1124. {
  1125.   if (options.network)
  1126.     return;
  1127.  
  1128.   if (!tape.pausing)
  1129.     TapeTogglePause(TAPE_TOGGLE_MANUAL);
  1130.  
  1131.   tape.single_step = !tape.single_step;
  1132.  
  1133.   DrawVideoDisplay((tape.single_step ? VIDEO_STATE_1STEP_ON :
  1134.             VIDEO_STATE_1STEP_OFF), 0);
  1135. }
  1136.  
  1137. void TapeQuickSave()
  1138. {
  1139.   if (game_status == GAME_MODE_PLAYING)
  1140.   {
  1141.     if (tape.recording)
  1142.       TapeHaltRecording();    /* prepare tape for saving on-the-fly */
  1143.  
  1144.     if (TAPE_IS_EMPTY(tape))
  1145.       Request("No tape that can be saved !", REQ_CONFIRM);
  1146.     else
  1147.       SaveTape(tape.level_nr);
  1148.   }
  1149.   else if (game_status == GAME_MODE_MAIN)
  1150.     Request("No game that can be saved !", REQ_CONFIRM);
  1151. }
  1152.  
  1153. void TapeQuickLoad()
  1154. {
  1155.   if (tape.recording && !Request("Stop recording and load tape ?",
  1156.                  REQ_ASK | REQ_STAY_CLOSED))
  1157.   {
  1158.     BlitBitmap(bitmap_db_door, bitmap_db_door,
  1159.            DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
  1160.            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
  1161.     OpenDoor(DOOR_OPEN_1);
  1162.  
  1163.     return;
  1164.   }
  1165.  
  1166.   if (game_status == GAME_MODE_PLAYING || game_status == GAME_MODE_MAIN)
  1167.   {
  1168.     TapeStop();
  1169.     TapeErase();
  1170.  
  1171.     LoadTape(level_nr);
  1172.     if (!TAPE_IS_EMPTY(tape))
  1173.     {
  1174.       TapeStartGamePlaying();
  1175.       TapeStartWarpForward();
  1176.  
  1177.       tape.quick_resume = TRUE;
  1178.     }
  1179.     else
  1180.       Request("No tape for this level !", REQ_CONFIRM);
  1181.   }
  1182. }
  1183.  
  1184. void InsertSolutionTape()
  1185. {
  1186.   if (!TAPE_IS_EMPTY(tape))
  1187.     return;
  1188.  
  1189.   LoadSolutionTape(level_nr);
  1190.  
  1191.   if (TAPE_IS_EMPTY(tape))
  1192.     Request("No solution tape for this level !", REQ_CONFIRM);
  1193.  
  1194.   DrawCompleteVideoDisplay();
  1195. }
  1196.  
  1197.  
  1198. /* ------------------------------------------------------------------------- *
  1199.  * tape autoplay functions
  1200.  * ------------------------------------------------------------------------- */
  1201.  
  1202. #define MAX_NUM_AUTOPLAY_LEVELS        1000
  1203.  
  1204. void AutoPlayTape()
  1205. {
  1206.   static LevelDirTree *autoplay_leveldir = NULL;
  1207.   static boolean autoplay_initialized = FALSE;
  1208.   static int autoplay_level_nr = -1;
  1209.   static int num_levels_played = 0;
  1210.   static int num_levels_solved = 0;
  1211.   static boolean levels_failed[MAX_NUM_AUTOPLAY_LEVELS];
  1212.   int i;
  1213.  
  1214.   if (autoplay_initialized)
  1215.   {
  1216.     /* just finished auto-playing tape */
  1217.     printf("%s.\n", tape.auto_play_level_solved ? "solved" : "NOT SOLVED");
  1218.  
  1219.     num_levels_played++;
  1220.     if (tape.auto_play_level_solved)
  1221.       num_levels_solved++;
  1222.     else if (level_nr >= 0 && level_nr < MAX_NUM_AUTOPLAY_LEVELS)
  1223.       levels_failed[level_nr] = TRUE;
  1224.   }
  1225.   else
  1226.   {
  1227.     DrawCompleteVideoDisplay();
  1228.     audio.sound_enabled = FALSE;
  1229.  
  1230.     autoplay_leveldir = getTreeInfoFromIdentifier(leveldir_first,
  1231.                           global.autoplay_leveldir);
  1232.  
  1233.     if (autoplay_leveldir == NULL)
  1234.       Error(ERR_EXIT, "no such level identifier: '%s'",
  1235.         global.autoplay_leveldir);
  1236.  
  1237.     leveldir_current = autoplay_leveldir;
  1238.  
  1239.     if (global.autoplay_level_nr != -1)
  1240.     {
  1241.       autoplay_leveldir->first_level = global.autoplay_level_nr;
  1242.       autoplay_leveldir->last_level  = global.autoplay_level_nr;
  1243.     }
  1244.  
  1245.     autoplay_level_nr = autoplay_leveldir->first_level;
  1246.  
  1247.     printf_line("=", 79);
  1248.     printf("Automatically playing level tapes\n");
  1249.     printf_line("-", 79);
  1250.     printf("Level series identifier: '%s'\n", autoplay_leveldir->identifier);
  1251.     printf("Level series name:       '%s'\n", autoplay_leveldir->name);
  1252.     printf("Level series author:     '%s'\n", autoplay_leveldir->author);
  1253.     printf("Number of levels:        %d\n",   autoplay_leveldir->levels);
  1254.     printf_line("=", 79);
  1255.     printf("\n");
  1256.  
  1257.     for (i = 0; i < MAX_NUM_AUTOPLAY_LEVELS; i++)
  1258.       levels_failed[i] = FALSE;
  1259.  
  1260.     autoplay_initialized = TRUE;
  1261.   }
  1262.  
  1263.   while (autoplay_level_nr <= autoplay_leveldir->last_level)
  1264.   {
  1265.     level_nr = autoplay_level_nr++;
  1266.  
  1267.     TapeErase();
  1268.  
  1269.     printf("Level %03d: ", level_nr);
  1270.  
  1271.     LoadLevel(level_nr);
  1272.     if (level.no_valid_file)
  1273.     {
  1274.       printf("(no level)\n");
  1275.       continue;
  1276.     }
  1277.  
  1278.     LoadSolutionTape(level_nr);
  1279. #if 1
  1280.     if (tape.no_valid_file)
  1281. #else
  1282.     if (TAPE_IS_EMPTY(tape))
  1283. #endif
  1284.     {
  1285.       printf("(no tape)\n");
  1286.       continue;
  1287.     }
  1288.  
  1289.     printf("playing tape ... ");
  1290.  
  1291.     TapeStartGamePlaying();
  1292.     TapeStartWarpForward();
  1293.  
  1294.     return;
  1295.   }
  1296.  
  1297.   printf("\n");
  1298.   printf_line("=", 79);
  1299.   printf("Number of levels played: %d\n", num_levels_played);
  1300.   printf("Number of levels solved: %d (%d%%)\n", num_levels_solved,
  1301.      (num_levels_played ? num_levels_solved * 100 / num_levels_played :0));
  1302.   printf_line("-", 79);
  1303.   printf("Summary (for automatic parsing by scripts):\n");
  1304.   printf("LEVELDIR '%s', SOLVED %d/%d (%d%%)",
  1305.      autoplay_leveldir->identifier, num_levels_solved, num_levels_played,
  1306.      (num_levels_played ? num_levels_solved * 100 / num_levels_played :0));
  1307.  
  1308.   if (num_levels_played != num_levels_solved)
  1309.   {
  1310.     printf(", FAILED:");
  1311.     for (i = 0; i < MAX_NUM_AUTOPLAY_LEVELS; i++)
  1312.       if (levels_failed[i])
  1313.     printf(" %03d", i);
  1314.   }
  1315.  
  1316.   printf("\n");
  1317.   printf_line("=", 79);
  1318.  
  1319.   CloseAllAndExit(0);
  1320. }
  1321.  
  1322.  
  1323. /* ---------- new tape button stuff ---------------------------------------- */
  1324.  
  1325. /* graphic position values for tape buttons */
  1326. #define TAPE_BUTTON_XSIZE    18
  1327. #define TAPE_BUTTON_YSIZE    18
  1328. #define TAPE_BUTTON_XPOS    5
  1329. #define TAPE_BUTTON_YPOS    77
  1330.  
  1331. #define TAPE_BUTTON_EJECT_XPOS    (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
  1332. #define TAPE_BUTTON_EXTRA_XPOS    (TAPE_BUTTON_XPOS + 0 * TAPE_BUTTON_XSIZE)
  1333. #define TAPE_BUTTON_STOP_XPOS    (TAPE_BUTTON_XPOS + 1 * TAPE_BUTTON_XSIZE)
  1334. #define TAPE_BUTTON_PAUSE_XPOS    (TAPE_BUTTON_XPOS + 2 * TAPE_BUTTON_XSIZE)
  1335. #define TAPE_BUTTON_RECORD_XPOS    (TAPE_BUTTON_XPOS + 3 * TAPE_BUTTON_XSIZE)
  1336. #define TAPE_BUTTON_PLAY_XPOS    (TAPE_BUTTON_XPOS + 4 * TAPE_BUTTON_XSIZE)
  1337.  
  1338. static struct
  1339. {
  1340.   int x, y;
  1341.   int gadget_id;
  1342.   char *infotext;
  1343. } tapebutton_info[NUM_TAPE_BUTTONS] =
  1344. {
  1345.   {
  1346.     TAPE_BUTTON_EJECT_XPOS,    TAPE_BUTTON_YPOS,
  1347.     TAPE_CTRL_ID_EJECT,
  1348.     "eject tape"
  1349.   },
  1350.   {
  1351.     TAPE_BUTTON_EXTRA_XPOS,    TAPE_BUTTON_YPOS,
  1352.     TAPE_CTRL_ID_EXTRA,
  1353.     "extra functions"
  1354.   },
  1355.   {
  1356.     TAPE_BUTTON_STOP_XPOS,    TAPE_BUTTON_YPOS,
  1357.     TAPE_CTRL_ID_STOP,
  1358.     "stop tape"
  1359.   },
  1360.   {
  1361.     TAPE_BUTTON_PAUSE_XPOS,    TAPE_BUTTON_YPOS,
  1362.     TAPE_CTRL_ID_PAUSE,
  1363.     "pause tape"
  1364.   },
  1365.   {
  1366.     TAPE_BUTTON_RECORD_XPOS,    TAPE_BUTTON_YPOS,
  1367.     TAPE_CTRL_ID_RECORD,
  1368.     "record tape"
  1369.   },
  1370.   {
  1371.     TAPE_BUTTON_PLAY_XPOS,    TAPE_BUTTON_YPOS,
  1372.     TAPE_CTRL_ID_PLAY,
  1373.     "play tape"
  1374.   }
  1375. };
  1376.  
  1377. void CreateTapeButtons()
  1378. {
  1379.   int i;
  1380.  
  1381.   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
  1382.   {
  1383.     Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
  1384.     struct GadgetInfo *gi;
  1385.     int gd_xoffset, gd_yoffset;
  1386.     int gd_x1, gd_x2, gd_y;
  1387.     int id = i;
  1388.  
  1389.     gd_xoffset = tapebutton_info[i].x;
  1390.     gd_yoffset = tapebutton_info[i].y;
  1391.     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
  1392.     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
  1393.     gd_y  = DOOR_GFX_PAGEY2 + gd_yoffset;
  1394.  
  1395.     if (i == TAPE_CTRL_ID_EXTRA)
  1396.     {
  1397.       gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
  1398.       gd_x2 = DOOR_GFX_PAGEX5 + gd_xoffset;
  1399.     }
  1400.  
  1401.     gi = CreateGadget(GDI_CUSTOM_ID, id,
  1402.               GDI_INFO_TEXT, tapebutton_info[i].infotext,
  1403.               GDI_X, VX + gd_xoffset,
  1404.               GDI_Y, VY + gd_yoffset,
  1405.               GDI_WIDTH, TAPE_BUTTON_XSIZE,
  1406.               GDI_HEIGHT, TAPE_BUTTON_YSIZE,
  1407.               GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
  1408.               GDI_STATE, GD_BUTTON_UNPRESSED,
  1409.               GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
  1410.               GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
  1411.               GDI_EVENT_MASK, GD_EVENT_RELEASED,
  1412.               GDI_CALLBACK_ACTION, HandleTapeButtons,
  1413.               GDI_END);
  1414.  
  1415.     if (gi == NULL)
  1416.       Error(ERR_EXIT, "cannot create gadget");
  1417.  
  1418.     tape_gadget[id] = gi;
  1419.   }
  1420. }
  1421.  
  1422. void FreeTapeButtons()
  1423. {
  1424.   int i;
  1425.  
  1426.   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
  1427.     FreeGadget(tape_gadget[i]);
  1428. }
  1429.  
  1430. void MapTapeEjectButton()
  1431. {
  1432.   UnmapGadget(tape_gadget[TAPE_CTRL_ID_EXTRA]);
  1433.   MapGadget(tape_gadget[TAPE_CTRL_ID_EJECT]);
  1434. }
  1435.  
  1436. void MapTapeWarpButton()
  1437. {
  1438.   UnmapGadget(tape_gadget[TAPE_CTRL_ID_EJECT]);
  1439.   MapGadget(tape_gadget[TAPE_CTRL_ID_EXTRA]);
  1440. }
  1441.  
  1442. void MapTapeButtons()
  1443. {
  1444.   int i;
  1445.  
  1446.   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
  1447.     if (i != TAPE_CTRL_ID_EXTRA)
  1448.       MapGadget(tape_gadget[i]);
  1449.  
  1450.   if (tape.recording || tape.playing)
  1451.     MapTapeWarpButton();
  1452. }
  1453.  
  1454. void UnmapTapeButtons()
  1455. {
  1456.   int i;
  1457.  
  1458.   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
  1459.     UnmapGadget(tape_gadget[i]);
  1460. }
  1461.  
  1462. static void HandleTapeButtons(struct GadgetInfo *gi)
  1463. {
  1464.   int id = gi->custom_id;
  1465.  
  1466.   if (game_status != GAME_MODE_MAIN && game_status != GAME_MODE_PLAYING)
  1467.     return;
  1468.  
  1469.   switch (id)
  1470.   {
  1471.     case TAPE_CTRL_ID_EJECT:
  1472.       TapeStop();
  1473.       if (TAPE_IS_EMPTY(tape))
  1474.       {
  1475.     LoadTape(level_nr);
  1476.     if (TAPE_IS_EMPTY(tape))
  1477.       Request("No tape for this level !", REQ_CONFIRM);
  1478.       }
  1479.       else
  1480.       {
  1481.     if (tape.changed)
  1482.       SaveTape(tape.level_nr);
  1483.     TapeErase();
  1484.       }
  1485.       DrawCompleteVideoDisplay();
  1486.       break;
  1487.  
  1488.     case TAPE_CTRL_ID_EXTRA:
  1489.       if (tape.playing)
  1490.       {
  1491.     if (!tape.warp_forward)            /* PLAY -> WARP FORWARD PLAY */
  1492.     {
  1493.       TapeStartWarpForward();
  1494.     }
  1495.     else                    /* WARP FORWARD PLAY -> PLAY */
  1496.     {
  1497.       TapeStopWarpForward();
  1498.  
  1499. #if 0
  1500.       if (tape.pause_before_death)
  1501.         DrawVideoDisplay(VIDEO_STATE_WARP_OFF | VIDEO_STATE_PLAY_ON, 0);
  1502.       else if (tape.fast_forward)
  1503.         DrawVideoDisplay(VIDEO_STATE_WARP_OFF | VIDEO_STATE_FFWD_ON, 0);
  1504.       else
  1505.         DrawVideoDisplay(VIDEO_STATE_WARP_OFF | VIDEO_STATE_PBEND_ON, 0);
  1506. #endif
  1507.     }
  1508.       }
  1509.       else if (tape.recording)
  1510.     TapeSingleStep();
  1511.       break;
  1512.  
  1513.     case TAPE_CTRL_ID_STOP:
  1514.       TapeStop();
  1515.       break;
  1516.  
  1517.     case TAPE_CTRL_ID_PAUSE:
  1518.       TapeTogglePause(TAPE_TOGGLE_MANUAL);
  1519.       break;
  1520.  
  1521.     case TAPE_CTRL_ID_RECORD:
  1522.       if (TAPE_IS_STOPPED(tape))
  1523.     TapeStartGameRecording();
  1524.       else if (tape.pausing)
  1525.       {
  1526.     if (tape.playing)            /* PLAY -> PAUSE -> RECORD */
  1527.       TapeAppendRecording();
  1528.     else
  1529.       TapeTogglePause(TAPE_TOGGLE_MANUAL);
  1530.       }
  1531.       break;
  1532.  
  1533.     case TAPE_CTRL_ID_PLAY:
  1534.       if (TAPE_IS_EMPTY(tape))
  1535.     break;
  1536.  
  1537.       if (TAPE_IS_STOPPED(tape))
  1538.       {
  1539.     TapeStartGamePlaying();
  1540.       }
  1541.       else if (tape.playing)
  1542.       {
  1543.     if (tape.pausing)            /* PAUSE -> PLAY */
  1544.     {
  1545.       TapeTogglePause(TAPE_TOGGLE_MANUAL);
  1546.     }
  1547.     else if (!tape.fast_forward)        /* PLAY -> FAST FORWARD PLAY */
  1548.     {
  1549.       tape.fast_forward = TRUE;
  1550.       DrawVideoDisplay(VIDEO_STATE_FFWD_ON, 0);
  1551.     }
  1552.     else if (!tape.pause_before_death)    /* FFWD PLAY -> AUTO PAUSE */
  1553.     {
  1554.       tape.pause_before_death = TRUE;
  1555. #if 1
  1556.       DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PBEND_ON, 0);
  1557. #else
  1558.       DrawVideoDisplay(VIDEO_STATE_PBEND_ON, VIDEO_DISPLAY_LABEL_ONLY);
  1559. #endif
  1560.     }
  1561.     else                    /* AUTO PAUSE -> NORMAL PLAY */
  1562.     {
  1563. #if 1
  1564.       if (tape.warp_forward)
  1565.         TapeStopWarpForward();
  1566. #else
  1567.       tape.warp_forward = FALSE;
  1568. #endif
  1569.       tape.fast_forward = FALSE;
  1570.       tape.pause_before_death = FALSE;
  1571.  
  1572. #if 1
  1573.       DrawVideoDisplay(VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PLAY_ON, 0);
  1574. #else
  1575.       DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PBEND_OFF, 0);
  1576. #endif
  1577.     }
  1578.       }
  1579.       break;
  1580.  
  1581.     default:
  1582.       break;
  1583.   }
  1584. }
  1585.