home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 25 / amigaformatcd25.iso / websites / amidoom / adoom_src-0.7.lha / ADoom_src / amiga_video.c < prev    next >
C/C++ Source or Header  |  1998-01-16  |  41KB  |  1,251 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. #include <exec/exec.h>
  7. #include <dos/dos.h>
  8. #include <graphics/gfx.h>
  9. #include <graphics/gfxbase.h>
  10. #include <graphics/gfxmacros.h>
  11. #include <intuition/intuition.h>
  12. #include <libraries/asl.h>
  13. #include <libraries/lowlevel.h>
  14. #include <cybergraphics/cybergraphics.h>
  15. #include <devices/gameport.h>
  16.  
  17. #include <proto/exec.h>
  18. #include <proto/dos.h>
  19. #include <proto/graphics.h>
  20. #include <proto/layers.h>
  21. #include <proto/intuition.h>
  22. #include <proto/asl.h>
  23. #include <proto/lowlevel.h>
  24. #include <proto/cybergraphics.h>
  25.  
  26. #include "doomtype.h"
  27. #include "doomdef.h"
  28. #include "doomstat.h"
  29. #include "i_system.h"
  30. #include "i_video.h"
  31. #include "v_video.h"
  32. #include "m_argv.h"
  33. #include "d_main.h"
  34.  
  35. #include "amiga_median.h"
  36. #include "c2p_020.h"
  37. #include "c2p_030.h"
  38. #include "c2p_040.h"
  39. #include "c2p8_040_amlaukka.h"
  40. #include "mmu.h"
  41.  
  42. /*experimental_c2p_stuff***********************************************/
  43. extern int scaledviewwidth;
  44. void REGARGS (*c2p)(REG(a0, const UBYTE *chunky),
  45.                     REG(a1, UBYTE *raster),
  46.                     REG(a2, const UBYTE *chunky_end)) = NULL;
  47.  
  48. /**********************************************************************/
  49. extern struct ExecBase *SysBase;
  50. struct Library *AslBase = NULL;
  51. struct Library *CyberGfxBase = NULL;
  52. struct Library *LowLevelBase = NULL;
  53.  
  54. extern int cpu_type;
  55.  
  56. static struct ScreenModeRequester *video_smr = NULL;
  57. static struct Screen *video_screen = NULL;
  58. static struct Window *video_window = NULL;
  59. static struct BitMap video_bitmap[3] = {
  60.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
  61.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
  62.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}
  63. };
  64. static PLANEPTR video_raster[3] = {NULL, NULL, NULL};    /* contiguous bitplanes */
  65. static UBYTE *video_compare_buffer[3] = {NULL, NULL, NULL};    /* in fastmem */
  66. static struct ScreenBuffer *video_sb[2] = {NULL, NULL};
  67. static struct DBufInfo *video_db = NULL;
  68. static struct MsgPort *video_mp = NULL;
  69. static int video_which = 0;
  70. static BYTE video_sigbit1 = -1;
  71. static BYTE video_sigbit2 = -1;
  72. static volatile BYTE video_sigbit3 = -1;
  73. static struct Task *video_maintask;
  74. static struct Task *video_fliptask = NULL;
  75. static int video_depth = 0;
  76. static int video_oscan_height;
  77. static struct RastPort *video_rastport = NULL;
  78. static ULONG video_colourtable[1 + 3*256 + 1];
  79. static volatile WORD video_palette_changed = 0;
  80. static BOOL video_is_ehb_mode = FALSE;
  81. static BOOL video_is_native_mode = FALSE;
  82. static BOOL video_is_cyber_mode = FALSE;
  83. static BOOL video_is_using_blitter = FALSE;
  84. static BOOL video_blit_is_in_progress = FALSE;
  85. static BOOL video_use_mmu = FALSE;
  86. static BOOL video_is_directcgx = FALSE;
  87. static BOOL video_bitmap_is_locked = FALSE;
  88. static APTR video_bitmap_handle;
  89. static int video_f_cache_mode;
  90. static int video_c_cache_mode;
  91. static struct RastPort video_temprp;
  92. static struct BitMap video_tmp_bm = {
  93.   0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
  94. };
  95. static UBYTE video_xlate[256];   /* xlate colour from 8-bit to 6-bit EHB */
  96. static UWORD __chip emptypointer[] = {
  97.   0x0000, 0x0000,    /* reserved, must be NULL */
  98.   0x0000, 0x0000,     /* 1 row of image data */
  99.   0x0000, 0x0000    /* reserved, must be NULL */
  100. };
  101.  
  102. /* gameport stuff */
  103. static struct MsgPort *gameport_mp = NULL;
  104. static struct IOStdReq *gameport_io = NULL;
  105. static BOOL gameport_is_open = FALSE;
  106. static BOOL gameport_io_in_progress = FALSE;
  107. static struct InputEvent gameport_ie;
  108. static BYTE gameport_ct;        /* controller type */
  109. struct GamePortTrigger gameport_gpt = {
  110.   GPTF_UPKEYS | GPTF_DOWNKEYS,    /* gpt_Keys */
  111.   0,                /* gpt_Timeout */
  112.   1,                /* gpt_XDelta */
  113.   1                /* gpt_YDelta */
  114. };
  115.  
  116. static unsigned int start_time[2];
  117. static unsigned int blit_time = 0;
  118. static unsigned int safe_time = 0;
  119. static unsigned int c2p_time = 0;
  120. static unsigned int wpa8_time = 0;
  121. static unsigned int lock_time = 0;
  122. static unsigned int total_frames = 0;
  123.  
  124. /****************************************************************************/
  125. static __inline void start_timer (void)
  126. {
  127.   timer (start_time);
  128. }
  129.  
  130. /****************************************************************************/
  131. static __inline unsigned int end_timer (void)
  132. {
  133.   unsigned int end_time[2];
  134.  
  135.   timer (end_time);
  136.   if (end_time[1] >= start_time[1])
  137.     return end_time[1] - start_time[1] + 50;
  138.   else
  139.     return end_time[1] + 1000000 - start_time[1];
  140. }
  141.  
  142. /****************************************************************************/
  143.  
  144. static char *mode_name (ULONG mode)
  145. /* Return a mode name for given mode, compatible with ASL mode requester */
  146. /* Use name in DisplayInfo database if available */
  147. /* else manually construct the name */
  148. {
  149.   APTR handle;
  150.   char *p;
  151.   struct NameInfo nameinfo;
  152.   struct DimensionInfo dimsinfo;
  153.   static char modename[DISPLAYNAMELEN + 4 + 4 + 11 + 1];
  154.  
  155.   p = modename;
  156.   *p = '\0';
  157.   if ((handle = FindDisplayInfo (mode & ~SPRITES)) != NULL) {
  158.     if (GetDisplayInfoData (handle, (UBYTE *)&nameinfo,
  159.                             sizeof(nameinfo), DTAG_NAME,
  160.                             NULL) > sizeof(struct QueryHeader)) {
  161.       p += sprintf (p, "%s", nameinfo.Name);
  162.     } else if (GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  163.                                    sizeof(dimsinfo), DTAG_DIMS,
  164.                                    NULL) >= 66 /* sizeof(dimsinfo)*/) {
  165.       switch (mode & MONITOR_ID_MASK) {
  166.         case DEFAULT_MONITOR_ID:
  167.           p += sprintf (p, "DEFAULT:");      /* PAL or NTSC??? */
  168.           break;
  169.         case NTSC_MONITOR_ID:
  170.           p += sprintf (p, "NTSC:");
  171.           break;
  172.         case PAL_MONITOR_ID:
  173.           p += sprintf (p, "PAL:");
  174.           break;
  175.         case VGA_MONITOR_ID:
  176.           p += sprintf (p, "MULTISCAN:");
  177.           break;
  178.         case A2024_MONITOR_ID:
  179.           p += sprintf (p, "A2024:");
  180.           break;
  181.         case PROTO_MONITOR_ID:
  182.           p += sprintf (p, "PROTO:");
  183.           break;
  184.         case EURO72_MONITOR_ID:
  185.           p += sprintf (p, "EURO72:");
  186.           break;
  187.         case EURO36_MONITOR_ID:
  188.           p += sprintf (p, "EURO36:");
  189.           break;
  190.         case SUPER72_MONITOR_ID:
  191.           p += sprintf (p, "SUPER72:");
  192.           break;
  193.         case DBLNTSC_MONITOR_ID:
  194.           p += sprintf (p, "DBLNTSC:");
  195.           break;
  196.         case DBLPAL_MONITOR_ID:
  197.           p += sprintf (p, "DBLPAL:");
  198.           break;
  199.         default:
  200.           p += sprintf (p, "(unknown):");
  201.           break;
  202.       }
  203.       p += sprintf (p, "%d x %d",
  204.                     dimsinfo.Nominal.MaxX - dimsinfo.Nominal.MinX + 1,
  205.                     dimsinfo.Nominal.MaxY - dimsinfo.Nominal.MinY + 1);
  206.       if ((mode & HAM_KEY) != 0)
  207.         p += sprintf (p, " HAM");
  208.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  209.         p += sprintf (p, " EHB");
  210.       if ((mode & LACE) != 0)
  211.         p += sprintf (p, " Interlaced");
  212.     } else {
  213.       p += sprintf (p, "%s", "(unnamed)");
  214.       if ((mode & HAM_KEY) != 0)
  215.         p += sprintf (p, " HAM");
  216.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  217.         p += sprintf (p, " EHB");
  218.       if ((mode & LACE) != 0)
  219.         p += sprintf (p, " Interlaced");
  220.     }
  221.   } else {
  222.     p += sprintf (p, "%s", "(unavailable)");
  223.   }
  224.   return (modename);
  225. }
  226.  
  227. /****************************************************************************/
  228.  
  229. static ULONG parse_mode (char *modename)
  230. /* Modename may be descriptive name ("PAL Lores"), or hex ("$00420001" or */
  231. /* "0x12345678") or decimal ("32768"). */
  232. {
  233.   ULONG mode, reason;
  234.  
  235.   mode = INVALID_ID;
  236.   if (modename != NULL) {
  237.     if (modename[0] == '0' && modename[1] == 'x') {
  238.       if (sscanf (&modename[2], "%lx", &mode) != 1)
  239.         mode = INVALID_ID;
  240.     } else if (modename[0] == '$') {
  241.       if (sscanf (&modename[1], "%lx", &mode) != 1)
  242.         mode = INVALID_ID;
  243.     } else if (modename[0] >= '0' && modename[0] <= '9') {
  244.       if (sscanf (modename, "%ld", &mode) != 1)
  245.         mode = INVALID_ID;
  246.     } else {
  247.       while ((mode = NextDisplayInfo (mode)) != INVALID_ID) {
  248.         if ((mode & LORESDPF_KEY) == 0) {
  249.           /* printf ("$%08x  \"%s\"\n", mode, mode_name (mode)); */
  250.           if (strcmp (mode_name (mode), modename) == 0)
  251.             break;
  252.         }
  253.       }
  254.     }
  255.   }
  256.   if (FindDisplayInfo (mode) == NULL)
  257.     I_Error ("ScreenMode not in database: \"%s\"", modename);
  258.   if ((reason = ModeNotAvailable (mode)) != 0)
  259.     I_Error ("Mode $%08x is not available: %ld", mode, reason);
  260.   return (mode);
  261. }
  262.  
  263. /**********************************************************************/
  264. // This asynchronous task waits in a loop for sigbit3 signals.
  265. // Sigbit3 is signalled when the next frame is just finished.
  266. // Sigbit3 may be signalled from the qblit() cleanup function or from the
  267. // main task.
  268. // On receipt of sigbit3, we load the new palette and call ChangeScreenBuffer().
  269. // This way there is no delay calling ChangeScreenBuffer() after the last blit
  270. // has finished.
  271. // The main 3D rendering task may be interrupted to call ChangeScreenBuffer()
  272. // SIGBREAKF_CTRL_F and SIGBREAKF_CTRL_C are used for synchronisation
  273. // with the main task.
  274.  
  275. static void __saveds __interrupt video_flipscreentask (void)
  276. {
  277.   ULONG sig;
  278.   struct MsgPort *video_dispport, *video_safeport;
  279.   BOOL going, video_disp, video_safe;
  280.   int i;
  281.  
  282.   video_sigbit3 = AllocSignal(-1);
  283.   Signal (video_maintask, SIGBREAKF_CTRL_F);
  284.   video_dispport = CreatePort (NULL, 0);
  285.   video_safeport = CreatePort (NULL, 0);
  286.   video_disp = TRUE;
  287.   video_safe = TRUE;
  288.   for (i = 0; i < 2; i++) {
  289.     video_sb[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = video_dispport;
  290.     video_sb[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = video_safeport;
  291.   }
  292.   going = (video_sigbit3 != -1) &&
  293.           (video_dispport != NULL) &&
  294.           (video_safeport != NULL);
  295.   while (going) {
  296.     sig = Wait (1 << video_sigbit3 | SIGBREAKF_CTRL_C);
  297.     if ((sig & (1 << video_sigbit3)) != 0) {
  298.       LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  299.       if ((ChangeScreenBuffer (video_screen, video_sb[video_which])) != 0) {
  300.         video_disp = FALSE;
  301.         video_safe = FALSE;
  302.       }
  303.       if (!video_safe) {  /* wait until safe */
  304.         Wait (1 << video_safeport->mp_SigBit);
  305.         while (GetMsg (video_safeport) != NULL) /* clear message queue */
  306.           /* do nothing */ ;
  307.         video_safe = TRUE;
  308.       }
  309.       Signal (video_maintask, SIGBREAKF_CTRL_F);
  310.       if (!video_disp) {  /* wait for previous frame to be displayed */
  311.         Wait (1 << video_dispport->mp_SigBit);
  312.         while (GetMsg (video_dispport) != NULL) /* clear message queue */
  313.           /* do nothing */ ;
  314.         video_disp = TRUE;
  315.       }
  316.     }
  317.     if ((sig & SIGBREAKF_CTRL_C) != 0) {
  318.       going = FALSE;
  319.     }
  320.   }
  321.   if (!video_safe) {  /* wait for safe */
  322.     Wait (1 << video_safeport->mp_SigBit);
  323.     while (GetMsg (video_safeport) != NULL) /* clear message queue */
  324.       /* do nothing */ ;
  325.     video_safe = TRUE;
  326.   }
  327.   if (!video_disp) {  /* wait for last frame to be displayed */
  328.     Wait (1 << video_dispport->mp_SigBit);
  329.     while (GetMsg (video_dispport) != NULL) /* clear message queue */
  330.       /* do nothing */ ;
  331.     video_disp = TRUE;
  332.   }
  333.   if (video_sigbit3 != -1)
  334.     FreeSignal (video_sigbit3);
  335.   if (video_dispport != NULL)
  336.     DeletePort (video_dispport);
  337.   if (video_safeport != NULL)
  338.     DeletePort (video_safeport);
  339.   Signal (video_maintask, SIGBREAKF_CTRL_F);
  340.   Wait (0);
  341. }
  342.  
  343. /**********************************************************************/
  344. // Called by D_DoomMain,
  345. // determines the hardware configuration
  346. // and sets up the video mode
  347. void I_InitGraphics (void)
  348. {
  349.   int i;
  350.   ULONG propertymask, idcmp, wflags, width, pixfmt;
  351.   struct Rectangle rect;
  352.   char reqtitle[32];
  353.   int mode, depth, nbytes, p;
  354.   DisplayInfoHandle handle;
  355.   struct DisplayInfo dispinfo;
  356.   struct DimensionInfo dimsinfo;
  357.  
  358.   video_maintask = FindTask(NULL);
  359.  
  360.   if (AslBase == NULL) {
  361.     if ((AslBase = OpenLibrary ("asl.library", 37L)) == NULL ||
  362.         (video_smr = AllocAslRequestTags (ASL_ScreenModeRequest, TAG_DONE)) == NULL) {
  363.       I_Error ("OpenLibrary(""asl.library"", 37) failed");
  364.     }
  365.   }
  366.  
  367.   /* first check tooltypes for SCREENMODE */
  368.   mode = -1;
  369.   p = M_CheckParm ("-screenmode");
  370.   if (p && p < myargc - 1) {
  371.     mode = parse_mode (myargv[p+1]);
  372.   }
  373.  
  374.   /* if not found in icon tooltypes, then put up a ScreenMode requester */
  375.   if (mode == -1) {
  376.     propertymask = /* DIPF_IS_EXTRAHALFBRITE | */ DIPF_IS_DUALPF |
  377.                    DIPF_IS_PF2PRI | DIPF_IS_HAM;
  378.     if (GfxBase->LibNode.lib_Version >= 39)
  379.       mode = BestModeID (BIDTAG_NominalWidth,     SCREENWIDTH,
  380.                          BIDTAG_NominalHeight,    SCREENHEIGHT,
  381.                          BIDTAG_Depth,            video_depth,
  382.                          BIDTAG_DIPFMustNotHave,  propertymask,
  383.                          TAG_DONE);
  384.     else
  385.       mode = EXTRAHALFBRITE_KEY;
  386.     if (AslBase->lib_Version >= 38) {
  387.       sprintf (reqtitle, "ADoom %dx%d", SCREENWIDTH, SCREENHEIGHT);
  388.       if (!AslRequestTags (video_smr,
  389.                            ASLSM_TitleText,        (ULONG)reqtitle,
  390.                            ASLSM_InitialDisplayID, mode,
  391.                            ASLSM_MinWidth,         SCREENWIDTH,
  392.                            ASLSM_MinHeight,        SCREENHEIGHT,
  393.                            ASLSM_MinDepth,         6,
  394.                            ASLSM_MaxDepth,         8,
  395.                            ASLSM_PropertyMask,     propertymask,
  396.                            ASLSM_PropertyFlags,    0,
  397.                            TAG_DONE)) {
  398.         I_Error ("AslRequest() failed");
  399.       }
  400.       mode = video_smr->sm_DisplayID;
  401.     }
  402.   }
  403.  
  404.   if ((handle = FindDisplayInfo (mode)) == NULL) {
  405.     I_Error ("Can't FindDisplayInfo() for mode %08x", mode);
  406.   }
  407.   if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dispinfo,
  408.                                     sizeof(struct DisplayInfo), DTAG_DISP,
  409.                                     NULL)) < 40 /*sizeof(struct DisplayInfo)*/) {
  410.     I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  411.              mode, nbytes);
  412.   }
  413.   if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  414.                                     sizeof(dimsinfo), DTAG_DIMS,
  415.                                     NULL)) < 66 /* sizeof(dimsinfo)*/) {
  416.     I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  417.              mode, nbytes);
  418.   }
  419.  
  420.   video_oscan_height = dimsinfo.MaxOScan.MaxY - dimsinfo.MaxOScan.MinY + 1;
  421.  
  422.   video_is_cyber_mode = 0;
  423.   if ((CyberGfxBase = OpenLibrary ("cybergraphics.library", 0)) != NULL) {
  424.     video_is_cyber_mode = IsCyberModeID (mode);
  425.   }
  426.  
  427.   /* this test needs improving */
  428.   video_is_native_mode = ((GfxBase->LibNode.lib_Version < 39 ||
  429.                            (dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0 ||
  430.                            (dispinfo.PropertyFlags & DIPF_IS_AA) != 0 ||
  431.                            (dispinfo.PropertyFlags & DIPF_IS_ECS) != 0 ||
  432.                            (dispinfo.PropertyFlags & DIPF_IS_DBUFFER) != 0) &&
  433.                           !video_is_cyber_mode &&
  434.                           (dispinfo.PropertyFlags & DIPF_IS_FOREIGN) == 0);
  435.  
  436.   video_is_ehb_mode = ((dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0);
  437.  
  438.   printf ("Screen Mode $%08x is ", mode);
  439.   if (video_is_native_mode)
  440.     printf (" NATIVE-PLANAR");
  441.   else
  442.     printf (" FOREIGN");
  443.   if (video_is_ehb_mode)
  444.     printf (" EXTRAHALFBRITE");
  445.   else
  446.     printf (" 8-BIT");
  447.   if (video_is_cyber_mode)
  448.     printf (" CYBERGRAPHX");
  449.   printf ("\n");
  450.  
  451.   if (video_is_ehb_mode)
  452.     video_depth = 6;
  453.   else
  454.     video_depth = 8;
  455.  
  456.   rect.MinX = 0;
  457.   rect.MinY = 0;
  458.   rect.MaxX = SCREENWIDTH - 1;
  459.   rect.MaxY = SCREENHEIGHT - 1;
  460.  
  461.   if (M_CheckParm ("-mmu") && cpu_type >= 68040)
  462.        video_use_mmu = true;
  463.  
  464.   if (video_is_native_mode) {
  465.     video_is_using_blitter = (cpu_type < 68040);
  466.  
  467.     for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  468.       /* use the mmu hack only if cpu is 68040+ and user specified -mmu */
  469.       if (video_use_mmu) {
  470.         ULONG *ptr, mem;
  471.         mem = (ULONG)AllocVec (SCREENWIDTH * SCREENHEIGHT / 8 * video_depth +
  472.                                4100, MEMF_CHIP);
  473.         if (!mem)
  474.           I_Error ("AllocVec() failed");
  475.         ptr = (ULONG*)((mem & ~0xfff) + 4096);
  476.     ptr[-1] = 4096 - (mem & 0xfff);
  477.     video_raster[i] = (byte *)ptr;
  478.         video_c_cache_mode = mmu_mark (video_raster[i],
  479.                                    SCREENWIDTH * SCREENHEIGHT / 8 * video_depth,
  480.                                    CM_IMPRECISE, SysBase);
  481.       } else {
  482.         if ((video_raster[i] = (PLANEPTR)AllocRaster (SCREENWIDTH,
  483.                                            video_depth * SCREENHEIGHT)) == NULL)
  484.           I_Error ("AllocRaster() failed");
  485.       }
  486.       memset (video_raster[i], 0, video_depth * RASSIZE (SCREENWIDTH, SCREENHEIGHT));
  487.       InitBitMap (&video_bitmap[i], video_depth, SCREENWIDTH, SCREENHEIGHT);
  488.       for (depth = 0; depth < video_depth; depth++)
  489.         video_bitmap[i].Planes[depth] = video_raster[i] +
  490.                                     depth * RASSIZE (SCREENWIDTH, SCREENHEIGHT);
  491.     }
  492.  
  493.     /* experimental c2p stuff */
  494.     if (!video_is_using_blitter)
  495.       c2p = c2p8_reloc (screens[0], &video_bitmap[0], SysBase);
  496.  
  497.     if ((video_screen = OpenScreenTags (NULL,
  498.           SA_Type,        CUSTOMSCREEN | CUSTOMBITMAP,
  499.           SA_DisplayID,   mode,
  500.           SA_DClip,       (ULONG)&rect,
  501.           SA_Width,       SCREENWIDTH,
  502.           SA_Height,      SCREENHEIGHT,
  503.           SA_Depth,       video_depth,
  504.           /* SA_Draggable,FALSE, */
  505.           /* SA_AutoScroll,FALSE, */
  506.           /* SA_Exclusive,TRUE, */
  507.           SA_Quiet,       TRUE,
  508.           SA_BitMap,      &video_bitmap[0], /* custom bitmap, contiguous planes */
  509.           TAG_DONE)) == NULL) {
  510.       I_Error ("OpenScreen() failed");
  511.     }
  512.     for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  513.       if ((video_compare_buffer[i] = malloc (SCREENWIDTH * SCREENHEIGHT)) == NULL)
  514.         I_Error ("Out of memory allocating %d bytes", SCREENWIDTH * SCREENHEIGHT);
  515.       memset (video_compare_buffer[i], 0, SCREENWIDTH * SCREENHEIGHT);
  516.     }
  517.     if (video_is_using_blitter) {
  518.       for (i = 0; i < 2; i++) {
  519.     if ((video_sb[i] = AllocScreenBuffer (video_screen, &video_bitmap[i], 0)) == NULL)
  520.       I_Error ("Can't allocate structure for double buffering");
  521.       }
  522.     } else {
  523.       video_db = AllocDBufInfo (&video_screen->ViewPort);
  524.       video_mp = CreateMsgPort ();
  525.       if (!video_db || !video_mp)
  526.         I_Error ("Can't allocate dbuffer information");
  527.       video_db->dbi_DispMessage.mn_ReplyPort = video_mp;
  528.       video_which = 1;
  529.       ChangeVPBitMap (&video_screen->ViewPort, &video_bitmap[0], video_db);
  530.     }
  531.   } else {
  532.     if (video_is_cyber_mode && M_CheckParm ("-directcgx"))
  533.       video_is_directcgx = TRUE;
  534.     if ((video_screen = OpenScreenTags (NULL,
  535.           SA_Type,        CUSTOMSCREEN,
  536.           SA_DisplayID,   mode,
  537.           SA_DClip,       (ULONG)&rect,
  538.           SA_Width,       SCREENWIDTH,
  539.           SA_Height,      video_is_directcgx ? video_oscan_height << 1 : SCREENHEIGHT,
  540.           SA_Depth,       video_depth,
  541.           /* SA_Draggable,FALSE, */
  542.           /* SA_AutoScroll,FALSE, */
  543.           /* SA_Exclusive,TRUE, */
  544.           SA_Quiet,       TRUE,
  545.           TAG_DONE)) == NULL) {
  546.       I_Error ("OpenScreen() failed");
  547.     }
  548.   }
  549.  
  550.   if (video_is_directcgx) {
  551.     video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  552.                                           LBMI_WIDTH,       &width,
  553.                                           LBMI_DEPTH,       &depth,
  554.                                           LBMI_PIXFMT,      &pixfmt,
  555.                                           LBMI_BASEADDRESS, &screens[0],
  556.                                           TAG_DONE);
  557.     UnLockBitMap (video_bitmap_handle);
  558.     if (/* width != SCREENWIDTH || */
  559.         depth != video_depth ||
  560.         pixfmt != PIXFMT_LUT8) {
  561.       I_Error ("ScreenMode of width %d, depth %d, pixfmt %d cannot be used with -directcgx",
  562.                width, depth, pixfmt);
  563.     }
  564.   } else {
  565.     if (video_use_mmu) {
  566.       video_f_cache_mode = mmu_mark (screens[0],
  567.                                      (SCREENWIDTH * SCREENHEIGHT + 4096) & ~0xfff,
  568.                                      CM_WRITETHROUGH, SysBase);
  569.     }
  570.   }
  571.  
  572.   idcmp = IDCMP_RAWKEY;
  573.   wflags = WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_RMBTRAP;
  574.   if (M_CheckParm("-mouse") != NULL) {
  575.     idcmp |= IDCMP_MOUSEMOVE | IDCMP_DELTAMOVE | IDCMP_MOUSEBUTTONS;
  576.     wflags |= WFLG_REPORTMOUSE;
  577.   }
  578.  
  579.   if ((video_window = OpenWindowTags (NULL,
  580.         WA_Left,         0,
  581.         WA_Top,          0,
  582.         WA_Width,        SCREENWIDTH,
  583.         WA_Height,       SCREENHEIGHT,
  584.         WA_IDCMP,        idcmp,
  585.         WA_Flags,        wflags,
  586.         WA_CustomScreen, video_screen,
  587.         TAG_DONE)) == NULL) {
  588.     I_Error ("OpenWindow() failed");
  589.   }
  590.   video_rastport = video_window->RPort;
  591.  
  592.   InitBitMap (&video_tmp_bm, video_depth, SCREENWIDTH, 1);
  593.   for (depth = 0; depth < video_depth; depth++)
  594.     if ((video_tmp_bm.Planes[depth] = (PLANEPTR)AllocRaster (SCREENWIDTH, 1)) == NULL)
  595.       I_Error ("AllocRaster() failed");
  596.   video_temprp = *video_rastport;
  597.   video_temprp.Layer = NULL;
  598.   video_temprp.BitMap = &video_tmp_bm;
  599.  
  600.   SetPointer (video_window, emptypointer, 1, 16, 0, 0);
  601.  
  602.   if (video_is_native_mode) {
  603.     if (video_is_using_blitter) {
  604.       if ((video_sigbit1 = AllocSignal(-1)) == -1 ||
  605.       (video_sigbit2 = AllocSignal(-1)) == -1)
  606.     I_Error ("Can't allocate signal!\n");
  607.       Signal (video_maintask, (1 << video_sigbit1) | (1 << video_sigbit2));
  608.                                                 /* initial state is finished */
  609.       if ((video_fliptask = CreateTask ("ADoom_flipscreen", 5,
  610.                     video_flipscreentask, 4096)) == NULL)
  611.     I_Error ("Can't create subtask");
  612.       Wait (SIGBREAKF_CTRL_F);
  613.       if (video_sigbit3 == -1)
  614.     I_Error ("Subtask couldn't allocate sigbit");
  615.       if (!video_is_ehb_mode)
  616.         c2p1x1_cpu3blit1_queue_init (SCREENWIDTH, SCREENHEIGHT, 0,
  617.                                      SCREENWIDTH * SCREENHEIGHT / 8,
  618.                                      1 << video_sigbit1, 1 << video_sigbit3,
  619.                                      video_maintask, video_fliptask);
  620.     }
  621.   }
  622.  
  623.   /* joystick initialisation */
  624.  
  625.   if (M_CheckParm ("-joypad") != NULL) {
  626.  
  627.     if ((LowLevelBase = OpenLibrary ("lowlevel.library", 0)) == NULL)
  628.       I_Error ("-joypad option specified and can't open lowlevel.library");
  629.  
  630.   } else {
  631.  
  632.     if ((gameport_mp = CreatePort (NULL, 0)) == NULL ||
  633.         (gameport_io = (struct IOStdReq *)CreateExtIO (gameport_mp,
  634.                                               sizeof(struct IOStdReq))) == NULL ||
  635.         OpenDevice ("gameport.device", 1, (struct IORequest *)gameport_io, 0) != 0)
  636.       I_Error ("Can't open gameport.device");
  637.  
  638.     gameport_is_open = TRUE;
  639.  
  640.     Forbid ();
  641.  
  642.     gameport_io->io_Command = GPD_ASKCTYPE;
  643.     gameport_io->io_Length = 1;
  644.     gameport_io->io_Data = &gameport_ct;
  645.     DoIO ((struct IORequest *)gameport_io);
  646.  
  647.     if (gameport_ct != GPCT_NOCONTROLLER) {
  648.  
  649.       Permit ();
  650.       fprintf (stderr, "Another task is using the gameport!  Joystick disabled");
  651.       CloseDevice ((struct IORequest *)gameport_io);
  652.       gameport_is_open = FALSE;
  653.  
  654.     } else {
  655.  
  656.       gameport_ct = GPCT_ABSJOYSTICK;
  657.       gameport_io->io_Command = GPD_SETCTYPE;
  658.       gameport_io->io_Length = 1;
  659.       gameport_io->io_Data = &gameport_ct;
  660.       DoIO ((struct IORequest *)gameport_io);
  661.  
  662.       Permit ();
  663.  
  664.       gameport_io->io_Command = GPD_SETTRIGGER;
  665.       gameport_io->io_Length = sizeof(struct GamePortTrigger);
  666.       gameport_io->io_Data = &gameport_gpt;
  667.       DoIO ((struct IORequest *)gameport_io);
  668.  
  669.       gameport_io->io_Command = GPD_READEVENT;
  670.       gameport_io->io_Length = sizeof (struct InputEvent);
  671.       gameport_io->io_Data = &gameport_ie;
  672.       SendIO ((struct IORequest *)gameport_io);
  673.       gameport_io_in_progress = TRUE;
  674.     }
  675.   }
  676. }
  677.  
  678. /**********************************************************************/
  679. void I_ShutdownGraphics (void)
  680. {
  681.   int depth, i;
  682.  
  683.   if (video_is_directcgx && video_bitmap_is_locked) {
  684.     UnLockBitMap (video_bitmap_handle);
  685.     video_bitmap_is_locked = FALSE;
  686.   }
  687.   if (LowLevelBase != NULL) {
  688.     CloseLibrary (LowLevelBase);
  689.     LowLevelBase = NULL;
  690.   }
  691.   if (gameport_io_in_progress) {
  692.     AbortIO ((struct IORequest *)gameport_io);
  693.     WaitIO ((struct IORequest *)gameport_io);
  694.     gameport_io_in_progress = FALSE;
  695.     gameport_ct = GPCT_NOCONTROLLER;
  696.     gameport_io->io_Command = GPD_SETCTYPE;
  697.     gameport_io->io_Length = 1;
  698.     gameport_io->io_Data = &gameport_ct;
  699.     DoIO ((struct IORequest *)gameport_io);
  700.   }
  701.   if (gameport_is_open) {
  702.     CloseDevice ((struct IORequest *)gameport_io);
  703.     gameport_is_open = FALSE;
  704.   }
  705.   if (gameport_io != NULL) {
  706.     DeleteExtIO ((struct IORequest *)gameport_io);
  707.     gameport_io = NULL;
  708.   }
  709.   if (gameport_mp != NULL) {
  710.     DeletePort (gameport_mp);
  711.     gameport_mp = NULL;
  712.   }
  713.   if (video_blit_is_in_progress) {
  714.     Wait (SIGBREAKF_CTRL_F);
  715.     video_blit_is_in_progress = FALSE;
  716.   }
  717.   if (video_fliptask != NULL) {
  718.     Signal (video_fliptask, SIGBREAKF_CTRL_C);
  719.     Wait (SIGBREAKF_CTRL_F);
  720.     DeleteTask (video_fliptask);
  721.     video_fliptask = NULL;
  722.   }
  723.   if (video_is_using_blitter) {
  724.     if (video_sigbit1 != -1) {
  725.       Wait (1 << video_sigbit1);  // wait for last c2p8 to finish pass 3
  726.     FreeSignal (video_sigbit1);
  727.       video_sigbit1 = -1;
  728.     }
  729.     if (video_sigbit2 != -1) {
  730.       Wait (1 << video_sigbit2);  // wait for last c2p8 to completely finish
  731.     FreeSignal (video_sigbit2);
  732.       video_sigbit2 = -1;
  733.     }
  734.   }
  735.   if (video_window != NULL) {
  736.     ClearPointer (video_window);
  737.     CloseWindow (video_window);
  738.     video_window = NULL;
  739.   }
  740.   if (video_is_using_blitter) {
  741.     for (i = 0; i < 2; i++) {
  742.       if (video_sb[i] != NULL) {
  743.     FreeScreenBuffer (video_screen, video_sb[i]);
  744.     video_sb[i] = NULL;
  745.       }
  746.     }
  747.   } else {
  748.     if (video_mp) {
  749.       WaitPort (video_mp);
  750.       while (GetMsg(video_mp));
  751.       DeleteMsgPort (video_mp);
  752.       video_mp = NULL; 
  753.     }
  754.     if (video_db) {
  755.       FreeDBufInfo (video_db);
  756.       video_db = NULL;
  757.     }
  758.   }
  759.   if (video_screen != NULL) {
  760.     CloseScreen (video_screen);
  761.     video_screen = NULL;
  762.   }
  763.   for (depth = 0; depth < video_depth; depth++) {
  764.     if (video_tmp_bm.Planes[depth] != NULL) {
  765.       FreeRaster (video_tmp_bm.Planes[depth], SCREENWIDTH, 1);
  766.       video_tmp_bm.Planes[depth] = NULL;
  767.     }
  768.   }
  769.   for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  770.     if (video_raster[i] != NULL) {
  771.       if (video_use_mmu) {
  772.         ULONG *ptr = (ULONG *)video_raster[i];
  773.         UBYTE *p2 = (UBYTE *)ptr;
  774.         mmu_mark (video_raster[i], SCREENWIDTH * SCREENHEIGHT / 8 * video_depth,
  775.                   video_c_cache_mode, SysBase);
  776.         FreeVec (p2 - ptr[-1]);
  777.       } else
  778.         FreeRaster (video_raster[i], SCREENWIDTH, video_depth * SCREENHEIGHT);
  779.       video_raster[i] = NULL;
  780.     }
  781.     if (video_compare_buffer[i] != NULL) {
  782.       free (video_compare_buffer[i]);
  783.       video_compare_buffer[i] = NULL;
  784.     }
  785.   }
  786.   if (video_use_mmu && !video_is_directcgx) {
  787.     if (screens[0] != NULL)
  788.       mmu_mark (screens[0], (SCREENWIDTH * SCREENHEIGHT + 4096) & ~0xfff,
  789.                 video_f_cache_mode, SysBase);
  790.   }
  791.   if (CyberGfxBase == NULL) {
  792.     CloseLibrary (CyberGfxBase);
  793.     CyberGfxBase = NULL;
  794.   }
  795.   /* experimental c2p stuff */
  796.   if (c2p && !video_is_using_blitter) {
  797.     c2p8_deinit (c2p, SysBase);
  798.     c2p = NULL;
  799.   }
  800. }
  801.  
  802. /**********************************************************************/
  803. // Takes full 8 bit values.
  804. void I_SetPalette (byte *palette)
  805. {
  806.   int i;
  807.   ULONG c, *p;
  808.   UBYTE *g;
  809.   static UBYTE gpalette[3*256];
  810.  
  811.   /* printf ("I_SetPalette()\n"); */
  812.   if (video_is_ehb_mode) {
  813.     g = gpalette;
  814.     for (i = 0; i < 256; i++) {
  815.       *g++ = gammatable[usegamma][*palette++];
  816.       *g++ = gammatable[usegamma][*palette++];
  817.       *g++ = gammatable[usegamma][*palette++];
  818.     }
  819.     video_colourtable[0] = (32 << 16) + 0;
  820.     median_cut (gpalette, &video_colourtable[1], video_xlate);
  821.     video_colourtable[33] = 0;
  822.   } else {
  823.     p = video_colourtable;
  824.     *p++ = (256 << 16) + 0;
  825.     for (i = 0; i < 256; i++) {
  826.       c = (ULONG)gammatable[usegamma][*palette++];
  827.       c += (c<<8);
  828.       c += (c<<16);
  829.       *p++ = c;
  830.       c = (ULONG)gammatable[usegamma][*palette++];
  831.       c += (c<<8);
  832.       c += (c<<16);
  833.       *p++ = c;
  834.       c = (ULONG)gammatable[usegamma][*palette++];
  835.       c += (c<<8);
  836.       c += (c<<16);
  837.       *p++ = c;
  838.     }
  839.     *p++ = 0;
  840.   }
  841.   if (video_is_ehb_mode)
  842.     if (video_is_using_blitter) {
  843.       video_palette_changed = 2;  /* double buffering */
  844.     } else
  845.       video_palette_changed = 3;  /* triple buffering */
  846.   else
  847.     video_palette_changed = 1;
  848. }
  849.  
  850. /**********************************************************************/
  851. void I_StartUpdate (void)
  852. {
  853.   UBYTE *base_address;
  854.  
  855.   if (video_is_directcgx) {
  856.     if (video_palette_changed != 0) {
  857.       LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  858.       video_palette_changed = 0;
  859.     }
  860.     if (!video_bitmap_is_locked) {
  861.       start_timer ();
  862.       video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  863.                                             LBMI_BASEADDRESS, &base_address,
  864.                                             TAG_DONE);
  865.       lock_time += end_timer ();
  866.       video_bitmap_is_locked = TRUE;
  867. /*
  868.       video_which = 1 - video_which;
  869.       if (video_which != 0)
  870.         screens[0] = base_address + (SCREENWIDTH * video_oscan_height);
  871.       else
  872. */
  873.       screens[0] = base_address;
  874.     }
  875.   }
  876. }
  877.  
  878. /**********************************************************************/
  879. void I_UpdateNoBlit (void)
  880. {
  881. }
  882.  
  883. /**********************************************************************/
  884. void I_FinishUpdate (void)
  885. /* This needs optimising to copy just the parts that changed,
  886.    especially if the user has shrunk the playscreen. */
  887. {
  888.   total_frames++;
  889.  
  890.   if (video_is_directcgx) {
  891.     if (video_bitmap_is_locked) {
  892.       UnLockBitMap (video_bitmap_handle);
  893.       video_bitmap_is_locked = FALSE;
  894. /*
  895.       video_screen->ViewPort.RasInfo->RyOffset = video_which != 0 ?
  896.                                                          video_oscan_height : 0;
  897.       ScrollVPort (&video_screen->ViewPort);
  898. */
  899.     } else
  900.       I_Error ("I_FinishUpdate() called without calling I_StartUpdate() first");
  901.     return;
  902.   }
  903.  
  904.   if (video_is_native_mode) {
  905.     if (video_is_using_blitter) {
  906.       start_timer();
  907.       Wait (1 << video_sigbit1); /* wait for prev c2p() to finish pass 3 */
  908.       blit_time += end_timer();
  909.       if (video_blit_is_in_progress) {
  910.     start_timer();
  911.     Wait (SIGBREAKF_CTRL_F); /* wait for prev ChangeScreenBuffer() safe */
  912.     safe_time += end_timer();
  913.     video_blit_is_in_progress = FALSE;
  914.       }
  915.       video_which = 1 - video_which;  /* render to the hidden bitmap */
  916.       start_timer();
  917.       if (video_is_ehb_mode) {
  918.         c2p_6_020 (screens[0],
  919.                    video_bitmap[video_which].Planes,
  920.                    1 << video_sigbit1, 1 << video_sigbit2, 1 << video_sigbit3,
  921.                    SCREENWIDTH * SCREENHEIGHT, 0, video_xlate, video_fliptask);
  922.       } else {
  923.         if (cpu_type < 68030)
  924.           c2p_8_020 (screens[0],
  925.                      video_bitmap[video_which].Planes,
  926.                      1 << video_sigbit1, 1 << video_sigbit2, 1 << video_sigbit3,
  927.                      SCREENWIDTH * SCREENHEIGHT, 0, video_fliptask);
  928.         else
  929.           c2p1x1_cpu3blit1_queue (screens[0], video_raster[video_which]);
  930.       }
  931.       c2p_time += end_timer();
  932.       video_blit_is_in_progress = TRUE;
  933.       if (video_palette_changed > 0) {
  934.         video_palette_changed--; /* keep it set for 2 frames for dblbuffering */
  935.       }
  936.     } else {
  937.       start_timer();
  938.       if (video_is_ehb_mode) {
  939.         c2p_6_040 (screens[0], video_raster[video_which],
  940.                    video_compare_buffer[video_which], video_xlate,
  941.                    (SCREENWIDTH * SCREENHEIGHT) >> 3,
  942.                    video_palette_changed);
  943.         if (video_palette_changed > 0) {
  944.           if (video_palette_changed == 3)
  945.             LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  946.           video_palette_changed--;
  947.         }
  948.       } else {
  949.         if (c2p && scaledviewwidth == SCREENWIDTH)
  950.            c2p (screens[0], video_raster[video_which],
  951.                 screens[0] + SCREENWIDTH * SCREENHEIGHT);
  952.         else
  953.           c2p_8_040 (screens[0], video_raster[video_which],
  954.                      video_compare_buffer[video_which],
  955.                    (SCREENWIDTH * SCREENHEIGHT) >> 3);
  956.         if (video_palette_changed != 0) {
  957.           LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  958.           video_palette_changed = 0;
  959.         }
  960.       }
  961.       c2p_time += end_timer();
  962.       WaitPort (video_mp);
  963.       while (GetMsg (video_mp))
  964.     /* do nothing */ ;
  965.       ChangeVPBitMap (&video_screen->ViewPort, &video_bitmap[video_which],
  966.                       video_db);
  967.       if (++video_which == 3)
  968.         video_which = 0;
  969.     }
  970.   } else {
  971.     if (video_palette_changed != 0) {
  972.       LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  973.       video_palette_changed = 0;
  974.     }
  975.     start_timer();
  976.     WritePixelArray8 (video_rastport, 0, 0, SCREENWIDTH-1, SCREENHEIGHT-1,
  977.                       screens[0], &video_temprp);
  978.     wpa8_time += end_timer();
  979.   }
  980. }
  981.  
  982. /**********************************************************************/
  983. // Wait for vertical retrace or pause a bit.  Use when quit game.
  984. void I_WaitVBL(int count)
  985. {
  986.   for ( ; count > 0; count--)
  987.     WaitTOF();
  988. }
  989.  
  990. /**********************************************************************/
  991. void I_ReadScreen (byte* scr)
  992. {
  993. /*
  994.   if (video_is_directcgx) {
  995.     printf ("I_ReadScreen() %d %d\n", video_which, video_bitmap_is_locked);
  996.     ReadPixelArray8 (video_rastport, 0,
  997.                      video_which != 0 ? 0 : video_oscan_height,
  998.                      SCREENWIDTH-1, SCREENHEIGHT-1, scr, &video_temprp);
  999.   } else
  1000. */
  1001. /*
  1002.   if (video_is_directcgx)
  1003.     if (video_which)
  1004.       memcpy (scr, screens[0] - SCREENWIDTH * video_oscan_height,
  1005.               SCREENWIDTH * SCREENHEIGHT);
  1006.     else
  1007.       memcpy (scr, screens[0] + SCREENWIDTH * video_oscan_height,
  1008.               SCREENWIDTH * SCREENHEIGHT);
  1009.   else
  1010. */
  1011.   memcpy (scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
  1012. }
  1013.  
  1014. /**********************************************************************/
  1015. void I_BeginRead (void)
  1016. {
  1017. }
  1018.  
  1019. /**********************************************************************/
  1020. void I_EndRead (void)
  1021. {
  1022. }
  1023.  
  1024. /**********************************************************************/
  1025. void amiga_getevents (void)
  1026. {
  1027.   event_t event;
  1028.   ULONG class;
  1029.   UWORD code;
  1030.   WORD mousex, mousey;
  1031.   struct IntuiMessage *msg;
  1032.   static ULONG previous = 0;
  1033.   static int xlate[0x68] = {
  1034.     '`', '1', '2', '3', '4', '5', '6', '7',
  1035.     '8', '9', '0', KEY_MINUS, KEY_EQUALS, '\\', 0, '0',
  1036.     'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  1037.     'o', 'p', KEY_F11, KEY_F12, 0, '0', '2', '3',
  1038.     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
  1039.     'l', ';', '\'', KEY_ENTER, 0, '4', '5', '6',
  1040.     KEY_RSHIFT, 'z', 'x', 'c', 'v', 'b', 'n', 'm',
  1041.     ',', '.', '/', 0, '.', '7', '8', '9',
  1042.     ' ', KEY_BACKSPACE, KEY_TAB, KEY_ENTER, KEY_ENTER, KEY_ESCAPE, KEY_BACKSPACE,
  1043.     0, 0, 0, KEY_MINUS, 0, KEY_UPARROW, KEY_DOWNARROW, KEY_RIGHTARROW, KEY_LEFTARROW,
  1044.     KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
  1045.     KEY_F9, KEY_F10, '(', ')', '/', '*', KEY_EQUALS, KEY_PAUSE,
  1046.     KEY_RSHIFT, KEY_RSHIFT, 0, KEY_RCTRL, KEY_LALT, KEY_RALT, 0, KEY_RCTRL
  1047.   };
  1048.   static event_t joyevent = {0}, mouseevent = {0};
  1049.  
  1050.   if (video_window != NULL) {
  1051.     while ((msg = (struct IntuiMessage *)GetMsg (video_window->UserPort)) != NULL) {
  1052.       class = msg->Class;
  1053.       code = msg->Code;
  1054.       mousex = msg->MouseX;
  1055.       mousey = msg->MouseY;
  1056.       ReplyMsg ((struct Message *)msg);
  1057.       if (class == IDCMP_RAWKEY) {
  1058.         if ((code & 0x80) != 0) {
  1059.           code &= ~0x80;
  1060.       event.type = ev_keyup;
  1061.         } else {
  1062.           event.type = ev_keydown;
  1063.         }
  1064.         if (code < 0x68 && xlate[code] != 0) {
  1065.           event.data1 = xlate[code];
  1066.           D_PostEvent (&event);
  1067.         }
  1068.       } else if (class == IDCMP_MOUSEMOVE) {
  1069.         mouseevent.type = ev_mouse;
  1070.         mouseevent.data2 = (mousex << 3);
  1071.         mouseevent.data3 = -(mousey << 5);
  1072.         D_PostEvent (&mouseevent);
  1073.       } else if (class == IDCMP_MOUSEBUTTONS) {
  1074.         mouseevent.type = ev_mouse;
  1075.         switch (code) {
  1076.           case SELECTDOWN:
  1077.             mouseevent.data1 |= 1;
  1078.             break;
  1079.           case SELECTUP:
  1080.             mouseevent.data1 &= ~1;
  1081.             break;
  1082.           case MENUDOWN:
  1083.             mouseevent.data1 |= 2;
  1084.             break;
  1085.           case MENUUP:
  1086.             mouseevent.data1 &= ~2;
  1087.             break;
  1088.           case MIDDLEDOWN:
  1089.             mouseevent.data1 |= 4;
  1090.             break;
  1091.           case MIDDLEUP:
  1092.             mouseevent.data1 &= ~4;
  1093.             break;
  1094.           default:
  1095.             break;
  1096.         }
  1097.         D_PostEvent (&mouseevent);
  1098.       }
  1099.     }
  1100.   }
  1101.  
  1102.   if (gameport_is_open && gameport_io_in_progress) {
  1103.     while (GetMsg (gameport_mp) != NULL) {
  1104.       switch (gameport_ie.ie_Code) {
  1105.         case IECODE_LBUTTON:
  1106.           joyevent.data1 |= 1;
  1107.           break;
  1108.         case IECODE_LBUTTON | IECODE_UP_PREFIX:
  1109.           joyevent.data1 &= ~1;
  1110.           break;
  1111.         case IECODE_RBUTTON:
  1112.           joyevent.data1 |= 2;
  1113.           break;
  1114.         case IECODE_RBUTTON | IECODE_UP_PREFIX:
  1115.           joyevent.data1 &= ~2;
  1116.           break;
  1117.         case IECODE_MBUTTON:
  1118.           joyevent.data1 |= 4;
  1119.           break;
  1120.         case IECODE_MBUTTON | IECODE_UP_PREFIX:
  1121.           joyevent.data1 &= ~4;
  1122.           break;
  1123.         case IECODE_NOBUTTON:
  1124.           joyevent.data2 = gameport_ie.ie_X;
  1125.           joyevent.data3 = gameport_ie.ie_Y;
  1126.           break;
  1127.         default:
  1128.           break;
  1129.       }
  1130.       joyevent.type = ev_joystick;
  1131.       D_PostEvent (&joyevent);
  1132.       gameport_io->io_Command = GPD_READEVENT;
  1133.       gameport_io->io_Length = sizeof (struct InputEvent);
  1134.       gameport_io->io_Data = &gameport_ie;
  1135.       SendIO ((struct IORequest *)gameport_io);
  1136.     }
  1137.   }
  1138.  
  1139.   /* CD32 joypad handler code supplied by Gabry (ggreco@iol.it) */
  1140.  
  1141.   if (LowLevelBase != NULL) {
  1142.     event_t joyevent;
  1143.     ULONG joypos = ReadJoyPort (1);
  1144.  
  1145.     if (previous == joypos)
  1146.       return;
  1147.  
  1148.     joyevent.type = ev_joystick;
  1149.     joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
  1150.  
  1151.     if (joypos & JPF_BUTTON_RED)
  1152.       joyevent.data1 |= 1;
  1153.     else
  1154.       joyevent.data1 &= ~1;
  1155.  
  1156.     if (joypos & JP_DIRECTION_MASK) {
  1157.       if (joypos & JPF_JOY_LEFT) {
  1158.         joyevent.data2 = -1;
  1159.       } else if (joypos & JPF_JOY_RIGHT) {
  1160.         joyevent.data2 = 1;
  1161.       }
  1162.       if (joypos & JPF_JOY_UP) {
  1163.         joyevent.data3 = -1;
  1164.       } else if (joypos & JPF_JOY_DOWN) {
  1165.         joyevent.data3 = 1;
  1166.       }
  1167.     }
  1168.  
  1169.     if (joypos & JP_TYPE_GAMECTLR) {
  1170.       event_t event;
  1171.  
  1172.       // Play/Pause = ESC (Menu)
  1173.       if (joypos & JPF_BUTTON_PLAY && !(previous & JPF_BUTTON_PLAY)) {
  1174.         event.type = ev_keydown;
  1175.         event.data1 = KEY_ESCAPE;
  1176.         D_PostEvent (&event);
  1177.       } else if (previous & JPF_BUTTON_PLAY) {
  1178.         event.type = ev_keyup;
  1179.         event.data1 = KEY_ESCAPE;
  1180.         D_PostEvent (&event);
  1181.       }
  1182.  
  1183.       // YELLOW = SHIFT (button 2) (Run)
  1184.       if (joypos & JPF_BUTTON_YELLOW)
  1185.         joyevent.data1 |= 4;
  1186.       else
  1187.         joyevent.data1 &= ~4;
  1188.  
  1189.       // BLUE = SPACE (button 3) (Open/Operate)
  1190.  
  1191.       if (joypos & JPF_BUTTON_BLUE)
  1192.         joyevent.data1 |= 8;
  1193.       else
  1194.         joyevent.data1 &= ~8;
  1195.  
  1196.       // GREEN = RETURN (show msg)
  1197.  
  1198.       if (joypos & JPF_BUTTON_GREEN && !(previous&JPF_BUTTON_GREEN)) {
  1199.         event.type = ev_keydown;
  1200.         event.data1 = 13;
  1201.         D_PostEvent (&event);
  1202.       } else if (previous & JPF_BUTTON_GREEN) {
  1203.         event.type = ev_keyup;
  1204.         event.data1 = 13;
  1205.         D_PostEvent (&event);
  1206.       }
  1207.  
  1208.       // FORWARD & REVERSE - ALT (Button1) Strafe left/right
  1209.  
  1210.       if (joypos & JPF_BUTTON_FORWARD) {
  1211.         joyevent.data1 |= 2;
  1212.         joyevent.data2 = 1;
  1213.       } else if (joypos & JPF_BUTTON_REVERSE) {
  1214.         joyevent.data1 |=2;
  1215.         joyevent.data2=-1;
  1216.       } else
  1217.         joyevent.data1 &= ~2;
  1218.     }
  1219.  
  1220.     D_PostEvent (&joyevent);
  1221.  
  1222.     previous = joypos;
  1223.   }
  1224.  
  1225. }
  1226.  
  1227. /**********************************************************************/
  1228. void _STDvideo_cleanup (void)
  1229. {
  1230.   I_ShutdownGraphics ();
  1231.   if (video_smr != NULL) {
  1232.     FreeAslRequest (video_smr);
  1233.     video_smr = NULL;
  1234.   }
  1235.   if (total_frames > 0) {
  1236.     printf ("Total number of frames = %u\n", total_frames);
  1237.     printf ("Total blit wait time   = %u us  (%u us/frame)\n", blit_time,
  1238.             blit_time / total_frames);
  1239.     printf ("Total safe wait time   = %u us  (%u us/frame)\n", safe_time,
  1240.             safe_time / total_frames);
  1241.     printf ("Total C2P time         = %u us  (%u us/frame)\n", c2p_time,
  1242.             c2p_time / total_frames);
  1243.     printf ("Total WPA8 time        = %u us  (%u us/frame)\n", wpa8_time,
  1244.             wpa8_time / total_frames);
  1245.     printf ("Total LockBitMap time  = %u us  (%u us/frame)\n", lock_time,
  1246.             lock_time / total_frames);
  1247.   }
  1248. }
  1249.  
  1250. /**********************************************************************/
  1251.