2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // vid_aros.c -- general AROS video driver
28 #include <proto/exec.h>
29 #include <proto/intuition.h>
30 #include <proto/graphics.h>
31 #include <proto/keymap.h>
32 #include <proto/cybergraphics.h>
34 #include <intuition/screens.h>
35 #include <intuition/intuition.h>
36 #include <graphics/rastport.h>
38 #include <cybergraphx/cybergraphics.h>
40 #include <exec/memory.h>
42 #include <devices/inputevent.h>
47 static UBYTE
*aros_framebuffer
;
48 static long aros_highhunkmark
;
49 static long aros_buffersize
;
50 static struct Screen
*aros_screen
= NULL
;
52 BOOL aros_size_changed
= FALSE
;
54 BOOL aros_use_wb_screen
= TRUE
;
55 BOOL aros_use_cgfx
= FALSE
;
57 static ULONG cgfx_coltab
[256];
59 struct Window
*aros_win
= NULL
;
60 LONG aros_win_innerleft
, aros_win_innertop
61 , aros_win_innerbottom
, aros_win_innerright
62 , aros_win_innerwidth
, aros_win_innerheight
;
66 int vid_surfcachesize
;
69 struct IntuitionBase
*IntuitionBase
= NULL
;
70 struct GfxBase
*GfxBase
= NULL
;
71 struct Library
*CyberGfxBase
= NULL
;
72 struct Library
*KeymapBase
= NULL
;
74 void aros_vid_shutdown();
77 /* SYMBOLS NEEDED FROM OTHER FILES */
78 viddef_t vid
; // global video state
79 unsigned short d_8to16table
[256];
81 static void calc_window_dims()
83 aros_win_innerleft
= aros_win
->BorderLeft
;
84 aros_win_innertop
= aros_win
->BorderTop
;
85 aros_win_innerright
= aros_win
->Width
- aros_win
->BorderRight
- 1;
86 aros_win_innerbottom
= aros_win
->Height
- aros_win
->BorderBottom
- 1;
88 aros_win_innerwidth
= aros_win_innerright
- aros_win_innerleft
+ 1;
89 aros_win_innerheight
= aros_win_innerbottom
- aros_win_innertop
+ 1;
91 /* NOTE !! Quake needs the alignment below */
92 aros_win_innerwidth
&= ~7;
93 aros_win_innerright
= aros_win_innerleft
+ aros_win_innerwidth
- 1;
97 static void reset_framebuffer()
99 aros_size_changed
= FALSE
;
101 if (aros_framebuffer
) {
102 FreeVec(aros_framebuffer
);
107 Hunk_FreeToHighMark(aros_highhunkmark
);
112 aros_highhunkmark
= Hunk_HighMark();
114 // alloc an extra line in case we want to wrap, and allocate the z-buffer
115 aros_buffersize
= vid
.width
* vid
.height
* sizeof (*d_pzbuffer
);
117 /* fprintf(stderr, "RFB: Size for each pixel: %d, total buffer size: %ld\n"
118 , sizeof (*d_pzbuffer), aros_buffersize);
120 vid_surfcachesize
= D_SurfaceCacheForRes(vid
.width
, vid
.height
);
122 aros_buffersize
+=vid_surfcachesize
;
124 d_pzbuffer
= Hunk_HighAllocName(aros_buffersize
, "video");
125 if (NULL
== d_pzbuffer
) {
126 Sys_Error("Not enough memory for video mode\n");
129 vid_surfcache
= (byte
*)d_pzbuffer
130 + vid
.width
* vid
.height
*sizeof (*d_pzbuffer
);
132 D_InitCaches(vid_surfcache
, vid_surfcachesize
);
134 aros_framebuffer
= AllocVec(vid
.width
* vid
.height
, MEMF_ANY
);
136 printf("New Quake dims: %dx%d\n", vid
.width
, vid
.height
);
138 if (NULL
== aros_framebuffer
) {
139 Sys_Error("Not enough memory for framebuffer\n");
142 vid
.buffer
= aros_framebuffer
;
143 vid
.conbuffer
= vid
.buffer
;
147 // Called at startup to set up translation tables, takes 256 8 bit RGB values
148 // the palette data will go away after the call, so it must be copied off if
149 // the video driver will need it again
151 void VID_Init (unsigned char *palette
)
156 printf("VID_INIT\n");
158 if ((pnum
=COM_CheckParm("-cgfx"))) {
159 aros_use_cgfx
= TRUE
;
164 // FIXME: Move this to main() ?
165 IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 37);
166 if (NULL
== IntuitionBase
) {
167 Sys_Error("Error opening intuition.library");
172 CyberGfxBase
= OpenLibrary("cybergraphics.library", 0);
173 if (NULL
== CyberGfxBase
) {
174 Sys_Error("Error opening cybergraphics.library");
179 GfxBase
= (struct GfxBase
*)OpenLibrary("graphics.library", 37);
180 if (NULL
== GfxBase
) {
181 Sys_Error("Error opening graphics.library");
186 KeymapBase
= OpenLibrary("keymap.library", 37);
187 if (NULL
== KeymapBase
) {
188 Sys_Error("Error opening keymap.library");
197 vid
.maxwarpwidth
= WARP_WIDTH
;
198 vid
.maxwarpheight
= WARP_HEIGHT
;
200 vid
.colormap
= host_colormap
;
201 // vid.cbits = VID_CBITS;
202 // vid.grades = VID_GRADES;
203 vid
.fullbright
= 256 - LittleLong (*((int *)vid
.colormap
+ 2048));
205 verbose
=COM_CheckParm("-verbose");
206 (void)verbose
; // FIXME: Unused
209 // check for command-line window size
210 if ((pnum
=COM_CheckParm("-winsize")))
212 if (pnum
>= com_argc
-2)
213 Sys_Error("VID: -winsize <width> <height>\n");
214 vid
.width
= Q_atoi(com_argv
[pnum
+1]);
215 vid
.height
= Q_atoi(com_argv
[pnum
+2]);
216 if (!vid
.width
|| !vid
.height
)
217 Sys_Error("VID: Bad window width/height\n");
219 if ((pnum
=COM_CheckParm("-width"))) {
220 if (pnum
>= com_argc
-1)
221 Sys_Error("VID: -width <width>\n");
222 vid
.width
= Q_atoi(com_argv
[pnum
+1]);
224 Sys_Error("VID: Bad window width\n");
226 if ((pnum
=COM_CheckParm("-height"))) {
227 if (pnum
>= com_argc
-1)
228 Sys_Error("VID: -height <height>\n");
229 vid
.height
= Q_atoi(com_argv
[pnum
+1]);
231 Sys_Error("VID: Bad window height\n");
235 if ((pnum
=COM_CheckParm("-ownscreen"))) {
236 aros_use_wb_screen
= FALSE
;
239 if (aros_use_wb_screen
) {
241 aros_screen
= LockPubScreen(NULL
);
242 if (NULL
== aros_screen
) {
243 Sys_Error("Could not get WB screen\n");
247 UnlockPubScreen(NULL
, aros_screen
);
252 aros_screen
= OpenScreenTags(NULL
258 if (NULL
== aros_screen
) {
259 Sys_Error("Could not get screen\n");
265 aros_win
= OpenWindowTags(NULL
266 , WA_InnerWidth
, vid
.width
267 , WA_InnerHeight
, vid
.height
269 , WA_SimpleRefresh
, TRUE
270 , WA_IDCMP
, IDCMP_RAWKEY
|IDCMP_NEWSIZE
|IDCMP_CLOSEWINDOW
271 , WA_CustomScreen
, aros_screen
272 , WA_Title
, "AROS Quake !"
273 , WA_DepthGadget
, TRUE
274 , WA_SizeGadget
, TRUE
275 , WA_CloseGadget
, TRUE
276 , WA_SizeBBottom
, TRUE
283 Sys_Error("Could not open window\n");
287 WindowLimits(aros_win
, 320 + aros_win
->BorderLeft
+ aros_win
->BorderRight
,
288 200 + aros_win
->BorderTop
+ aros_win
->BorderBottom
,
289 1024 + aros_win
->BorderLeft
+ aros_win
->BorderRight
,
290 1024 + aros_win
->BorderTop
+ aros_win
->BorderBottom
);
292 VID_SetPalette(palette
);
295 vid
.width
= aros_win_innerwidth
;
296 vid
.height
= aros_win_innerheight
;
300 vid
.rowbytes
= vid
.width
;
301 vid
.buffer
= aros_framebuffer
;
303 vid
.conbuffer
= aros_framebuffer
;
304 vid
.conrowbytes
= vid
.rowbytes
;
305 vid
.conwidth
= vid
.width
;
306 vid
.conheight
= vid
.height
;
307 vid
.aspect
= ((float)vid
.height
/ (float)vid
.width
) * (320.0 / 240.0);
312 void VID_ShiftPalette(unsigned char *p
)
314 // printf("VID_ShiftPalette\n");
319 #define NUMCOLORS 256L
321 void VID_SetPalette(unsigned char *palette
)
325 /* Just copy the colors to the palette */
326 for (i
= 0; i
< NUMCOLORS
; i
++) {
327 cgfx_coltab
[i
] = (palette
[i
*3] << 16)
328 |(palette
[i
*3+1] << 8)
334 ULONG coltab
[NUMCOLORS
* 3 + 2];
338 colcell
= &coltab
[1];
340 coltab
[0] = (NUMCOLORS
<< 16) + 0;
342 for (i
= 0; i
< NUMCOLORS
; i
++)
344 colcell
[0] = palette
[i
*3] << 24;
345 colcell
[1] = palette
[i
*3+1] << 24;
346 colcell
[2] = palette
[i
*3+2] << 24;
352 LoadRGB32(&aros_screen
->ViewPort
, coltab
);
357 // Called at shutdown
359 void aros_vid_shutdown()
361 if (NULL
!= aros_framebuffer
) {
362 FreeVec(aros_framebuffer
);
364 if (NULL
!= aros_win
) {
365 CloseWindow(aros_win
);
368 if (!aros_use_wb_screen
) {
369 if (NULL
!= aros_screen
) {
370 CloseScreen(aros_screen
);
374 if (NULL
!= KeymapBase
) {
375 CloseLibrary(KeymapBase
);
379 if (NULL
!= GfxBase
) {
380 CloseLibrary((struct Library
*)GfxBase
);
383 if (NULL
!= IntuitionBase
) {
384 CloseLibrary((struct Library
*)IntuitionBase
);
388 void VID_Shutdown (void)
390 printf("VID_Shutdown\n");
392 Con_Printf("VID_Shutdown\n");
398 // flushes the given rectangles from the view buffer to the screen
400 void VID_Update (vrect_t
*rects
)
406 // if the window changes dimension, skip this frame
407 if (aros_size_changed
)
409 printf("config notify\n");
410 aros_size_changed
= FALSE
;
413 vid
.width
= aros_win_innerwidth
;
414 vid
.height
= aros_win_innerheight
;
416 printf("New dims: %d, %d\n", vid
.width
, vid
.height
);
419 vid
.rowbytes
= vid
.width
;
420 vid
.buffer
= aros_framebuffer
;
421 vid
.conbuffer
= vid
.buffer
;
422 vid
.conwidth
= vid
.width
;
423 vid
.conheight
= vid
.height
;
424 vid
.conrowbytes
= vid
.rowbytes
;
425 vid
.recalc_refdef
= 1; // force a surface cache flush
435 // FIXME: Optimize this. Just rerender the part inside the rect
441 , aros_win_innerwidth
446 , aros_win_innerwidth
447 , aros_win_innerheight
453 /* Just do a full screen update for now */
454 SetDrMd(aros_win
->RPort
, JAM1
);
455 WritePixelArray8(aros_win
->RPort
458 , aros_win_innerright
459 , aros_win_innerbottom
465 rects
= rects
->pnext
;
475 struct IntuiMessage
*imsg
;
478 if ((imsg
= (struct IntuiMessage
*)GetMsg(aros_win
->UserPort
))) {
479 switch (imsg
->Class
) {
482 /* The window is resized */
483 aros_size_changed
= TRUE
;
491 if (imsg
->Code
& 0x80) {
495 // kprintf("DOWN\n");
500 switch (imsg
->Code
& ~0x80) {
501 case 0x45: key
= K_ESCAPE
; break;
502 case 0x44: key
= K_ENTER
; break;
504 case 0x4F: key
= K_LEFTARROW
; break;
505 case 0x4E: key
= K_RIGHTARROW
; break;
506 case 0x4C: key
= K_UPARROW
; break;
507 case 0x4D: key
= K_DOWNARROW
; break;
510 case 0x61: key
= K_SHIFT
; break;
512 case 0x63: key
= K_CTRL
; break;
514 case 0x64: key
= K_ALT
; break;
520 struct InputEvent ie
;
521 memset (&ie
, 0, sizeof (ie
));
524 ie
.ie_NextEvent
= NULL
;
525 ie
.ie_Class
= IECLASS_RAWKEY
;
526 ie
.ie_Code
= imsg
->Code
& ~0x80;
527 ie
.ie_Qualifier
= imsg
->Qualifier
;
530 chars
= MapRawKey(&ie
, buf
, 10, NULL
);
532 // printf("GOT KEY %c, chars=%ld\n", *buf, chars);
536 if (key
>= 'A' && key
<= 'Z') {
537 key
= key
- 'A' + 'a';
547 Key_Event(key
, down
);
551 case IDCMP_CLOSEWINDOW
:
557 ReplyMsg((struct Message
*)imsg
);
568 void VID_DitherOn(void)
570 printf("VID_DitherOn\n");
574 vid
.recalc_refdef
= 1;
579 void VID_DitherOff(void)
581 printf("VID_DitherOff\n");
584 vid
.recalc_refdef
= 1;
589 int Sys_OpenWindow(void)
594 void Sys_EraseWindow(int window
)
598 void Sys_DrawCircle(int window
, int x
, int y
, int r
)
602 void Sys_DisplayWindow(int window
)
606 void Sys_SendKeyEvents(void)
608 // printf("Sys_SendKeyEvents\n");
614 void D_BeginDirectRect (int x
, int y
, byte
*pbitmap
, int width
, int height
)
616 // direct drawing of the "accessing disk" icon isn't supported under Linux
619 void D_EndDirectRect (int x
, int y
, int width
, int height
)
621 // direct drawing of the "accessing disk" icon isn't supported under Linux