fix remapping behavior. Remapping is only necessary if we are rendering on the workbe...
[AROS-Contrib.git] / Games / Doom / aros_video.c
blob1b455b31eff12c06844cba0d19f2afe1c857de91
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 <cybergraphx/cybergraphics.h>
13 #include <devices/gameport.h>
14 #include <devices/keymap.h>
16 #include <proto/exec.h>
17 #include <proto/dos.h>
18 #include <proto/graphics.h>
19 #include <proto/layers.h>
20 #include <proto/intuition.h>
21 #include <proto/asl.h>
22 #include <proto/keymap.h>
23 #include <proto/cybergraphics.h>
24 #include <proto/timer.h>
25 #include <clib/alib_protos.h>
27 #include <aros/debug.h>
29 #include "doomtype.h"
30 #include "doomdef.h"
31 #include "doomstat.h"
32 #include "i_system.h"
33 #include "i_video.h"
34 #include "v_video.h"
35 #include "m_argv.h"
36 #include "m_bbox.h"
37 #include "d_main.h"
39 #include "amiga_sega.h"
40 #include "r_draw.h"
41 #include "w_wad.h"
42 #include "z_zone.h"
44 /**********************************************************************/
46 extern struct ExecBase *SysBase;
47 extern struct Device *TimerBase;
48 struct Library *AslBase = NULL;
49 struct Library *CyberGfxBase = NULL;
50 struct Library *LowLevelBase = NULL;
51 struct Library *KeymapBase = NULL;
53 extern int cpu_type;
55 int SCREENWIDTH;
56 int SCREENHEIGHT;
57 int weirdaspect;
60 #define NUMPALETTES 14
62 static struct ScreenModeRequester *video_smr = NULL;
63 static struct Screen *video_screen = NULL;
64 static struct Window *video_window = NULL;
66 static int video_depth = 8;
68 static FAR ULONG video_colourtable[NUMPALETTES][1 + 3*256 + 1];
69 static FAR ULONG cgfx_coltab[NUMPALETTES][256];
70 static int video_palette_index = 0;
71 static volatile WORD video_palette_changed = 0;
73 static BOOL video_is_cyber_mode = FALSE;
74 static BOOL video_is_directcgx = FALSE;
75 static BOOL video_is_native = FALSE;
76 static BOOL video_do_screen = FALSE;
77 static BOOL video_doing_fps = FALSE;
78 static APTR video_bitmap_handle;
80 static struct RastPort video_temprp;
81 static struct BitMap video_tmp_bm = {
82 0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
85 static UWORD *emptypointer;
87 /* keyboard */
88 static BOOL video_is_rawkey;
90 /* gameport stuff */
91 static struct MsgPort *gameport_mp = NULL;
92 static struct IOStdReq *gameport_io = NULL;
93 static BOOL gameport_is_open = FALSE;
94 static BOOL gameport_io_in_progress = FALSE;
95 #ifndef AROS
96 static struct InputEvent gameport_ie;
97 #endif
98 static BYTE gameport_ct; /* controller type */
99 struct GamePortTrigger gameport_gpt = {
100 GPTF_UPKEYS | GPTF_DOWNKEYS, /* gpt_Keys */
101 0, /* gpt_Timeout */
102 1, /* gpt_XDelta */
103 1 /* gpt_YDelta */
106 /* SEGA variables */
107 #ifndef AROS
108 static ULONG prevSega;
109 static BOOL sega3_selected = FALSE;
110 static BOOL sega6_selected = FALSE;
111 #endif
113 #ifdef PROFILE
114 unsigned int profile[32][4];
115 #endif
117 /****************************************************************************/
119 static unsigned int start_time[2];
120 static unsigned int wpa8_time = 0;
121 static unsigned int lock_time = 0;
122 static unsigned int c2p_time = 0;
123 static unsigned int total_frames = 0;
125 /****************************************************************************/
127 static __inline void start_timer (void)
129 struct timeval tv;
131 GetSysTime(&tv);
133 start_time[0] = tv.tv_secs;
134 start_time[1] = tv.tv_micro;
138 /****************************************************************************/
140 static __inline unsigned int end_timer (void)
142 unsigned int end_time[2], result;
143 struct timeval tv;
145 GetSysTime(&tv);
147 end_time[0] = tv.tv_secs;
148 end_time[1] = tv.tv_micro;
150 result = (end_time[0] - start_time[0]) * 1000000 +
151 ( ((int)end_time[1]) - ((int)start_time[1]) );
153 return result;
157 /**********************************************************************/
158 static void video_do_fps (struct RastPort *rp, int yoffset)
160 #define FPS_STAT_COUNT 50
162 static ULONG oldsecs = 0;
163 static LONG oldmicro = 0;
164 static LONG fps_stat[FPS_STAT_COUNT];
165 static LONG fps_stat_pos;
166 struct timeval tv;
167 ULONG secs;
168 LONG micro;
169 LONG time, fps = 0, i;
170 char msg[4];
172 GetSysTime(&tv);
173 secs = tv.tv_secs;
174 micro = tv.tv_micro;
176 time = (secs - oldsecs) * 1000000 + (micro - oldmicro);
177 if (time > 0) fps = 1000000 / time;
179 fps_stat[fps_stat_pos++] = fps;
180 fps_stat_pos %= FPS_STAT_COUNT;
182 fps = 0;
183 for (i = 0; i < FPS_STAT_COUNT; i++)
185 fps += fps_stat[i];
187 fps /= FPS_STAT_COUNT;
189 msg[0] = (fps % 1000) / 100 + '0';
190 msg[1] = (fps % 100) / 10 + + '0';
191 msg[2] = (fps % 10) + '0';
192 msg[3] = '\0';
194 SetABPenDrMd(rp, 2, 1, JAM2);
196 Move (rp, video_window->BorderLeft + SCREENWIDTH - 24,
197 video_window->BorderTop + yoffset + rp->TxBaseline + 3);
198 Text (rp, msg, 3);
200 oldsecs = secs;
201 oldmicro = micro;
204 /**********************************************************************/
205 // Called by D_DoomMain,
206 // determines the hardware configuration
207 // and sets up the video mode
208 void I_InitGraphics (void)
210 ULONG propertymask, idcmp, wflags, width, pixfmt;
211 struct Rectangle rect;
212 #ifndef AROS
213 char reqtitle[32];
214 int nbytes, p;
215 DisplayInfoHandle handle;
216 struct DisplayInfo dispinfo;
217 struct DimensionInfo dimsinfo;
218 #endif
219 int mode, depth;
220 static struct TextAttr topaz8 = {
221 "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
224 if ((KeymapBase = OpenLibrary ("keymap.library", 0)) == NULL)
225 I_Error ("Can't open keymap.library");
227 video_doing_fps = M_CheckParm ("-fps");
228 video_do_screen = M_CheckParm ("-scr");
230 #ifndef AROS
231 kprintf("_-- Asl Requester\n");
232 if (AslBase == NULL) {
233 if ((AslBase = OpenLibrary ("asl.library", 37L)) == NULL ||
234 (video_smr = AllocAslRequestTags (ASL_ScreenModeRequest, TAG_DONE)) == NULL) {
235 I_Error ("OpenLibrary(""asl.library"", 37) failed");
238 kprintf("--- Asl Requester done\n");
239 #endif
241 CyberGfxBase = OpenLibrary ("cybergraphics.library", 0); /* may be NULL */
242 if (!CyberGfxBase) video_do_screen = TRUE;
244 if (video_do_screen)
246 /* first check tooltypes for SCREENMODE */
247 mode = -1;
249 /* if not found in icon tooltypes, then put up a ScreenMode requester */
250 if (mode == -1) {
251 propertymask = DIPF_IS_EXTRAHALFBRITE | DIPF_IS_DUALPF |
252 DIPF_IS_PF2PRI | DIPF_IS_HAM;
253 #ifndef AROS
254 if (CyberGfxBase != NULL)
255 mode = BestCModeIDTags (CYBRBIDTG_NominalWidth, SCREENWIDTH,
256 CYBRBIDTG_NominalHeight, SCREENHEIGHT,
257 CYBRBIDTG_Depth, 8,
258 TAG_DONE);
259 else if (GfxBase->LibNode.lib_Version >= 39)
260 mode = BestModeID (BIDTAG_NominalWidth, SCREENWIDTH,
261 BIDTAG_NominalHeight, SCREENHEIGHT,
262 BIDTAG_Depth, video_depth,
263 BIDTAG_DIPFMustNotHave, propertymask,
264 TAG_DONE);
265 if (AslBase->lib_Version >= 38) {
266 sprintf (reqtitle, "ADoomPPC %dx%d", SCREENWIDTH, SCREENHEIGHT);
267 if (!AslRequestTags (video_smr,
268 ASLSM_TitleText, (ULONG)reqtitle,
269 ASLSM_InitialDisplayID, mode,
270 ASLSM_MinWidth, SCREENWIDTH,
271 ASLSM_MinHeight, SCREENHEIGHT,
272 ASLSM_MaxWidth, MAXSCREENWIDTH,
273 ASLSM_MaxHeight, MAXSCREENHEIGHT,
274 ASLSM_MinDepth, 8,
275 ASLSM_MaxDepth, 8,
276 ASLSM_PropertyMask, propertymask,
277 ASLSM_PropertyFlags, 0,
278 TAG_DONE)) {
279 I_Error ("AslRequest() failed");
281 mode = video_smr->sm_DisplayID;
283 #endif
286 #ifdef AROS
287 video_is_native = FALSE;
288 #else
289 if ((handle = FindDisplayInfo (mode)) == NULL) {
290 I_Error ("Can't FindDisplayInfo() for mode %08x", mode);
292 if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dispinfo,
293 sizeof(struct DisplayInfo), DTAG_DISP,
294 NULL)) < 40 /*sizeof(struct DisplayInfo)*/) {
295 I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
296 mode, nbytes);
298 if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
299 sizeof(dimsinfo), DTAG_DIMS,
300 NULL)) < 66 /* sizeof(dimsinfo)*/) {
301 I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
302 mode, nbytes);
305 video_is_cyber_mode = 0;
306 if (CyberGfxBase != NULL)
307 video_is_cyber_mode = IsCyberModeID (mode);
309 video_is_native = ((GfxBase->LibNode.lib_Version < 39 ||
310 (dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0 ||
311 (dispinfo.PropertyFlags & DIPF_IS_AA) != 0 ||
312 (dispinfo.PropertyFlags & DIPF_IS_ECS) != 0 ||
313 (dispinfo.PropertyFlags & DIPF_IS_DBUFFER) != 0) &&
314 !video_is_cyber_mode &&
315 (dispinfo.PropertyFlags & DIPF_IS_FOREIGN) == 0);
317 /* manual overrides */
318 if (M_CheckParm ("-rtg"))
319 video_is_native = FALSE;
320 else if (M_CheckParm ("-native"))
321 video_is_native = TRUE;
322 #endif
324 printf ("Screen Mode $%08x is ", mode);
325 printf (" 8-BIT");
326 if (video_is_native)
327 printf (" Native-Planar");
328 if (video_is_cyber_mode)
329 printf (" CyberGraphX");
330 printf ("\n");
332 video_depth = 8;
334 rect.MinX = 0;
335 rect.MinY = 0;
336 rect.MaxX = SCREENWIDTH - 1;
337 rect.MaxY = SCREENHEIGHT - 1;
339 #ifndef AROS
340 if (video_is_cyber_mode && M_CheckParm ("-directcgx"))
341 video_is_directcgx = TRUE;
342 #endif
344 if ((video_screen = OpenScreenTags (NULL,
345 SA_Type, CUSTOMSCREEN,
346 SA_DisplayID, mode,
347 SA_DClip, (ULONG)&rect,
348 SA_Width, SCREENWIDTH,
349 SA_Height, SCREENHEIGHT,
350 SA_Depth, video_depth,
351 SA_Font, &topaz8,
352 /* SA_Draggable,FALSE, */
353 /* SA_AutoScroll,FALSE, */
354 /* SA_Exclusive,TRUE, */
355 SA_Quiet, TRUE,
356 TAG_DONE, 0)) == NULL) {
357 I_Error ("OpenScreen() failed");
360 if (video_is_directcgx) {
361 video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
362 LBMI_WIDTH, &width,
363 LBMI_DEPTH, &depth,
364 LBMI_PIXFMT, &pixfmt,
365 TAG_DONE);
366 UnLockBitMap (video_bitmap_handle);
367 if (/* width != SCREENWIDTH || */
368 depth != video_depth ||
369 pixfmt != PIXFMT_LUT8) {
370 I_Error ("ScreenMode of width %d, depth %d, pixfmt %d cannot be used with -directcgx",
371 width, depth, pixfmt);
375 } /* video_do_screen */
377 idcmp = IDCMP_RAWKEY;
378 wflags = WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_RMBTRAP | WFLG_NOCAREREFRESH |
379 WFLG_SIMPLE_REFRESH;
380 if (M_CheckParm("-mouse") != 0) {
381 idcmp |= IDCMP_MOUSEMOVE | IDCMP_DELTAMOVE | IDCMP_MOUSEBUTTONS;
382 wflags |= WFLG_REPORTMOUSE;
385 if (video_do_screen)
387 if ((video_window = OpenWindowTags (NULL,
388 WA_Left, 0,
389 WA_Top, 0,
390 WA_Width, SCREENWIDTH,
391 WA_Height, SCREENHEIGHT,
392 WA_IDCMP, idcmp,
393 WA_Flags, wflags,
394 WA_CustomScreen, (IPTR)video_screen,
395 TAG_DONE)) == NULL) {
396 I_Error ("OpenWindow() failed");
398 } else {
399 struct Screen *scr = LockPubScreen(NULL);
400 STRPTR wintitle = "AROS Doom";
401 WORD winx = 0, winy = 0;
402 int p;
404 if (scr == NULL) I_Error("Can't lock public screen!");
406 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
408 UnlockPubScreen(NULL, scr);
409 I_Error("Window mode only works on hi or true color screens. Try option \"-scr\" to play Doom on a screen!");
412 wflags &= ~WFLG_BORDERLESS;
413 idcmp |= IDCMP_CLOSEWINDOW;
415 p = M_CheckParm("-winleft");
416 if (p && p < myargc-1) winx = atoi(myargv[p+1]);
418 p = M_CheckParm("-wintop");
419 if (p && p < myargc-1) winy = atoi(myargv[p+1]);
421 p = M_CheckParm("-wintitle");
422 if (p && p < myargc-1) wintitle = myargv[p+1];
424 video_window = OpenWindowTags(NULL,
425 WA_PubScreen, (IPTR)scr,
426 WA_Title, (IPTR)wintitle,
427 WA_Left, winx,
428 WA_Top, winy,
429 WA_InnerWidth, SCREENWIDTH,
430 WA_InnerHeight, SCREENHEIGHT,
431 WA_AutoAdjust, TRUE,
432 WA_IDCMP, idcmp,
433 WA_Flags, wflags,
434 WA_CloseGadget, TRUE,
435 WA_DepthGadget, TRUE,
436 WA_DragBar, TRUE,
437 TAG_DONE);
439 UnlockPubScreen(NULL, scr);
441 if (video_window == NULL) {
442 I_Error ("OpenWindow() failed");
447 InitBitMap (&video_tmp_bm, video_depth, SCREENWIDTH, 1);
448 for (depth = 0; depth < video_depth; depth++)
449 if ((video_tmp_bm.Planes[depth] = (PLANEPTR)AllocRaster (SCREENWIDTH, 1)) == NULL)
450 I_Error ("AllocRaster() failed");
451 video_temprp = *video_window->RPort;
452 video_temprp.Layer = NULL;
453 video_temprp.BitMap = &video_tmp_bm;
455 if ((emptypointer = AllocVec (16, MEMF_CHIP+MEMF_CLEAR)) == NULL)
456 I_Error ("Couldn't allocate chip memory for pointer");
458 if (!M_CheckParm ("-mousepointer"))
459 SetPointer (video_window, emptypointer, 1, 16, 0, 0);
461 I_RecalcPalettes ();
463 /* keyboard & joystick initialisation */
465 video_is_rawkey = M_CheckParm ("-rawkey");
467 #ifndef AROS
468 if (M_CheckParm ("-sega3") != 0)
469 sega3_selected = TRUE;
471 if (M_CheckParm ("-sega6") != 0)
472 sega6_selected = TRUE;
473 #endif
475 if (M_CheckParm ("-joypad") != 0) {
477 if ((LowLevelBase = OpenLibrary ("lowlevel.library", 0)) == NULL)
478 I_Error ("-joypad option specified and can't open lowlevel.library");
480 } else {
482 #ifndef AROS
483 if ((gameport_mp = CreatePort (NULL, 0)) == NULL ||
484 (gameport_io = (struct IOStdReq *)CreateExtIO (gameport_mp,
485 sizeof(struct IOStdReq))) == NULL ||
486 OpenDevice ("gameport.device", 1, (struct IORequest *)gameport_io, 0) != 0)
487 I_Error ("Can't open gameport.device");
489 gameport_is_open = TRUE;
491 Forbid ();
493 gameport_io->io_Command = GPD_ASKCTYPE;
494 gameport_io->io_Length = 1;
495 gameport_io->io_Data = &gameport_ct;
496 DoIO ((struct IORequest *)gameport_io);
498 if (gameport_ct != GPCT_NOCONTROLLER) {
500 Permit ();
501 fprintf (stderr, "Another task is using the gameport! Joystick disabled");
502 CloseDevice ((struct IORequest *)gameport_io);
503 gameport_is_open = FALSE;
505 } else {
507 gameport_ct = GPCT_ABSJOYSTICK;
508 gameport_io->io_Command = GPD_SETCTYPE;
509 gameport_io->io_Length = 1;
510 gameport_io->io_Data = &gameport_ct;
511 DoIO ((struct IORequest *)gameport_io);
513 Permit ();
515 gameport_io->io_Command = GPD_SETTRIGGER;
516 gameport_io->io_Length = sizeof(struct GamePortTrigger);
517 gameport_io->io_Data = &gameport_gpt;
518 DoIO ((struct IORequest *)gameport_io);
520 gameport_io->io_Command = GPD_READEVENT;
521 gameport_io->io_Length = sizeof (struct InputEvent);
522 gameport_io->io_Data = &gameport_ie;
523 SendIO ((struct IORequest *)gameport_io);
524 gameport_io_in_progress = TRUE;
526 #endif
532 /**********************************************************************/
533 void I_ShutdownGraphics (void)
535 int depth;
537 if (LowLevelBase != NULL) {
538 CloseLibrary (LowLevelBase);
539 LowLevelBase = NULL;
541 if (gameport_io_in_progress) {
542 AbortIO ((struct IORequest *)gameport_io);
543 WaitIO ((struct IORequest *)gameport_io);
544 gameport_io_in_progress = FALSE;
545 gameport_ct = GPCT_NOCONTROLLER;
546 gameport_io->io_Command = GPD_SETCTYPE;
547 gameport_io->io_Length = 1;
548 gameport_io->io_Data = &gameport_ct;
549 DoIO ((struct IORequest *)gameport_io);
551 if (gameport_is_open) {
552 CloseDevice ((struct IORequest *)gameport_io);
553 gameport_is_open = FALSE;
555 if (gameport_io != NULL) {
556 DeleteExtIO ((struct IORequest *)gameport_io);
557 gameport_io = NULL;
559 if (gameport_mp != NULL) {
560 DeletePort (gameport_mp);
561 gameport_mp = NULL;
564 if (video_window != NULL) {
565 ClearPointer (video_window);
566 CloseWindow (video_window);
567 video_window = NULL;
569 if (emptypointer != NULL) {
570 FreeVec (emptypointer);
571 emptypointer = NULL;
574 if (video_screen != NULL) {
575 CloseScreen (video_screen);
576 video_screen = NULL;
579 for (depth = 0; depth < video_depth; depth++) {
580 if (video_tmp_bm.Planes[depth] != NULL) {
582 FreeRaster (video_tmp_bm.Planes[depth], SCREENWIDTH, 1);
584 video_tmp_bm.Planes[depth] = NULL;
588 if (KeymapBase == NULL) {
589 CloseLibrary (KeymapBase);
590 KeymapBase = NULL;
593 if (CyberGfxBase == NULL) {
594 CloseLibrary (CyberGfxBase);
595 CyberGfxBase = NULL;
600 /**********************************************************************/
601 // recalculate colourtable[][] after changing usegamma
602 void I_RecalcPalettes (void)
604 int p, i;
605 byte *palette;
606 static int lu_palette;
608 lu_palette = W_GetNumForName ("PLAYPAL");
609 for (p = 0; p < NUMPALETTES; p++) {
610 if (video_do_screen)
612 palette = (byte *) W_CacheLumpNum (lu_palette, PU_STATIC)+p*768;
614 i = 3 * 256 - 1;
615 video_colourtable[p][i + 2] = 0;
616 do {
617 // Better to define c locally here instead of for the whole function:
618 ULONG c = gammatable[usegamma][palette[i]];
619 c += (c << 8);
620 video_colourtable[p][i + 1] = (c << 16) + c;
621 } while (--i >= 0);
622 video_colourtable[p][0] = (256 << 16) + 0;
623 } else {
624 palette = (byte *) W_CacheLumpNum (lu_palette, PU_STATIC);
626 for(i = 0; i < 256;i++)
628 cgfx_coltab[p][i] = ((gammatable[usegamma][palette[i * 3]]) << 16) +
629 ((gammatable[usegamma][palette[i * 3 + 1]]) << 8) +
630 ((gammatable[usegamma][palette[i * 3 + 2]]));
636 /**********************************************************************/
637 // Takes full 8 bit values.
638 void I_SetPalette (byte *palette, int palette_index)
640 video_palette_changed = 1;
641 video_palette_index = palette_index;
644 /**********************************************************************/
645 // Called by anything that renders to screens[0] (except 3D view)
646 void I_MarkRect (int left, int top, int width, int height)
648 M_AddToBox (dirtybox, left, top);
649 M_AddToBox (dirtybox, left + width - 1, top + height - 1);
652 /**********************************************************************/
653 void I_StartUpdate (void)
657 /**********************************************************************/
658 void I_UpdateNoBlit (void)
662 /**********************************************************************/
663 void I_FinishUpdate (void)
664 /* This needs optimising to copy just the parts that changed,
665 especially if the user has shrunk the playscreen. */
667 int top, left, width, height;
668 #ifndef AROS
669 int stat, i, j;
670 UBYTE *base_address;
671 #endif
673 total_frames++;
675 #ifndef AROS
676 if (video_is_directcgx) {
677 if (video_palette_changed != 0) {
678 LoadRGB32 (&video_screen->ViewPort,
679 video_colourtable[video_palette_index]);
680 video_palette_changed = 0;
682 start_timer ();
683 video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
684 LBMI_BASEADDRESS, &base_address,
685 TAG_DONE);
686 memcpy (base_address, screens[0], SCREENWIDTH * SCREENHEIGHT);
687 UnLockBitMap (video_bitmap_handle);
688 lock_time += end_timer();
690 if (video_doing_fps)
691 video_do_fps (video_window->RPort, 0);
692 return;
694 #endif
696 /* update only the viewwindow and dirtybox when gamestate == GS_LEVEL */
697 if (gamestate == GS_LEVEL) {
698 if (dirtybox[BOXLEFT] < viewwindowx)
699 left = dirtybox[BOXLEFT];
700 else
701 left = viewwindowx;
702 if (dirtybox[BOXRIGHT] + 1 > viewwindowx + scaledviewwidth)
703 width = dirtybox[BOXRIGHT] + 1 - left;
704 else
705 width = viewwindowx + scaledviewwidth - left;
706 if (dirtybox[BOXBOTTOM] < viewwindowy) /* BOXBOTTOM is really the top! */
707 top = dirtybox[BOXBOTTOM];
708 else
709 top = viewwindowy;
710 if (dirtybox[BOXTOP] + 1 > viewwindowy + viewheight)
711 height = dirtybox[BOXTOP] + 1 - top;
712 else
713 height = viewwindowy + viewheight - top;
714 M_ClearBox (dirtybox);
715 #ifdef RANGECHECK
716 if (left < 0 || left + width > SCREENWIDTH ||
717 top < 0 || top + height > SCREENHEIGHT)
718 I_Error ("I_FinishUpdate: Box out of range: %d %d %d %d",
719 left, top, width, height);
720 #endif
721 } else {
722 left = 0;
723 top = 0;
724 width = SCREENWIDTH;
725 height = SCREENHEIGHT;
728 /* not directcgx or graffiti */
729 if (video_palette_changed != 0) {
731 if (video_do_screen)
733 LoadRGB32 (&video_screen->ViewPort,
734 video_colourtable[video_palette_index]);
737 video_palette_changed = 0;
741 if (video_do_screen)
743 start_timer();
744 WritePixelArray8 (video_window->RPort, 0, top, SCREENWIDTH-1,
745 top+height-1, &screens[0][SCREENWIDTH * top],
746 &video_temprp);
747 wpa8_time += end_timer();
748 } else {
749 WriteLUTPixelArray(screens[0],
750 left,
751 top,
752 SCREENWIDTH,
753 video_window->RPort,
754 cgfx_coltab[video_palette_index],
755 video_window->BorderLeft,
756 video_window->BorderTop,
757 width,
758 height,
759 CTABFMT_XRGB8);
762 if (video_doing_fps)
763 video_do_fps (video_window->RPort, 0);
765 SetTaskPri(FindTask(NULL), -1);
766 SetTaskPri(FindTask(NULL), 0);
770 /**********************************************************************/
771 // Wait for vertical retrace or pause a bit. Use when quit game.
772 void I_WaitVBL(int count)
774 Delay(count);
777 /**********************************************************************/
778 void I_ReadScreen (byte* scr)
780 memcpy (scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
784 /**********************************************************************/
785 void I_BeginRead (void)
789 /**********************************************************************/
790 void I_EndRead (void)
794 /**********************************************************************/
796 int xlate_key (UWORD rawkey, UWORD qualifier, APTR *eventptr)
798 char buffer[4], c;
799 struct InputEvent ie;
800 static int xlate[0x68] = {
801 '`', '1', '2', '3', '4', '5', '6', '7',
802 '8', '9', '0', KEY_MINUS, KEY_EQUALS, '\\', 0, '0',
803 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
804 'o', 'p', KEY_F11, KEY_F12, 0, '0', '2', '3',
805 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
806 'l', ';', '\'', KEY_ENTER, 0, '4', '5', '6',
807 KEY_RSHIFT, 'z', 'x', 'c', 'v', 'b', 'n', 'm',
808 ',', '.', '/', 0, '.', '7', '8', '9',
809 ' ', KEY_BACKSPACE, KEY_TAB, KEY_ENTER, KEY_ENTER, KEY_ESCAPE, KEY_F11,
810 0, 0, 0, KEY_MINUS, 0, KEY_UPARROW, KEY_DOWNARROW, KEY_RIGHTARROW, KEY_LEFTARROW,
811 KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
812 KEY_F9, KEY_F10, '(', ')', '/', '*', KEY_EQUALS, KEY_PAUSE,
813 KEY_RSHIFT, KEY_RSHIFT, 0, KEY_RCTRL, KEY_LALT, KEY_RALT, 0, KEY_RCTRL
816 if (video_is_rawkey)
817 if (rawkey < 0x68)
818 return xlate[rawkey];
819 else
820 return 0;
821 else {
822 if (rawkey > 0x00 && rawkey < 0x0a) // '1'..'9', no SHIFT French keyboards
823 return '0' + rawkey;
824 else if (rawkey == 0x0a) // '0'
825 return '0';
826 else if (rawkey < 0x40) {
827 ie.ie_Class = IECLASS_RAWKEY;
828 ie.ie_Code = rawkey;
829 ie.ie_Qualifier = qualifier;
830 ie.ie_EventAddress = eventptr ? *eventptr : NULL; /* AROS FIXME: key intuimessage */
831 ie.ie_NextEvent = NULL; /* AROS FIX */
833 if (MapRawKey (&ie, buffer, sizeof(buffer), NULL) > 0) {
834 c = buffer[0];
835 if (c >= '0' && c <= '9') /* numeric pad */
836 switch (c) {
837 case '0':
838 return ' ';
839 case '1':
840 return ',';
841 case '2':
842 return KEY_RCTRL;
843 case '3':
844 return '.';
845 case '4':
846 return KEY_LEFTARROW;
847 case '5':
848 return KEY_DOWNARROW;
849 case '6':
850 return KEY_RIGHTARROW;
851 case '7':
852 return ',';
853 case '8':
854 return KEY_UPARROW;
855 case '9':
856 return '.';
858 else if (c >= 'A' && c <= 'Z')
859 return c - 'A' + 'a';
860 else if (c == '<')
861 return ',';
862 else if (c == '>')
863 return '.';
864 else if (c == '-')
865 return KEY_MINUS;
866 else if (c == '=')
867 return KEY_EQUALS;
868 else if (c == '[')
869 return KEY_F11;
870 else if (c == ']')
871 return KEY_F12;
872 else if (c == '\r')
873 return KEY_ENTER;
874 else if (c == '\n')
875 return KEY_ENTER;
876 else
877 return c;
878 } else
879 return 0;
880 } else if (rawkey < 0x68)
881 return xlate[rawkey];
883 return 0;
886 /**********************************************************************/
887 void amiga_getevents (void)
889 event_t event;
890 ULONG class;
891 UWORD code;
892 WORD mousex, mousey;
893 struct IntuiMessage *msg;
894 #ifndef __AROS__
895 static ULONG previous = 0;
896 static event_t joyevent = {0};
897 ULONG currSega;
898 #endif
899 static event_t mouseevent = {0};
900 int doomkey;
902 if (video_window != NULL) {
903 while ((msg = (struct IntuiMessage *)GetMsg (video_window->UserPort)) != NULL) {
904 class = msg->Class;
905 code = msg->Code;
906 mousex = msg->MouseX;
907 mousey = msg->MouseY;
908 if (class == IDCMP_RAWKEY) {
909 if ((code & 0x80) != 0) {
910 code &= ~0x80;
911 event.type = ev_keyup;
912 } else {
913 event.type = ev_keydown;
915 if (code < 0x68)
916 doomkey = xlate_key (code, msg->Qualifier, msg->IAddress);
918 ReplyMsg ((struct Message *)msg); /* reply after xlating key */
919 if (class == IDCMP_RAWKEY) {
920 if (code < 0x68 && doomkey != 0) {
921 event.data1 = doomkey;
922 D_PostEvent (&event);
923 /* printf ("key %02x -> %02x\n", code, doomkey); */
925 } else if (class == IDCMP_MOUSEMOVE) {
926 mouseevent.type = ev_mouse;
927 mouseevent.data2 = (mousex << 3);
928 mouseevent.data3 = -(mousey << 5);
929 D_PostEvent (&mouseevent);
930 } else if (class == IDCMP_MOUSEBUTTONS) {
931 mouseevent.type = ev_mouse;
932 switch (code) {
933 case SELECTDOWN:
934 mouseevent.data1 |= 1;
935 break;
936 case SELECTUP:
937 mouseevent.data1 &= ~1;
938 break;
939 case MENUDOWN:
940 mouseevent.data1 |= 2;
941 break;
942 case MENUUP:
943 mouseevent.data1 &= ~2;
944 break;
945 case MIDDLEDOWN:
946 mouseevent.data1 |= 4;
947 break;
948 case MIDDLEUP:
949 mouseevent.data1 &= ~4;
950 break;
951 default:
952 break;
954 D_PostEvent (&mouseevent);
955 } else if (class == IDCMP_CLOSEWINDOW)
957 I_Quit();
962 #ifndef AROS
964 if (gameport_is_open && gameport_io_in_progress) {
965 while (GetMsg (gameport_mp) != NULL) {
966 switch (gameport_ie.ie_Code) {
967 case IECODE_LBUTTON:
968 joyevent.data1 |= 1;
969 break;
970 case IECODE_LBUTTON | IECODE_UP_PREFIX:
971 joyevent.data1 &= ~1;
972 break;
973 case IECODE_RBUTTON:
974 joyevent.data1 |= 2;
975 break;
976 case IECODE_RBUTTON | IECODE_UP_PREFIX:
977 joyevent.data1 &= ~2;
978 break;
979 case IECODE_MBUTTON:
980 joyevent.data1 |= 4;
981 break;
982 case IECODE_MBUTTON | IECODE_UP_PREFIX:
983 joyevent.data1 &= ~4;
984 break;
985 case IECODE_NOBUTTON:
986 joyevent.data2 = gameport_ie.ie_X;
987 joyevent.data3 = gameport_ie.ie_Y;
988 break;
989 default:
990 break;
992 joyevent.type = ev_joystick;
993 D_PostEvent (&joyevent);
994 gameport_io->io_Command = GPD_READEVENT;
995 gameport_io->io_Length = sizeof (struct InputEvent);
996 gameport_io->io_Data = &gameport_ie;
997 SendIO ((struct IORequest *)gameport_io);
1001 /* CD32 joypad handler code supplied by Gabry (ggreco@iol.it) */
1003 if (LowLevelBase != NULL) {
1004 event_t joyevent;
1005 ULONG joypos = ReadJoyPort (1);
1007 if (previous == joypos)
1008 return;
1010 joyevent.type = ev_joystick;
1011 joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
1013 if (joypos & JPF_BUTTON_RED)
1014 joyevent.data1 |= 1;
1015 else
1016 joyevent.data1 &= ~1;
1018 if (joypos & JP_DIRECTION_MASK) {
1019 if (joypos & JPF_JOY_LEFT) {
1020 joyevent.data2 = -1;
1021 } else if (joypos & JPF_JOY_RIGHT) {
1022 joyevent.data2 = 1;
1024 if (joypos & JPF_JOY_UP) {
1025 joyevent.data3 = -1;
1026 } else if (joypos & JPF_JOY_DOWN) {
1027 joyevent.data3 = 1;
1031 if (joypos & JP_TYPE_GAMECTLR) {
1032 event_t event;
1034 // Play/Pause = ESC (Menu)
1035 if (joypos & JPF_BUTTON_PLAY && !(previous & JPF_BUTTON_PLAY)) {
1036 event.type = ev_keydown;
1037 event.data1 = KEY_ESCAPE;
1038 D_PostEvent (&event);
1039 } else if (previous & JPF_BUTTON_PLAY) {
1040 event.type = ev_keyup;
1041 event.data1 = KEY_ESCAPE;
1042 D_PostEvent (&event);
1045 // YELLOW = SHIFT (button 2) (Run)
1046 if (joypos & JPF_BUTTON_YELLOW)
1047 joyevent.data1 |= 4;
1048 else
1049 joyevent.data1 &= ~4;
1051 // BLUE = SPACE (button 3) (Open/Operate)
1053 if (joypos & JPF_BUTTON_BLUE)
1054 joyevent.data1 |= 8;
1055 else
1056 joyevent.data1 &= ~8;
1058 // GREEN = RETURN (show msg)
1060 if (joypos & JPF_BUTTON_GREEN && !(previous&JPF_BUTTON_GREEN)) {
1061 event.type = ev_keydown;
1062 event.data1 = 13;
1063 D_PostEvent (&event);
1064 } else if (previous & JPF_BUTTON_GREEN) {
1065 event.type = ev_keyup;
1066 event.data1 = 13;
1067 D_PostEvent (&event);
1070 // FORWARD & REVERSE - ALT (Button1) Strafe left/right
1072 if (joypos & JPF_BUTTON_FORWARD) {
1073 joyevent.data1 |= 2;
1074 joyevent.data2 = 1;
1075 } else if (joypos & JPF_BUTTON_REVERSE) {
1076 joyevent.data1 |=2;
1077 joyevent.data2=-1;
1078 } else
1079 joyevent.data1 &= ~2;
1082 D_PostEvent (&joyevent);
1084 previous = joypos;
1087 /* SEGA joypad handler code by Joe Fenton, loosely based on CD32 handling */
1089 if (sega3_selected || sega6_selected) {
1090 event_t joyevent, event;
1092 if (sega3_selected) {
1093 currSega = Sega3 ();
1094 } else {
1095 currSega = Sega6 ();
1098 if (prevSega == currSega)
1099 return;
1101 joyevent.type = ev_joystick;
1102 joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
1104 // B = fire
1105 if (currSega & 0x10)
1106 joyevent.data1 |= 1;
1107 else
1108 joyevent.data1 &= ~1;
1110 // directionals
1111 if (currSega & 0xF) {
1112 if (currSega & 4) {
1113 joyevent.data2 = -1;
1114 } else if (currSega & 8) {
1115 joyevent.data2 = 1;
1117 if (currSega & 1) {
1118 joyevent.data3 = -1;
1119 } else if (currSega & 2) {
1120 joyevent.data3 = 1;
1124 // Mode = ESC (Menu)
1125 if (currSega & 0x80000 && !(prevSega & 0x80000)) {
1126 event.type = ev_keydown;
1127 event.data1 = KEY_ESCAPE;
1128 D_PostEvent (&event);
1129 } else if (prevSega & 0x80000) {
1130 event.type = ev_keyup;
1131 event.data1 = KEY_ESCAPE;
1132 D_PostEvent (&event);
1135 // Y = SHIFT (Run)
1136 if (currSega & 0x20000)
1137 joyevent.data1 |= 4;
1138 else
1139 joyevent.data1 &= ~4;
1141 // Start = SPACE (Open/Operate)
1142 if (currSega & 0x2000)
1143 joyevent.data1 |= 8;
1144 else
1145 joyevent.data1 &= ~8;
1147 // A & C - ALT (Button1) Strafe left/right
1148 if (currSega & 0x20) {
1149 joyevent.data1 |= 2;
1150 joyevent.data2 = 1;
1151 } else if (currSega & 0x1000) {
1152 joyevent.data1 |=2;
1153 joyevent.data2=-1;
1154 } else
1155 joyevent.data1 &= ~2;
1157 // X = RETURN (show msg)
1158 if (currSega & 0x40000 && !(prevSega&0x40000)) {
1159 event.type = ev_keydown;
1160 event.data1 = 13;
1161 D_PostEvent (&event);
1162 } else if (prevSega & 0x40000) {
1163 event.type = ev_keyup;
1164 event.data1 = 13;
1165 D_PostEvent (&event);
1168 // Z = TAB (show map)
1169 if (currSega & 0x10000 && !(prevSega&0x10000)) {
1170 event.type = ev_keydown;
1171 event.data1 = 9;
1172 D_PostEvent (&event);
1173 } else if (prevSega & 0x10000) {
1174 event.type = ev_keyup;
1175 event.data1 = 9;
1176 D_PostEvent (&event);
1179 D_PostEvent (&joyevent);
1181 prevSega = currSega;
1183 #endif
1186 /**********************************************************************/
1187 static void calc_time (ULONG time, char *msg)
1189 printf ("Total %s = %u us (%u us/frame)\n", msg, time, time / total_frames);
1192 /**********************************************************************/
1193 void _STDvideo_cleanup (void)
1195 I_ShutdownGraphics ();
1196 if (video_smr != NULL) {
1197 FreeAslRequest (video_smr);
1198 video_smr = NULL;
1200 if (total_frames > 0) {
1201 printf ("Total number of frames = %u\n", total_frames);
1202 calc_time (wpa8_time, "WritePixelArray8 time ");
1203 calc_time (lock_time, "LockBitMap time ");
1204 calc_time (c2p_time, "Chunky2Planar time ");
1205 #ifdef PROFILE
1207 int i;
1209 for (i=0; i<32; i++)
1210 calc_time (profile[n][2], "Profile Time ");
1212 #endif
1216 /**********************************************************************/