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>
29 #include "graffiti_lib.h"
30 #include "graffiti_protos.h"
43 #include "amiga_sega.h"
48 /**********************************************************************/
49 extern void ppctimer (unsigned int *time
);
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
;
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
;
101 static BOOL video_is_rawkey
;
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 */
118 static ULONG prevSega
;
119 static BOOL sega3_selected
= FALSE
;
120 static BOOL sega6_selected
= FALSE
;
123 struct Library
*GraffitiBase
= NULL
;
124 int video_graffiti
= 0;
125 static struct GRF_Screen
*video_grf_screen
= NULL
;
129 unsigned int profile
[32][4];
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];
152 if (end_time
[1] >= start_time
[1])
153 return (((end_time
[1] - start_time
[1]) << 2) / bus_MHz
);
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 */
167 struct NameInfo nameinfo
;
168 struct DimensionInfo dimsinfo
;
169 static char modename
[DISPLAYNAMELEN
+ 4 + 4 + 11 + 1];
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??? */
185 case NTSC_MONITOR_ID
:
186 p
+= sprintf (p
, "NTSC:");
189 p
+= sprintf (p
, "PAL:");
192 p
+= sprintf (p
, "MULTISCAN:");
194 case A2024_MONITOR_ID
:
195 p
+= sprintf (p
, "A2024:");
197 case PROTO_MONITOR_ID
:
198 p
+= sprintf (p
, "PROTO:");
200 case EURO72_MONITOR_ID
:
201 p
+= sprintf (p
, "EURO72:");
203 case EURO36_MONITOR_ID
:
204 p
+= sprintf (p
, "EURO36:");
206 case SUPER72_MONITOR_ID
:
207 p
+= sprintf (p
, "SUPER72:");
209 case DBLNTSC_MONITOR_ID
:
210 p
+= sprintf (p
, "DBLNTSC:");
212 case DBLPAL_MONITOR_ID
:
213 p
+= sprintf (p
, "DBLPAL:");
216 p
+= sprintf (p
, "(unknown):");
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");
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");
238 p
+= sprintf (p
, "%s", "(unavailable)");
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"). */
252 if (modename
!= NULL
) {
253 if (modename
[0] == '0' && modename
[1] == 'x') {
254 if (sscanf (&modename
[2], "%lx", &mode
) != 1)
256 } else if (modename
[0] == '$') {
257 if (sscanf (&modename
[1], "%lx", &mode
) != 1)
259 } else if (modename
[0] >= '0' && modename
[0] <= '9') {
260 if (sscanf (modename
, "%ld", &mode
) != 1)
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)
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
);
279 /**********************************************************************/
280 static void video_do_fps (struct RastPort
*rp
, int yoffset
)
283 static unsigned int start_time
[2] = {0, 0};
284 unsigned int end_time
[2];
288 if (end_time
[1] >= start_time
[1])
289 x
= (((end_time
[1] - start_time
[1]) << 2) / bus_MHz
);
291 x
= (((end_time
[1] - start_time
[1]) << 2) / bus_MHz
+ 1000000);
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';
298 Move (rp
, SCREENWIDTH
- 24, yoffset
+ 6);
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
;
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");
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
;
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 */
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 */
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
,
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
,
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
,
379 ASLSM_PropertyMask
, propertymask
,
380 ASLSM_PropertyFlags
, 0,
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",
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",
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
);
425 printf (" Native-Planar");
426 if (video_is_cyber_mode
)
427 printf (" CyberGraphX");
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
,
444 SA_DClip
, (ULONG
)&rect
,
445 SA_Width
, SCREENWIDTH
,
446 SA_Height
, SCREENHEIGHT
,
447 SA_Depth
, video_depth
,
449 /* SA_Draggable,FALSE, */
450 /* SA_AutoScroll,FALSE, */
451 /* SA_Exclusive,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
,
468 LBMI_PIXFMT
, &pixfmt
,
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
);
483 idcmp
= IDCMP_RAWKEY
;
484 wflags
= WFLG_ACTIVATE
| WFLG_BORDERLESS
| WFLG_RMBTRAP
| WFLG_NOCAREREFRESH
|
486 if (M_CheckParm("-mouse") != NULL
) {
487 idcmp
|= IDCMP_MOUSEMOVE
| IDCMP_DELTAMOVE
| IDCMP_MOUSEBUTTONS
;
488 wflags
|= WFLG_REPORTMOUSE
;
491 if ((video_window
= OpenWindowTags (NULL
,
494 WA_Width
, SCREENWIDTH
,
495 WA_Height
, SCREENHEIGHT
,
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);
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");
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
;
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
) {
554 fprintf (stderr
, "Another task is using the gameport! Joystick disabled");
555 CloseDevice ((struct IORequest
*)gameport_io
);
556 gameport_is_open
= FALSE
;
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
);
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)
587 if (LowLevelBase
!= NULL
) {
588 CloseLibrary (LowLevelBase
);
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
);
609 if (gameport_mp
!= NULL
) {
610 DeletePort (gameport_mp
);
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]);
624 if (video_window
!= NULL
) {
625 ClearPointer (video_window
);
626 CloseWindow (video_window
);
629 if (emptypointer
!= NULL
) {
630 FreeVec (emptypointer
);
634 if (video_grf_screen
!= NULL
) {
635 CloseChunkyScreen (video_grf_screen
);
636 video_grf_screen
= NULL
;
639 if (GraffitiBase
!= NULL
) {
640 CloseLibrary (GraffitiBase
);
644 if (video_screen
!= NULL
) {
645 CloseScreen (video_screen
);
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
);
658 if (CyberGfxBase
== NULL
) {
659 CloseLibrary (CyberGfxBase
);
664 /**********************************************************************/
665 // recalculate colourtable[][] after changing usegamma
666 void I_RecalcPalettes (void)
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;
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]]);
685 video_colourtable
[p
][i
+ 2] = 0;
687 // Better to define c locally here instead of for the whole function:
688 ULONG c
= gammatable
[usegamma
][palette
[i
]];
690 video_colourtable
[p
][i
+ 1] = (c
<< 16) + c
;
692 video_colourtable
[p
][0] = (256 << 16) + 0;
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
;
737 if (video_graffiti
!= 0) {
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();
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;
755 video_bitmap_handle
= LockBitMapTags (video_screen
->ViewPort
.RasInfo
->BitMap
,
756 LBMI_BASEADDRESS
, &base_address
,
758 memcpy (base_address
, screens
[0], SCREENWIDTH
* SCREENHEIGHT
);
759 UnLockBitMap (video_bitmap_handle
);
760 lock_time
+= end_timer ();
762 video_do_fps (video_window
->RPort
, 0);
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
];
772 if (dirtybox
[BOXRIGHT
] + 1 > viewwindowx
+ scaledviewwidth
)
773 width
= dirtybox
[BOXRIGHT
] + 1 - left
;
775 width
= viewwindowx
+ scaledviewwidth
- left
;
776 if (dirtybox
[BOXBOTTOM
] < viewwindowy
) /* BOXBOTTOM is really the top! */
777 top
= dirtybox
[BOXBOTTOM
];
780 if (dirtybox
[BOXTOP
] + 1 > viewwindowy
+ viewheight
)
781 height
= dirtybox
[BOXTOP
] + 1 - top
;
783 height
= viewwindowy
+ viewheight
- top
;
784 M_ClearBox (dirtybox
);
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
);
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
) {
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];
814 NextSBuffer
= SBuffer
[0];
815 c2p_time
+= end_timer();
818 WritePixelArray8 (video_window
->RPort
, 0, top
, SCREENWIDTH
-1,
819 top
+height
-1, &screens
[0][SCREENWIDTH
* top
],
821 wpa8_time
+= end_timer();
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
--)
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
)
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
875 return xlate
[rawkey
];
879 if (rawkey
> 0x00 && rawkey
< 0x0a) // '1'..'9', no SHIFT French keyboards
881 else if (rawkey
== 0x0a) // '0'
883 else if (rawkey
< 0x40) {
884 ie
.ie_Class
= IECLASS_RAWKEY
;
886 ie
.ie_Qualifier
= qualifier
;
887 ie
.ie_EventAddress
= *eventptr
;
888 if (MapRawKey (&ie
, buffer
, sizeof(buffer
), NULL
) > 0) {
890 if (c
>= '0' && c
<= '9') /* numeric pad */
901 return KEY_LEFTARROW
;
903 return KEY_DOWNARROW
;
905 return KEY_RIGHTARROW
;
913 else if (c
>= 'A' && c
<= 'Z')
914 return c
- 'A' + 'a';
935 } else if (rawkey
< 0x68)
936 return xlate
[rawkey
];
941 /**********************************************************************/
942 void amiga_getevents (void)
948 struct IntuiMessage
*msg
;
949 static ULONG previous
= 0;
950 static event_t joyevent
= {0}, mouseevent
= {0};
954 if (video_window
!= NULL
) {
955 while ((msg
= (struct IntuiMessage
*)GetMsg (video_window
->UserPort
)) != NULL
) {
958 mousex
= msg
->MouseX
;
959 mousey
= msg
->MouseY
;
960 if (class == IDCMP_RAWKEY
) {
961 if ((code
& 0x80) != 0) {
963 event
.type
= ev_keyup
;
965 event
.type
= ev_keydown
;
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
;
986 mouseevent
.data1
|= 1;
989 mouseevent
.data1
&= ~1;
992 mouseevent
.data1
|= 2;
995 mouseevent
.data1
&= ~2;
998 mouseevent
.data1
|= 4;
1001 mouseevent
.data1
&= ~4;
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;
1017 case IECODE_LBUTTON
| IECODE_UP_PREFIX
:
1018 joyevent
.data1
&= ~1;
1020 case IECODE_RBUTTON
:
1021 joyevent
.data1
|= 2;
1023 case IECODE_RBUTTON
| IECODE_UP_PREFIX
:
1024 joyevent
.data1
&= ~2;
1026 case IECODE_MBUTTON
:
1027 joyevent
.data1
|= 4;
1029 case IECODE_MBUTTON
| IECODE_UP_PREFIX
:
1030 joyevent
.data1
&= ~4;
1032 case IECODE_NOBUTTON
:
1033 joyevent
.data2
= gameport_ie
.ie_X
;
1034 joyevent
.data3
= gameport_ie
.ie_Y
;
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
) {
1052 ULONG joypos
= ReadJoyPort (1);
1054 if (previous
== joypos
)
1057 joyevent
.type
= ev_joystick
;
1058 joyevent
.data1
= joyevent
.data2
= joyevent
.data3
= 0;
1060 if (joypos
& JPF_BUTTON_RED
)
1061 joyevent
.data1
|= 1;
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
) {
1071 if (joypos
& JPF_JOY_UP
) {
1072 joyevent
.data3
= -1;
1073 } else if (joypos
& JPF_JOY_DOWN
) {
1078 if (joypos
& JP_TYPE_GAMECTLR
) {
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;
1096 joyevent
.data1
&= ~4;
1098 // BLUE = SPACE (button 3) (Open/Operate)
1100 if (joypos
& JPF_BUTTON_BLUE
)
1101 joyevent
.data1
|= 8;
1103 joyevent
.data1
&= ~8;
1105 // GREEN = RETURN (show msg)
1107 if (joypos
& JPF_BUTTON_GREEN
&& !(previous
&JPF_BUTTON_GREEN
)) {
1108 event
.type
= ev_keydown
;
1110 D_PostEvent (&event
);
1111 } else if (previous
& JPF_BUTTON_GREEN
) {
1112 event
.type
= ev_keyup
;
1114 D_PostEvent (&event
);
1117 // FORWARD & REVERSE - ALT (Button1) Strafe left/right
1119 if (joypos
& JPF_BUTTON_FORWARD
) {
1120 joyevent
.data1
|= 2;
1122 } else if (joypos
& JPF_BUTTON_REVERSE
) {
1126 joyevent
.data1
&= ~2;
1129 D_PostEvent (&joyevent
);
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 ();
1142 currSega
= Sega6 ();
1145 if (prevSega
== currSega
)
1148 joyevent
.type
= ev_joystick
;
1149 joyevent
.data1
= joyevent
.data2
= joyevent
.data3
= 0;
1152 if (currSega
& 0x10)
1153 joyevent
.data1
|= 1;
1155 joyevent
.data1
&= ~1;
1158 if (currSega
& 0xF) {
1160 joyevent
.data2
= -1;
1161 } else if (currSega
& 8) {
1165 joyevent
.data3
= -1;
1166 } else if (currSega
& 2) {
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
);
1183 if (currSega
& 0x20000)
1184 joyevent
.data1
|= 4;
1186 joyevent
.data1
&= ~4;
1188 // Start = SPACE (Open/Operate)
1189 if (currSega
& 0x2000)
1190 joyevent
.data1
|= 8;
1192 joyevent
.data1
&= ~8;
1194 // A & C - ALT (Button1) Strafe left/right
1195 if (currSega
& 0x20) {
1196 joyevent
.data1
|= 2;
1198 } else if (currSega
& 0x1000) {
1202 joyevent
.data1
&= ~2;
1204 // X = RETURN (show msg)
1205 if (currSega
& 0x40000 && !(prevSega
&0x40000)) {
1206 event
.type
= ev_keydown
;
1208 D_PostEvent (&event
);
1209 } else if (prevSega
& 0x40000) {
1210 event
.type
= ev_keyup
;
1212 D_PostEvent (&event
);
1215 // Z = TAB (show map)
1216 if (currSega
& 0x10000 && !(prevSega
&0x10000)) {
1217 event
.type
= ev_keydown
;
1219 D_PostEvent (&event
);
1220 } else if (prevSega
& 0x10000) {
1221 event
.type
= ev_keyup
;
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
);
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 ");
1256 for (i
=0; i
<32; i
++)
1257 calc_time (profile
[n
][2], "Profile Time ");
1263 /**********************************************************************/