# Correct the needed linklibs in curl-config also.
[AROS-Contrib.git] / Games / Doom / amiga_video.c
blob5af650eb27f16ea0c4614a6f5d5a0463a942ab23
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #include <exec/exec.h>
6 #include <dos/dos.h>
7 #include <graphics/gfx.h>
8 #include <graphics/gfxbase.h>
9 #include <graphics/gfxmacros.h>
10 #include <intuition/intuition.h>
11 #include <libraries/asl.h>
12 #include <libraries/lowlevel.h>
13 #include <cybergraphics/cybergraphics.h>
14 #include <devices/gameport.h>
15 #include <devices/keymap.h>
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/keymap.h>
24 #include <proto/lowlevel.h>
25 #include <proto/cybergraphics.h>
27 #ifdef GRAFFITI
28 #include "graffiti.h"
29 #include "graffiti_lib.h"
30 #include "graffiti_protos.h"
31 #endif
33 #include "doomtype.h"
34 #include "doomdef.h"
35 #include "doomstat.h"
36 #include "i_system.h"
37 #include "i_video.h"
38 #include "v_video.h"
39 #include "m_argv.h"
40 #include "m_bbox.h"
41 #include "d_main.h"
43 #include "amiga_sega.h"
44 #include "r_draw.h"
45 #include "w_wad.h"
46 #include "z_zone.h"
48 /**********************************************************************/
49 extern void ppctimer (unsigned int *time);
50 extern int bus_MHz;
52 extern void ppc_c2p_line (int line, int src, struct BitMap *dst, int cnt);
54 extern struct ExecBase *SysBase;
55 struct Library *AslBase = NULL;
56 struct Library *CyberGfxBase = NULL;
57 struct Library *LowLevelBase = NULL;
58 struct Library *KeymapBase = NULL;
60 extern int cpu_type;
62 int SCREENWIDTH;
63 int SCREENHEIGHT;
64 int weirdaspect;
67 #define NUMPALETTES 14
69 static struct ScreenModeRequester *video_smr = NULL;
70 static struct Screen *video_screen = NULL;
71 static struct Window *video_window = NULL;
73 static struct ScreenBuffer *SBuffer[3] = {NULL, NULL, NULL};
74 static struct ScreenBuffer *NextSBuffer = NULL;
76 static int video_mod = 320;
77 static ULONG video_pixfmt = PIXFMT_LUT8;
78 static ULONG *video_buffer = NULL;
80 static int video_depth = 8;
82 static FAR ULONG video_colourtable[NUMPALETTES][1 + 3*256 + 1];
83 static int video_palette_index = 0;
84 static int video_pending_palette_index = 0;
85 static volatile WORD video_palette_changed = 0;
87 static BOOL video_is_cyber_mode = FALSE;
88 static BOOL video_is_directcgx = FALSE;
89 static BOOL video_is_native = FALSE;
90 static BOOL video_doing_fps = FALSE;
91 static APTR video_bitmap_handle;
93 static struct RastPort video_temprp;
94 static struct BitMap video_tmp_bm = {
95 0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
98 static UWORD *emptypointer;
100 /* keyboard */
101 static BOOL video_is_rawkey;
103 /* gameport stuff */
104 static struct MsgPort *gameport_mp = NULL;
105 static struct IOStdReq *gameport_io = NULL;
106 static BOOL gameport_is_open = FALSE;
107 static BOOL gameport_io_in_progress = FALSE;
108 static struct InputEvent gameport_ie;
109 static BYTE gameport_ct; /* controller type */
110 struct GamePortTrigger gameport_gpt = {
111 GPTF_UPKEYS | GPTF_DOWNKEYS, /* gpt_Keys */
112 0, /* gpt_Timeout */
113 1, /* gpt_XDelta */
114 1 /* gpt_YDelta */
117 /* SEGA variables */
118 static ULONG prevSega;
119 static BOOL sega3_selected = FALSE;
120 static BOOL sega6_selected = FALSE;
122 #ifdef GRAFFITI
123 struct Library *GraffitiBase = NULL;
124 int video_graffiti = 0;
125 static struct GRF_Screen *video_grf_screen = NULL;
126 #endif
128 #ifdef PROFILE
129 unsigned int profile[32][4];
130 #endif
132 /****************************************************************************/
134 static unsigned int start_time[2];
135 static unsigned int wpa8_time = 0;
136 static unsigned int lock_time = 0;
137 static unsigned int c2p_time = 0;
138 static unsigned int total_frames = 0;
140 /****************************************************************************/
141 static __inline void start_timer (void)
143 ppctimer (start_time);
146 /****************************************************************************/
147 static __inline unsigned int end_timer (void)
149 unsigned int end_time[2];
151 ppctimer (end_time);
152 if (end_time[1] >= start_time[1])
153 return (((end_time[1] - start_time[1]) << 2) / bus_MHz);
154 else
155 return (((end_time[1] - start_time[1]) << 2) / bus_MHz + 1000000);
158 /****************************************************************************/
160 static char *mode_name (ULONG mode)
161 /* Return a mode name for given mode, compatible with ASL mode requester */
162 /* Use name in DisplayInfo database if available */
163 /* else manually construct the name */
165 APTR handle;
166 char *p;
167 struct NameInfo nameinfo;
168 struct DimensionInfo dimsinfo;
169 static char modename[DISPLAYNAMELEN + 4 + 4 + 11 + 1];
171 p = modename;
172 *p = '\0';
173 if ((handle = FindDisplayInfo (mode & ~SPRITES)) != NULL) {
174 if (GetDisplayInfoData (handle, (UBYTE *)&nameinfo,
175 sizeof(nameinfo), DTAG_NAME,
176 NULL) > sizeof(struct QueryHeader)) {
177 p += sprintf (p, "%s", nameinfo.Name);
178 } else if (GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
179 sizeof(dimsinfo), DTAG_DIMS,
180 NULL) >= 66 /* sizeof(dimsinfo)*/) {
181 switch (mode & MONITOR_ID_MASK) {
182 case DEFAULT_MONITOR_ID:
183 p += sprintf (p, "DEFAULT:"); /* PAL or NTSC??? */
184 break;
185 case NTSC_MONITOR_ID:
186 p += sprintf (p, "NTSC:");
187 break;
188 case PAL_MONITOR_ID:
189 p += sprintf (p, "PAL:");
190 break;
191 case VGA_MONITOR_ID:
192 p += sprintf (p, "MULTISCAN:");
193 break;
194 case A2024_MONITOR_ID:
195 p += sprintf (p, "A2024:");
196 break;
197 case PROTO_MONITOR_ID:
198 p += sprintf (p, "PROTO:");
199 break;
200 case EURO72_MONITOR_ID:
201 p += sprintf (p, "EURO72:");
202 break;
203 case EURO36_MONITOR_ID:
204 p += sprintf (p, "EURO36:");
205 break;
206 case SUPER72_MONITOR_ID:
207 p += sprintf (p, "SUPER72:");
208 break;
209 case DBLNTSC_MONITOR_ID:
210 p += sprintf (p, "DBLNTSC:");
211 break;
212 case DBLPAL_MONITOR_ID:
213 p += sprintf (p, "DBLPAL:");
214 break;
215 default:
216 p += sprintf (p, "(unknown):");
217 break;
219 p += sprintf (p, "%d x %d",
220 dimsinfo.Nominal.MaxX - dimsinfo.Nominal.MinX + 1,
221 dimsinfo.Nominal.MaxY - dimsinfo.Nominal.MinY + 1);
222 if ((mode & HAM_KEY) != 0)
223 p += sprintf (p, " HAM");
224 if ((mode & EXTRAHALFBRITE_KEY) != 0)
225 p += sprintf (p, " EHB");
226 if ((mode & LACE) != 0)
227 p += sprintf (p, " Interlaced");
228 } else {
229 p += sprintf (p, "%s", "(unnamed)");
230 if ((mode & HAM_KEY) != 0)
231 p += sprintf (p, " HAM");
232 if ((mode & EXTRAHALFBRITE_KEY) != 0)
233 p += sprintf (p, " EHB");
234 if ((mode & LACE) != 0)
235 p += sprintf (p, " Interlaced");
237 } else {
238 p += sprintf (p, "%s", "(unavailable)");
240 return (modename);
243 /****************************************************************************/
245 static ULONG parse_mode (char *modename)
246 /* Modename may be descriptive name ("PAL Lores"), or hex ("$00420001" or */
247 /* "0x12345678") or decimal ("32768"). */
249 ULONG mode, reason;
251 mode = INVALID_ID;
252 if (modename != NULL) {
253 if (modename[0] == '0' && modename[1] == 'x') {
254 if (sscanf (&modename[2], "%lx", &mode) != 1)
255 mode = INVALID_ID;
256 } else if (modename[0] == '$') {
257 if (sscanf (&modename[1], "%lx", &mode) != 1)
258 mode = INVALID_ID;
259 } else if (modename[0] >= '0' && modename[0] <= '9') {
260 if (sscanf (modename, "%ld", &mode) != 1)
261 mode = INVALID_ID;
262 } else {
263 while ((mode = NextDisplayInfo (mode)) != INVALID_ID) {
264 if ((mode & LORESDPF_KEY) == 0) {
265 /* printf ("$%08x \"%s\"\n", mode, mode_name (mode)); */
266 if (strcmp (mode_name (mode), modename) == 0)
267 break;
272 if (FindDisplayInfo (mode) == NULL)
273 I_Error ("ScreenMode not in database: \"%s\"", modename);
274 if ((reason = ModeNotAvailable (mode)) != 0)
275 I_Error ("Mode $%08x is not available: %ld", mode, reason);
276 return (mode);
279 /**********************************************************************/
280 static void video_do_fps (struct RastPort *rp, int yoffset)
282 int x;
283 static unsigned int start_time[2] = {0, 0};
284 unsigned int end_time[2];
285 char msg[4];
287 ppctimer (end_time);
288 if (end_time[1] >= start_time[1])
289 x = (((end_time[1] - start_time[1]) << 2) / bus_MHz);
290 else
291 x = (((end_time[1] - start_time[1]) << 2) / bus_MHz + 1000000);
292 if (x != 0) {
293 x = (1000000 + (x >> 1)) / x; /* round to nearest */
294 msg[0] = (x % 1000) / 100 + '0';
295 msg[1] = (x % 100) / 10 + '0';
296 msg[2] = (x % 10) + '0';
297 msg[3] = '\0';
298 Move (rp, SCREENWIDTH - 24, yoffset + 6);
299 Text (rp, msg, 3);
301 start_time[1] = end_time[1];
304 /**********************************************************************/
305 // Called by D_DoomMain,
306 // determines the hardware configuration
307 // and sets up the video mode
308 void I_InitGraphics (void)
310 ULONG propertymask, idcmp, wflags, width, pixfmt;
311 struct Rectangle rect;
312 char reqtitle[32];
313 int mode, depth, nbytes, p;
314 DisplayInfoHandle handle;
315 struct DisplayInfo dispinfo;
316 struct DimensionInfo dimsinfo;
317 static struct TextAttr topaz8 = {
318 "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
321 if ((KeymapBase = OpenLibrary ("keymap.library", 0)) == NULL)
322 I_Error ("Can't open keymap.library");
324 video_doing_fps = M_CheckParm ("-fps");
326 #ifdef GRAFFITI
327 if (video_graffiti != 0) {
328 if ((GraffitiBase = OpenLibrary ("graffiti.library", 0)) == NULL)
329 I_Error ("Can't open graffiti.library");
330 if ((video_grf_screen = OpenChunkyScreen (video_graffiti)) == NULL)
331 I_Error ("graffiti.library OpenChunkyScreen() failed");
332 video_screen = (struct Screen *)video_grf_screen->GRF_ScreenID;
333 video_depth = 8;
334 } else {
335 #endif
337 if (AslBase == NULL) {
338 if ((AslBase = OpenLibrary ("asl.library", 37L)) == NULL ||
339 (video_smr = AllocAslRequestTags (ASL_ScreenModeRequest, TAG_DONE)) == NULL) {
340 I_Error ("OpenLibrary(""asl.library"", 37) failed");
344 CyberGfxBase = OpenLibrary ("cybergraphics.library", 0); /* may be NULL */
346 /* first check tooltypes for SCREENMODE */
347 mode = -1;
348 p = M_CheckParm ("-screenmode");
349 if (p && p < myargc - 1) {
350 mode = parse_mode (myargv[p+1]);
353 /* if not found in icon tooltypes, then put up a ScreenMode requester */
354 if (mode == -1) {
355 propertymask = DIPF_IS_EXTRAHALFBRITE | DIPF_IS_DUALPF |
356 DIPF_IS_PF2PRI | DIPF_IS_HAM;
357 if (CyberGfxBase != NULL)
358 mode = BestCModeIDTags (CYBRBIDTG_NominalWidth, SCREENWIDTH,
359 CYBRBIDTG_NominalHeight, SCREENHEIGHT,
360 CYBRBIDTG_Depth, 8,
361 TAG_DONE);
362 else if (GfxBase->LibNode.lib_Version >= 39)
363 mode = BestModeID (BIDTAG_NominalWidth, SCREENWIDTH,
364 BIDTAG_NominalHeight, SCREENHEIGHT,
365 BIDTAG_Depth, video_depth,
366 BIDTAG_DIPFMustNotHave, propertymask,
367 TAG_DONE);
368 if (AslBase->lib_Version >= 38) {
369 sprintf (reqtitle, "ADoomPPC %dx%d", SCREENWIDTH, SCREENHEIGHT);
370 if (!AslRequestTags (video_smr,
371 ASLSM_TitleText, (ULONG)reqtitle,
372 ASLSM_InitialDisplayID, mode,
373 ASLSM_MinWidth, SCREENWIDTH,
374 ASLSM_MinHeight, SCREENHEIGHT,
375 ASLSM_MaxWidth, MAXSCREENWIDTH,
376 ASLSM_MaxHeight, MAXSCREENHEIGHT,
377 ASLSM_MinDepth, 8,
378 ASLSM_MaxDepth, 8,
379 ASLSM_PropertyMask, propertymask,
380 ASLSM_PropertyFlags, 0,
381 TAG_DONE)) {
382 I_Error ("AslRequest() failed");
384 mode = video_smr->sm_DisplayID;
388 if ((handle = FindDisplayInfo (mode)) == NULL) {
389 I_Error ("Can't FindDisplayInfo() for mode %08x", mode);
391 if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dispinfo,
392 sizeof(struct DisplayInfo), DTAG_DISP,
393 NULL)) < 40 /*sizeof(struct DisplayInfo)*/) {
394 I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
395 mode, nbytes);
397 if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
398 sizeof(dimsinfo), DTAG_DIMS,
399 NULL)) < 66 /* sizeof(dimsinfo)*/) {
400 I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
401 mode, nbytes);
404 video_is_cyber_mode = 0;
405 if (CyberGfxBase != NULL)
406 video_is_cyber_mode = IsCyberModeID (mode);
408 video_is_native = ((GfxBase->LibNode.lib_Version < 39 ||
409 (dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0 ||
410 (dispinfo.PropertyFlags & DIPF_IS_AA) != 0 ||
411 (dispinfo.PropertyFlags & DIPF_IS_ECS) != 0 ||
412 (dispinfo.PropertyFlags & DIPF_IS_DBUFFER) != 0) &&
413 !video_is_cyber_mode &&
414 (dispinfo.PropertyFlags & DIPF_IS_FOREIGN) == 0);
416 /* manual overrides */
417 if (M_CheckParm ("-rtg"))
418 video_is_native = FALSE;
419 else if (M_CheckParm ("-native"))
420 video_is_native = TRUE;
422 printf ("Screen Mode $%08x is ", mode);
423 printf (" 8-BIT");
424 if (video_is_native)
425 printf (" Native-Planar");
426 if (video_is_cyber_mode)
427 printf (" CyberGraphX");
428 printf ("\n");
430 video_depth = 8;
432 rect.MinX = 0;
433 rect.MinY = 0;
434 rect.MaxX = SCREENWIDTH - 1;
435 rect.MaxY = SCREENHEIGHT - 1;
438 if (video_is_cyber_mode && M_CheckParm ("-directcgx"))
439 video_is_directcgx = TRUE;
441 if ((video_screen = OpenScreenTags (NULL,
442 SA_Type, CUSTOMSCREEN,
443 SA_DisplayID, mode,
444 SA_DClip, (ULONG)&rect,
445 SA_Width, SCREENWIDTH,
446 SA_Height, SCREENHEIGHT,
447 SA_Depth, video_depth,
448 SA_Font, &topaz8,
449 /* SA_Draggable,FALSE, */
450 /* SA_AutoScroll,FALSE, */
451 /* SA_Exclusive,TRUE, */
452 SA_Quiet, TRUE,
453 TAG_DONE, 0)) == NULL) {
454 I_Error ("OpenScreen() failed");
457 if (video_is_native) {
458 SBuffer[0] = AllocScreenBuffer (video_screen, NULL, SB_SCREEN_BITMAP);
459 SBuffer[1] = AllocScreenBuffer (video_screen, NULL, NULL);
460 SBuffer[2] = AllocScreenBuffer (video_screen, NULL, NULL);
461 NextSBuffer = SBuffer[1];
464 if (video_is_directcgx) {
465 video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
466 LBMI_WIDTH, &width,
467 LBMI_DEPTH, &depth,
468 LBMI_PIXFMT, &pixfmt,
469 TAG_DONE);
470 UnLockBitMap (video_bitmap_handle);
471 if (/* width != SCREENWIDTH || */
472 depth != video_depth ||
473 pixfmt != PIXFMT_LUT8) {
474 I_Error ("ScreenMode of width %d, depth %d, pixfmt %d cannot be used with -directcgx",
475 width, depth, pixfmt);
479 #ifdef GRAFFITI
481 #endif
483 idcmp = IDCMP_RAWKEY;
484 wflags = WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_RMBTRAP | WFLG_NOCAREREFRESH |
485 WFLG_SIMPLE_REFRESH;
486 if (M_CheckParm("-mouse") != NULL) {
487 idcmp |= IDCMP_MOUSEMOVE | IDCMP_DELTAMOVE | IDCMP_MOUSEBUTTONS;
488 wflags |= WFLG_REPORTMOUSE;
491 if ((video_window = OpenWindowTags (NULL,
492 WA_Left, 0,
493 WA_Top, 0,
494 WA_Width, SCREENWIDTH,
495 WA_Height, SCREENHEIGHT,
496 WA_IDCMP, idcmp,
497 WA_Flags, wflags,
498 WA_CustomScreen, video_screen,
499 TAG_DONE)) == NULL) {
500 I_Error ("OpenWindow() failed");
503 InitBitMap (&video_tmp_bm, video_depth, SCREENWIDTH, 1);
504 for (depth = 0; depth < video_depth; depth++)
505 if ((video_tmp_bm.Planes[depth] = (PLANEPTR)AllocRaster (SCREENWIDTH, 1)) == NULL)
506 I_Error ("AllocRaster() failed");
507 video_temprp = *video_window->RPort;
508 video_temprp.Layer = NULL;
509 video_temprp.BitMap = &video_tmp_bm;
511 if ((emptypointer = AllocVec (16, MEMF_CHIP+MEMF_CLEAR)) == NULL)
512 I_Error ("Couldn't allocate chip memory for pointer");
514 if (!M_CheckParm ("-mousepointer"))
515 SetPointer (video_window, emptypointer, 1, 16, 0, 0);
517 I_RecalcPalettes ();
519 /* keyboard & joystick initialisation */
521 video_is_rawkey = M_CheckParm ("-rawkey");
523 if (M_CheckParm ("-sega3") != NULL)
524 sega3_selected = TRUE;
526 if (M_CheckParm ("-sega6") != NULL)
527 sega6_selected = TRUE;
529 if (M_CheckParm ("-joypad") != NULL) {
531 if ((LowLevelBase = OpenLibrary ("lowlevel.library", 0)) == NULL)
532 I_Error ("-joypad option specified and can't open lowlevel.library");
534 } else {
536 if ((gameport_mp = CreatePort (NULL, 0)) == NULL ||
537 (gameport_io = (struct IOStdReq *)CreateExtIO (gameport_mp,
538 sizeof(struct IOStdReq))) == NULL ||
539 OpenDevice ("gameport.device", 1, (struct IORequest *)gameport_io, 0) != 0)
540 I_Error ("Can't open gameport.device");
542 gameport_is_open = TRUE;
544 Forbid ();
546 gameport_io->io_Command = GPD_ASKCTYPE;
547 gameport_io->io_Length = 1;
548 gameport_io->io_Data = &gameport_ct;
549 DoIO ((struct IORequest *)gameport_io);
551 if (gameport_ct != GPCT_NOCONTROLLER) {
553 Permit ();
554 fprintf (stderr, "Another task is using the gameport! Joystick disabled");
555 CloseDevice ((struct IORequest *)gameport_io);
556 gameport_is_open = FALSE;
558 } else {
560 gameport_ct = GPCT_ABSJOYSTICK;
561 gameport_io->io_Command = GPD_SETCTYPE;
562 gameport_io->io_Length = 1;
563 gameport_io->io_Data = &gameport_ct;
564 DoIO ((struct IORequest *)gameport_io);
566 Permit ();
568 gameport_io->io_Command = GPD_SETTRIGGER;
569 gameport_io->io_Length = sizeof(struct GamePortTrigger);
570 gameport_io->io_Data = &gameport_gpt;
571 DoIO ((struct IORequest *)gameport_io);
573 gameport_io->io_Command = GPD_READEVENT;
574 gameport_io->io_Length = sizeof (struct InputEvent);
575 gameport_io->io_Data = &gameport_ie;
576 SendIO ((struct IORequest *)gameport_io);
577 gameport_io_in_progress = TRUE;
582 /**********************************************************************/
583 void I_ShutdownGraphics (void)
585 int depth;
587 if (LowLevelBase != NULL) {
588 CloseLibrary (LowLevelBase);
589 LowLevelBase = NULL;
591 if (gameport_io_in_progress) {
592 AbortIO ((struct IORequest *)gameport_io);
593 WaitIO ((struct IORequest *)gameport_io);
594 gameport_io_in_progress = FALSE;
595 gameport_ct = GPCT_NOCONTROLLER;
596 gameport_io->io_Command = GPD_SETCTYPE;
597 gameport_io->io_Length = 1;
598 gameport_io->io_Data = &gameport_ct;
599 DoIO ((struct IORequest *)gameport_io);
601 if (gameport_is_open) {
602 CloseDevice ((struct IORequest *)gameport_io);
603 gameport_is_open = FALSE;
605 if (gameport_io != NULL) {
606 DeleteExtIO ((struct IORequest *)gameport_io);
607 gameport_io = NULL;
609 if (gameport_mp != NULL) {
610 DeletePort (gameport_mp);
611 gameport_mp = NULL;
613 if (video_is_native) {
614 if (SBuffer[0] != NULL)
615 FreeScreenBuffer (video_screen, SBuffer[0]);
616 if (SBuffer[1] != NULL)
617 FreeScreenBuffer (video_screen, SBuffer[1]);
618 if (SBuffer[2] != NULL)
619 FreeScreenBuffer (video_screen, SBuffer[2]);
620 SBuffer[0] = NULL;
621 SBuffer[1] = NULL;
622 SBuffer[2] = NULL;
624 if (video_window != NULL) {
625 ClearPointer (video_window);
626 CloseWindow (video_window);
627 video_window = NULL;
629 if (emptypointer != NULL) {
630 FreeVec (emptypointer);
631 emptypointer = NULL;
633 #ifdef GRAFFITI
634 if (video_grf_screen != NULL) {
635 CloseChunkyScreen (video_grf_screen);
636 video_grf_screen = NULL;
637 video_screen = NULL;
639 if (GraffitiBase != NULL) {
640 CloseLibrary (GraffitiBase);
641 GraffitiBase = NULL;
643 #endif
644 if (video_screen != NULL) {
645 CloseScreen (video_screen);
646 video_screen = NULL;
648 for (depth = 0; depth < video_depth; depth++) {
649 if (video_tmp_bm.Planes[depth] != NULL) {
650 FreeRaster (video_tmp_bm.Planes[depth], SCREENWIDTH, 1);
651 video_tmp_bm.Planes[depth] = NULL;
654 if (KeymapBase == NULL) {
655 CloseLibrary (KeymapBase);
656 KeymapBase = NULL;
658 if (CyberGfxBase == NULL) {
659 CloseLibrary (CyberGfxBase);
660 CyberGfxBase = NULL;
664 /**********************************************************************/
665 // recalculate colourtable[][] after changing usegamma
666 void I_RecalcPalettes (void)
668 int p, i;
669 byte *palette;
670 static int lu_palette;
672 lu_palette = W_GetNumForName ("PLAYPAL");
673 for (p = 0; p < NUMPALETTES; p++) {
674 palette = (byte *) W_CacheLumpNum (lu_palette, PU_STATIC)+p*768;
675 #ifdef GRAFFITI
676 if (video_graffiti != 0) {
677 for (i = 0; i < 256; i++)
678 video_colourtable[p][i] =
679 (((UBYTE)gammatable[usegamma][palette[3*i+0]]) << 16) +
680 (((UBYTE)gammatable[usegamma][palette[3*i+1]]) << 8) +
681 ((UBYTE)gammatable[usegamma][palette[3*i+2]]);
682 } else {
683 #endif
684 i = 3 * 256 - 1;
685 video_colourtable[p][i + 2] = 0;
686 do {
687 // Better to define c locally here instead of for the whole function:
688 ULONG c = gammatable[usegamma][palette[i]];
689 c += (c << 8);
690 video_colourtable[p][i + 1] = (c << 16) + c;
691 } while (--i >= 0);
692 video_colourtable[p][0] = (256 << 16) + 0;
693 #ifdef GRAFFITI
695 #endif
699 /**********************************************************************/
700 // Takes full 8 bit values.
701 void I_SetPalette (byte *palette, int palette_index)
703 video_palette_changed = 1;
704 video_palette_index = palette_index;
707 /**********************************************************************/
708 // Called by anything that renders to screens[0] (except 3D view)
709 void I_MarkRect (int left, int top, int width, int height)
711 M_AddToBox (dirtybox, left, top);
712 M_AddToBox (dirtybox, left + width - 1, top + height - 1);
715 /**********************************************************************/
716 void I_StartUpdate (void)
720 /**********************************************************************/
721 void I_UpdateNoBlit (void)
725 /**********************************************************************/
726 void I_FinishUpdate (void)
727 /* This needs optimising to copy just the parts that changed,
728 especially if the user has shrunk the playscreen. */
730 int top, left, width, height;
731 int stat, i, j;
732 UBYTE *base_address;
734 total_frames++;
736 #ifdef GRAFFITI
737 if (video_graffiti != 0) {
738 start_timer();
739 CopyChunkyScreen (video_grf_screen, screens[0]);
740 SetChunkyPalette (video_grf_screen,
741 (long *)video_colourtable[video_palette_index]);
742 video_palette_changed = 0;
743 ccs_time += end_timer();
744 return;
746 #endif
748 if (video_is_directcgx) {
749 if (video_palette_changed != 0) {
750 LoadRGB32 (&video_screen->ViewPort,
751 video_colourtable[video_palette_index]);
752 video_palette_changed = 0;
754 start_timer ();
755 video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
756 LBMI_BASEADDRESS, &base_address,
757 TAG_DONE);
758 memcpy (base_address, screens[0], SCREENWIDTH * SCREENHEIGHT);
759 UnLockBitMap (video_bitmap_handle);
760 lock_time += end_timer ();
761 if (video_doing_fps)
762 video_do_fps (video_window->RPort, 0);
763 return;
766 /* update only the viewwindow and dirtybox when gamestate == GS_LEVEL */
767 if (gamestate == GS_LEVEL) {
768 if (dirtybox[BOXLEFT] < viewwindowx)
769 left = dirtybox[BOXLEFT];
770 else
771 left = viewwindowx;
772 if (dirtybox[BOXRIGHT] + 1 > viewwindowx + scaledviewwidth)
773 width = dirtybox[BOXRIGHT] + 1 - left;
774 else
775 width = viewwindowx + scaledviewwidth - left;
776 if (dirtybox[BOXBOTTOM] < viewwindowy) /* BOXBOTTOM is really the top! */
777 top = dirtybox[BOXBOTTOM];
778 else
779 top = viewwindowy;
780 if (dirtybox[BOXTOP] + 1 > viewwindowy + viewheight)
781 height = dirtybox[BOXTOP] + 1 - top;
782 else
783 height = viewwindowy + viewheight - top;
784 M_ClearBox (dirtybox);
785 #ifdef RANGECHECK
786 if (left < 0 || left + width > SCREENWIDTH ||
787 top < 0 || top + height > SCREENHEIGHT)
788 I_Error ("I_FinishUpdate: Box out of range: %d %d %d %d",
789 left, top, width, height);
790 #endif
791 } else {
792 left = 0;
793 top = 0;
794 width = SCREENWIDTH;
795 height = SCREENHEIGHT;
798 /* not directcgx or graffiti */
799 if (video_palette_changed != 0) {
800 LoadRGB32 (&video_screen->ViewPort,
801 video_colourtable[video_palette_index]);
802 video_palette_changed = 0;
804 if (video_is_native) {
805 start_timer();
806 for (i=0, j=(int)screens[0]; i<SCREENHEIGHT; i++, j+=SCREENWIDTH)
807 ppc_c2p_line (i, j, NextSBuffer->sb_BitMap, (SCREENWIDTH+31)>>5);
808 stat = ChangeScreenBuffer(video_screen, NextSBuffer);
809 if (NextSBuffer == SBuffer[0])
810 NextSBuffer = SBuffer[1];
811 else if (NextSBuffer == SBuffer[1])
812 NextSBuffer = SBuffer[2];
813 else
814 NextSBuffer = SBuffer[0];
815 c2p_time += end_timer();
816 } else {
817 start_timer();
818 WritePixelArray8 (video_window->RPort, 0, top, SCREENWIDTH-1,
819 top+height-1, &screens[0][SCREENWIDTH * top],
820 &video_temprp);
821 wpa8_time += end_timer();
823 if (video_doing_fps)
824 video_do_fps (video_window->RPort, 0);
827 /**********************************************************************/
828 // Wait for vertical retrace or pause a bit. Use when quit game.
829 void I_WaitVBL(int count)
831 for ( ; count > 0; count--)
832 WaitTOF();
835 /**********************************************************************/
836 void I_ReadScreen (byte* scr)
838 memcpy (scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
841 /**********************************************************************/
842 void I_BeginRead (void)
846 /**********************************************************************/
847 void I_EndRead (void)
851 /**********************************************************************/
853 int xlate_key (UWORD rawkey, UWORD qualifier, APTR *eventptr)
855 char buffer[4], c;
856 struct InputEvent ie;
857 static int xlate[0x68] = {
858 '`', '1', '2', '3', '4', '5', '6', '7',
859 '8', '9', '0', KEY_MINUS, KEY_EQUALS, '\\', 0, '0',
860 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
861 'o', 'p', KEY_F11, KEY_F12, 0, '0', '2', '3',
862 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
863 'l', ';', '\'', KEY_ENTER, 0, '4', '5', '6',
864 KEY_RSHIFT, 'z', 'x', 'c', 'v', 'b', 'n', 'm',
865 ',', '.', '/', 0, '.', '7', '8', '9',
866 ' ', KEY_BACKSPACE, KEY_TAB, KEY_ENTER, KEY_ENTER, KEY_ESCAPE, KEY_F11,
867 0, 0, 0, KEY_MINUS, 0, KEY_UPARROW, KEY_DOWNARROW, KEY_RIGHTARROW, KEY_LEFTARROW,
868 KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
869 KEY_F9, KEY_F10, '(', ')', '/', '*', KEY_EQUALS, KEY_PAUSE,
870 KEY_RSHIFT, KEY_RSHIFT, 0, KEY_RCTRL, KEY_LALT, KEY_RALT, 0, KEY_RCTRL
873 if (video_is_rawkey)
874 if (rawkey < 0x68)
875 return xlate[rawkey];
876 else
877 return 0;
878 else
879 if (rawkey > 0x00 && rawkey < 0x0a) // '1'..'9', no SHIFT French keyboards
880 return '0' + rawkey;
881 else if (rawkey == 0x0a) // '0'
882 return '0';
883 else if (rawkey < 0x40) {
884 ie.ie_Class = IECLASS_RAWKEY;
885 ie.ie_Code = rawkey;
886 ie.ie_Qualifier = qualifier;
887 ie.ie_EventAddress = *eventptr;
888 if (MapRawKey (&ie, buffer, sizeof(buffer), NULL) > 0) {
889 c = buffer[0];
890 if (c >= '0' && c <= '9') /* numeric pad */
891 switch (c) {
892 case '0':
893 return ' ';
894 case '1':
895 return ',';
896 case '2':
897 return KEY_RCTRL;
898 case '3':
899 return '.';
900 case '4':
901 return KEY_LEFTARROW;
902 case '5':
903 return KEY_DOWNARROW;
904 case '6':
905 return KEY_RIGHTARROW;
906 case '7':
907 return ',';
908 case '8':
909 return KEY_UPARROW;
910 case '9':
911 return '.';
913 else if (c >= 'A' && c <= 'Z')
914 return c - 'A' + 'a';
915 else if (c == '<')
916 return ',';
917 else if (c == '>')
918 return '.';
919 else if (c == '-')
920 return KEY_MINUS;
921 else if (c == '=')
922 return KEY_EQUALS;
923 else if (c == '[')
924 return KEY_F11;
925 else if (c == ']')
926 return KEY_F12;
927 else if (c == '\r')
928 return KEY_ENTER;
929 else if (c == '\n')
930 return KEY_ENTER;
931 else
932 return c;
933 } else
934 return 0;
935 } else if (rawkey < 0x68)
936 return xlate[rawkey];
937 else
938 return 0;
941 /**********************************************************************/
942 void amiga_getevents (void)
944 event_t event;
945 ULONG class;
946 UWORD code;
947 WORD mousex, mousey;
948 struct IntuiMessage *msg;
949 static ULONG previous = 0;
950 static event_t joyevent = {0}, mouseevent = {0};
951 ULONG currSega;
952 int doomkey;
954 if (video_window != NULL) {
955 while ((msg = (struct IntuiMessage *)GetMsg (video_window->UserPort)) != NULL) {
956 class = msg->Class;
957 code = msg->Code;
958 mousex = msg->MouseX;
959 mousey = msg->MouseY;
960 if (class == IDCMP_RAWKEY) {
961 if ((code & 0x80) != 0) {
962 code &= ~0x80;
963 event.type = ev_keyup;
964 } else {
965 event.type = ev_keydown;
967 if (code < 0x68)
968 doomkey = xlate_key (code, msg->Qualifier, msg->IAddress);
970 ReplyMsg ((struct Message *)msg); /* reply after xlating key */
971 if (class == IDCMP_RAWKEY) {
972 if (code < 0x68 && doomkey != 0) {
973 event.data1 = doomkey;
974 D_PostEvent (&event);
975 /* printf ("key %02x -> %02x\n", code, doomkey); */
977 } else if (class == IDCMP_MOUSEMOVE) {
978 mouseevent.type = ev_mouse;
979 mouseevent.data2 = (mousex << 3);
980 mouseevent.data3 = -(mousey << 5);
981 D_PostEvent (&mouseevent);
982 } else if (class == IDCMP_MOUSEBUTTONS) {
983 mouseevent.type = ev_mouse;
984 switch (code) {
985 case SELECTDOWN:
986 mouseevent.data1 |= 1;
987 break;
988 case SELECTUP:
989 mouseevent.data1 &= ~1;
990 break;
991 case MENUDOWN:
992 mouseevent.data1 |= 2;
993 break;
994 case MENUUP:
995 mouseevent.data1 &= ~2;
996 break;
997 case MIDDLEDOWN:
998 mouseevent.data1 |= 4;
999 break;
1000 case MIDDLEUP:
1001 mouseevent.data1 &= ~4;
1002 break;
1003 default:
1004 break;
1006 D_PostEvent (&mouseevent);
1011 if (gameport_is_open && gameport_io_in_progress) {
1012 while (GetMsg (gameport_mp) != NULL) {
1013 switch (gameport_ie.ie_Code) {
1014 case IECODE_LBUTTON:
1015 joyevent.data1 |= 1;
1016 break;
1017 case IECODE_LBUTTON | IECODE_UP_PREFIX:
1018 joyevent.data1 &= ~1;
1019 break;
1020 case IECODE_RBUTTON:
1021 joyevent.data1 |= 2;
1022 break;
1023 case IECODE_RBUTTON | IECODE_UP_PREFIX:
1024 joyevent.data1 &= ~2;
1025 break;
1026 case IECODE_MBUTTON:
1027 joyevent.data1 |= 4;
1028 break;
1029 case IECODE_MBUTTON | IECODE_UP_PREFIX:
1030 joyevent.data1 &= ~4;
1031 break;
1032 case IECODE_NOBUTTON:
1033 joyevent.data2 = gameport_ie.ie_X;
1034 joyevent.data3 = gameport_ie.ie_Y;
1035 break;
1036 default:
1037 break;
1039 joyevent.type = ev_joystick;
1040 D_PostEvent (&joyevent);
1041 gameport_io->io_Command = GPD_READEVENT;
1042 gameport_io->io_Length = sizeof (struct InputEvent);
1043 gameport_io->io_Data = &gameport_ie;
1044 SendIO ((struct IORequest *)gameport_io);
1048 /* CD32 joypad handler code supplied by Gabry (ggreco@iol.it) */
1050 if (LowLevelBase != NULL) {
1051 event_t joyevent;
1052 ULONG joypos = ReadJoyPort (1);
1054 if (previous == joypos)
1055 return;
1057 joyevent.type = ev_joystick;
1058 joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
1060 if (joypos & JPF_BUTTON_RED)
1061 joyevent.data1 |= 1;
1062 else
1063 joyevent.data1 &= ~1;
1065 if (joypos & JP_DIRECTION_MASK) {
1066 if (joypos & JPF_JOY_LEFT) {
1067 joyevent.data2 = -1;
1068 } else if (joypos & JPF_JOY_RIGHT) {
1069 joyevent.data2 = 1;
1071 if (joypos & JPF_JOY_UP) {
1072 joyevent.data3 = -1;
1073 } else if (joypos & JPF_JOY_DOWN) {
1074 joyevent.data3 = 1;
1078 if (joypos & JP_TYPE_GAMECTLR) {
1079 event_t event;
1081 // Play/Pause = ESC (Menu)
1082 if (joypos & JPF_BUTTON_PLAY && !(previous & JPF_BUTTON_PLAY)) {
1083 event.type = ev_keydown;
1084 event.data1 = KEY_ESCAPE;
1085 D_PostEvent (&event);
1086 } else if (previous & JPF_BUTTON_PLAY) {
1087 event.type = ev_keyup;
1088 event.data1 = KEY_ESCAPE;
1089 D_PostEvent (&event);
1092 // YELLOW = SHIFT (button 2) (Run)
1093 if (joypos & JPF_BUTTON_YELLOW)
1094 joyevent.data1 |= 4;
1095 else
1096 joyevent.data1 &= ~4;
1098 // BLUE = SPACE (button 3) (Open/Operate)
1100 if (joypos & JPF_BUTTON_BLUE)
1101 joyevent.data1 |= 8;
1102 else
1103 joyevent.data1 &= ~8;
1105 // GREEN = RETURN (show msg)
1107 if (joypos & JPF_BUTTON_GREEN && !(previous&JPF_BUTTON_GREEN)) {
1108 event.type = ev_keydown;
1109 event.data1 = 13;
1110 D_PostEvent (&event);
1111 } else if (previous & JPF_BUTTON_GREEN) {
1112 event.type = ev_keyup;
1113 event.data1 = 13;
1114 D_PostEvent (&event);
1117 // FORWARD & REVERSE - ALT (Button1) Strafe left/right
1119 if (joypos & JPF_BUTTON_FORWARD) {
1120 joyevent.data1 |= 2;
1121 joyevent.data2 = 1;
1122 } else if (joypos & JPF_BUTTON_REVERSE) {
1123 joyevent.data1 |=2;
1124 joyevent.data2=-1;
1125 } else
1126 joyevent.data1 &= ~2;
1129 D_PostEvent (&joyevent);
1131 previous = joypos;
1134 /* SEGA joypad handler code by Joe Fenton, loosely based on CD32 handling */
1136 if (sega3_selected || sega6_selected) {
1137 event_t joyevent, event;
1139 if (sega3_selected) {
1140 currSega = Sega3 ();
1141 } else {
1142 currSega = Sega6 ();
1145 if (prevSega == currSega)
1146 return;
1148 joyevent.type = ev_joystick;
1149 joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
1151 // B = fire
1152 if (currSega & 0x10)
1153 joyevent.data1 |= 1;
1154 else
1155 joyevent.data1 &= ~1;
1157 // directionals
1158 if (currSega & 0xF) {
1159 if (currSega & 4) {
1160 joyevent.data2 = -1;
1161 } else if (currSega & 8) {
1162 joyevent.data2 = 1;
1164 if (currSega & 1) {
1165 joyevent.data3 = -1;
1166 } else if (currSega & 2) {
1167 joyevent.data3 = 1;
1171 // Mode = ESC (Menu)
1172 if (currSega & 0x80000 && !(prevSega & 0x80000)) {
1173 event.type = ev_keydown;
1174 event.data1 = KEY_ESCAPE;
1175 D_PostEvent (&event);
1176 } else if (prevSega & 0x80000) {
1177 event.type = ev_keyup;
1178 event.data1 = KEY_ESCAPE;
1179 D_PostEvent (&event);
1182 // Y = SHIFT (Run)
1183 if (currSega & 0x20000)
1184 joyevent.data1 |= 4;
1185 else
1186 joyevent.data1 &= ~4;
1188 // Start = SPACE (Open/Operate)
1189 if (currSega & 0x2000)
1190 joyevent.data1 |= 8;
1191 else
1192 joyevent.data1 &= ~8;
1194 // A & C - ALT (Button1) Strafe left/right
1195 if (currSega & 0x20) {
1196 joyevent.data1 |= 2;
1197 joyevent.data2 = 1;
1198 } else if (currSega & 0x1000) {
1199 joyevent.data1 |=2;
1200 joyevent.data2=-1;
1201 } else
1202 joyevent.data1 &= ~2;
1204 // X = RETURN (show msg)
1205 if (currSega & 0x40000 && !(prevSega&0x40000)) {
1206 event.type = ev_keydown;
1207 event.data1 = 13;
1208 D_PostEvent (&event);
1209 } else if (prevSega & 0x40000) {
1210 event.type = ev_keyup;
1211 event.data1 = 13;
1212 D_PostEvent (&event);
1215 // Z = TAB (show map)
1216 if (currSega & 0x10000 && !(prevSega&0x10000)) {
1217 event.type = ev_keydown;
1218 event.data1 = 9;
1219 D_PostEvent (&event);
1220 } else if (prevSega & 0x10000) {
1221 event.type = ev_keyup;
1222 event.data1 = 9;
1223 D_PostEvent (&event);
1226 D_PostEvent (&joyevent);
1228 prevSega = currSega;
1233 /**********************************************************************/
1234 static void calc_time (ULONG time, char *msg)
1236 printf ("Total %s = %u us (%u us/frame)\n", msg, time, time / total_frames);
1239 /**********************************************************************/
1240 void _STDvideo_cleanup (void)
1242 I_ShutdownGraphics ();
1243 if (video_smr != NULL) {
1244 FreeAslRequest (video_smr);
1245 video_smr = NULL;
1247 if (total_frames > 0) {
1248 printf ("Total number of frames = %u\n", total_frames);
1249 calc_time (wpa8_time, "WritePixelArray8 time ");
1250 calc_time (lock_time, "LockBitMap time ");
1251 calc_time (c2p_time, "Chunky2Planar time ");
1252 #ifdef PROFILE
1254 int i;
1256 for (i=0; i<32; i++)
1257 calc_time (profile[n][2], "Profile Time ");
1259 #endif
1263 /**********************************************************************/