doomgeneric/frosted-doom/i_video_fbdev.c

354 lines
7.2 KiB
C

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// DOOM graphics stuff for fbdev on Frosted
//
//-----------------------------------------------------------------------------
static const char
rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $";
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include "doomstat.h"
#include "i_system.h"
#include "v_video.h"
#include "m_argv.h"
#include "d_main.h"
#include "doomdef.h"
struct color {
uint32_t b:8;
uint32_t g:8;
uint32_t r:8;
uint32_t a:8;
};
struct color colors[256];
/* framebuffer file descriptor */
int fd_fb = 0;
int X_width;
int X_height;
void I_ShutdownGraphics(void)
{
printf("I_ShutdownGraphics\n");
// Always be sure to clean up
//SDL_Quit();
close(fd_fb);
}
//
// I_StartFrame
//
void I_StartFrame (void)
{
// er?
}
void I_GetEvent(void)
{
/*
event_t event;
// put event-grabbing stuff in here
XNextEvent(X_display, &X_event);
switch (X_event.type)
{
case KeyPress:
event.type = ev_keydown;
event.data1 = xlatekey();
D_PostEvent(&event);
// fprintf(stderr, "k");
break;
case KeyRelease:
event.type = ev_keyup;
event.data1 = xlatekey();
D_PostEvent(&event);
// fprintf(stderr, "ku");
break;
case ButtonPress:
event.type = ev_mouse;
event.data1 =
(X_event.xbutton.state & Button1Mask)
| (X_event.xbutton.state & Button2Mask ? 2 : 0)
| (X_event.xbutton.state & Button3Mask ? 4 : 0)
| (X_event.xbutton.button == Button1)
| (X_event.xbutton.button == Button2 ? 2 : 0)
| (X_event.xbutton.button == Button3 ? 4 : 0);
event.data2 = event.data3 = 0;
D_PostEvent(&event);
// fprintf(stderr, "b");
break;
case ButtonRelease:
event.type = ev_mouse;
event.data1 =
(X_event.xbutton.state & Button1Mask)
| (X_event.xbutton.state & Button2Mask ? 2 : 0)
| (X_event.xbutton.state & Button3Mask ? 4 : 0);
// suggest parentheses around arithmetic in operand of |
event.data1 =
event.data1
^ (X_event.xbutton.button == Button1 ? 1 : 0)
^ (X_event.xbutton.button == Button2 ? 2 : 0)
^ (X_event.xbutton.button == Button3 ? 4 : 0);
event.data2 = event.data3 = 0;
D_PostEvent(&event);
// fprintf(stderr, "bu");
break;
case MotionNotify:
event.type = ev_mouse;
event.data1 =
(X_event.xmotion.state & Button1Mask)
| (X_event.xmotion.state & Button2Mask ? 2 : 0)
| (X_event.xmotion.state & Button3Mask ? 4 : 0);
event.data2 = (X_event.xmotion.x - lastmousex) << 2;
event.data3 = (lastmousey - X_event.xmotion.y) << 2;
if (event.data2 || event.data3)
{
lastmousex = X_event.xmotion.x;
lastmousey = X_event.xmotion.y;
if (X_event.xmotion.x != X_width/2 &&
X_event.xmotion.y != X_height/2)
{
D_PostEvent(&event);
// fprintf(stderr, "m");
mousemoved = false;
} else
{
mousemoved = true;
}
}
break;
case Expose:
case ConfigureNotify:
break;
default:
if (doShm && X_event.type == X_shmeventtype) shmFinished = true;
break;
}
*/
}
//
// I_StartTic
//
void I_StartTic (void)
{
return;
/*
if (!X_display)
return;
while (XPending(X_display))
I_GetEvent();
// Warp the pointer back to the middle of the window
// or it will wander off - that is, the game will
// loose input focus within X11.
if (grabMouse)
{
if (!--doPointerWarp)
{
XWarpPointer( X_display,
None,
X_mainWindow,
0, 0,
0, 0,
X_width/2, X_height/2);
doPointerWarp = POINTER_WARP_COUNTDOWN;
}
}
mousemoved = false;
*/
}
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit (void)
{
// what is this?
}
//
// I_FinishUpdate
//
#define FB_WIDTH (480)
#define FB_HEIGHT (272)
#define FB_BPP_RGB565 (16)
unsigned char line_out[FB_WIDTH * (FB_BPP_RGB565/8)];
void cmap_to_rgb565(uint16_t * out, uint8_t * in, int in_pixels)
{
int i;
struct color c;
uint16_t r, g, b;
for (i = 0; i < in_pixels; i++)
{
c = colors[*in];
r = ((uint16_t)(c.r >> 3)) << 11;
g = ((uint16_t)(c.g >> 2)) << 5;
b = ((uint16_t)(c.b >> 3)) << 0;
*out = (r | g | b);
in++;
out++;
}
}
void I_FinishUpdate (void)
{
unsigned char *line_in;
static int lasttic;
int tics;
int i;
int y;
// draws little dots on the bottom of the screen
if (devparm)
{
i = I_GetTime();
tics = i - lasttic;
lasttic = i;
if (tics > 20) tics = 20;
for (i=0 ; i<tics*2 ; i+=2)
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
for ( ; i<20*2 ; i+=2)
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
}
/* DRAW SCREEN */
line_in = (unsigned char *) screens[0];
lseek(fd_fb, 0, SEEK_SET);
y = SCREENHEIGHT;
#define CMAP256
#ifdef CMAP256
while (y--)
{
write(fd_fb, line_in, FB_WIDTH); /* FB_WIDTH is bigger then Doom SCREENWIDTH... */
line_in += SCREENWIDTH;
}
#else
while (y--)
{
cmap_to_rgb565(line_out, line_in, SCREENWIDTH);
write(fd_fb, line_out, FB_WIDTH * (FB_BPP_RGB565/8));
line_in += SCREENWIDTH;
}
#endif
}
//
// I_ReadScreen
//
void I_ReadScreen (byte* scr)
{
/* Our framebuffer is not the same resolution, so makes reading difficult */
//lseek(fd_fb, 0, SEEK_SET);
//int left = SCREENWIDTH * SCREENHEIGHT;
//while (left)
//{
// int rd = read(fd_fb, scr, left);
// if (rd > 0)
// left -= rd;
//}
memcpy(scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
}
//
// I_SetPalette
//
void I_SetPalette (byte* palette)
{
//printf("I_SetPalette\n");
for (int i=0; i<256; ++i ) {
colors[i].a = 0;
colors[i].r = gammatable[usegamma][*palette++];
colors[i].g = gammatable[usegamma][*palette++];
colors[i].b = gammatable[usegamma][*palette++];
}
/* Set new color map in kernel framebuffer driver */
ioctl(fd_fb, IOCTL_FB_PUTCMAP, colors);
}
void I_InitGraphics(void)
{
unsigned char * screen_pixels;
X_width = SCREENWIDTH;
X_height = SCREENHEIGHT;
printf("I_InitGraphics: w x h: %d x %d\n", X_width, X_height);
/* Open fbdev file descriptor */
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
printf("Could not open /dev/fb0");
exit(-1);
}
/* Allocate screen to draw to */
screen_pixels = malloc(X_width * X_height);
screens[0] = (unsigned char *)screen_pixels;
}