Replaced Exit() by exit() because Exit() is like abort().
[AROS-Contrib.git] / Games / Quake / vid_aros.c
blobf39a03bf6adbafe015603579146c46a4d447e1cf
1 /*
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
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
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>
44 #include "quakedef.h"
45 #include "d_local.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;
67 void *vid_surfcache;
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);
105 if (d_pzbuffer) {
106 D_FlushCaches();
107 Hunk_FreeToHighMark(aros_highhunkmark);
108 d_pzbuffer = NULL;
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)
153 int verbose;
154 int pnum;
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");
168 return;
171 if (aros_use_cgfx) {
172 CyberGfxBase = OpenLibrary("cybergraphics.library", 0);
173 if (NULL == CyberGfxBase) {
174 Sys_Error("Error opening cybergraphics.library");
175 return;
177 } else {
179 GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37);
180 if (NULL == GfxBase) {
181 Sys_Error("Error opening graphics.library");
182 return;
186 KeymapBase = OpenLibrary("keymap.library", 37);
187 if (NULL == KeymapBase) {
188 Sys_Error("Error opening keymap.library");
189 return;
194 // ignorenext=0;
195 vid.width = 320;
196 vid.height = 200;
197 vid.maxwarpwidth = WARP_WIDTH;
198 vid.maxwarpheight = WARP_HEIGHT;
199 vid.numpages = 2;
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]);
223 if (!vid.width)
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]);
230 if (!vid.height)
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");
244 return;
247 UnlockPubScreen(NULL, aros_screen);
249 } else {
252 aros_screen = OpenScreenTags(NULL
253 , SA_Width, 640
254 , SA_Height, 480
255 , TAG_DONE);
258 if (NULL == aros_screen) {
259 Sys_Error("Could not get screen\n");
260 return;
265 aros_win = OpenWindowTags(NULL
266 , WA_InnerWidth, vid.width
267 , WA_InnerHeight, vid.height
268 , WA_DragBar, TRUE
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
277 , WA_Activate, TRUE
278 , TAG_DONE
282 if (!aros_win) {
283 Sys_Error("Could not open window\n");
284 return;
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);
294 calc_window_dims();
295 vid.width = aros_win_innerwidth;
296 vid.height = aros_win_innerheight;
297 reset_framebuffer();
300 vid.rowbytes = vid.width;
301 vid.buffer = aros_framebuffer;
302 vid.direct = 0;
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");
315 VID_SetPalette(p);
319 #define NUMCOLORS 256L
321 void VID_SetPalette(unsigned char *palette)
323 if (aros_use_cgfx) {
324 int i;
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)
329 | palette[i*3+2];
333 } else {
334 ULONG coltab[NUMCOLORS * 3 + 2];
335 int i;
337 ULONG *colcell;
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;
348 colcell += 3;
350 colcell [0] = 0;
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");
394 aros_vid_shutdown();
398 // flushes the given rectangles from the view buffer to the screen
400 void VID_Update (vrect_t *rects)
404 // vrect_t full;
406 // if the window changes dimension, skip this frame
407 if (aros_size_changed)
409 printf("config notify\n");
410 aros_size_changed = FALSE;
412 calc_window_dims();
413 vid.width = aros_win_innerwidth;
414 vid.height = aros_win_innerheight;
416 printf("New dims: %d, %d\n", vid.width, vid.height);
418 reset_framebuffer();
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
426 Con_CheckResize();
427 Con_Clear_f();
428 return;
432 while (rects)
435 // FIXME: Optimize this. Just rerender the part inside the rect
436 if (aros_use_cgfx) {
438 WriteLUTPixelArray(
439 aros_framebuffer
440 , 0, 0
441 , aros_win_innerwidth
442 , aros_win->RPort
443 , cgfx_coltab
444 , aros_win_innerleft
445 , aros_win_innertop
446 , aros_win_innerwidth
447 , aros_win_innerheight
448 , CTABFMT_XRGB8
451 } else {
453 /* Just do a full screen update for now */
454 SetDrMd(aros_win->RPort, JAM1);
455 WritePixelArray8(aros_win->RPort
456 , aros_win_innerleft
457 , aros_win_innertop
458 , aros_win_innerright
459 , aros_win_innerbottom
460 , aros_framebuffer
461 , NULL
465 rects = rects->pnext;
472 void GetEvent(void)
475 struct IntuiMessage *imsg;
476 BOOL quit = FALSE;
478 if ((imsg = (struct IntuiMessage *)GetMsg(aros_win->UserPort))) {
479 switch (imsg->Class) {
481 case IDCMP_NEWSIZE:
482 /* The window is resized */
483 aros_size_changed = TRUE;
484 break;
486 case IDCMP_RAWKEY: {
487 LONG key = -1;
488 BOOL down;
491 if (imsg->Code & 0x80) {
492 // kprintf("UP\n");
493 down = FALSE;
494 } else {
495 // kprintf("DOWN\n");
496 down = TRUE;
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;
509 case 0x60:
510 case 0x61: key = K_SHIFT; break;
512 case 0x63: key = K_CTRL; break;
514 case 0x64: key = K_ALT; break;
516 default: {
517 UBYTE buf[10];
518 LONG chars;
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);
534 if (1 == chars) {
535 key = *buf;
536 if (key >= 'A' && key <= 'Z') {
537 key = key - 'A' + 'a';
539 break; }
545 if (-1 != key) {
547 Key_Event(key, down);
549 break; }
551 case IDCMP_CLOSEWINDOW:
552 quit = TRUE;
553 break;
557 ReplyMsg((struct Message *)imsg);
560 if (quit) {
561 Sys_Quit();
564 return;
566 static int dither;
568 void VID_DitherOn(void)
570 printf("VID_DitherOn\n");
572 if (dither == 0)
574 vid.recalc_refdef = 1;
575 dither = 1;
579 void VID_DitherOff(void)
581 printf("VID_DitherOff\n");
582 if (dither)
584 vid.recalc_refdef = 1;
585 dither = 0;
589 int Sys_OpenWindow(void)
591 return 0;
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");
609 GetEvent();
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