520 lines
10 KiB
C
520 lines
10 KiB
C
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id:$
|
|
//
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// $Log:$
|
|
//
|
|
// DESCRIPTION:
|
|
// DOOM graphics stuff for X11, UNIX.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static const char
|
|
rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $";
|
|
|
|
#include "config.h"
|
|
#include "v_video.h"
|
|
#include "m_argv.h"
|
|
#include "d_event.h"
|
|
#include "d_main.h"
|
|
#include "i_video.h"
|
|
#include "z_zone.h"
|
|
|
|
#include "tables.h"
|
|
#include "doomkeys.h"
|
|
|
|
#include <stdbool.h>
|
|
#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>
|
|
|
|
|
|
#define FB_WIDTH (480)
|
|
#define FB_HEIGHT (272)
|
|
#define FB_BPP_RGB565 (16)
|
|
|
|
struct color {
|
|
uint32_t b:8;
|
|
uint32_t g:8;
|
|
uint32_t r:8;
|
|
uint32_t a:8;
|
|
};
|
|
|
|
static struct color colors[256];
|
|
|
|
// The screen buffer; this is modified to draw things to the screen
|
|
|
|
byte *I_VideoBuffer = NULL;
|
|
byte *I_VideoBuffer_FB = NULL;
|
|
|
|
/* framebuffer file descriptor */
|
|
int fd_fb = 0;
|
|
|
|
int X_width;
|
|
int X_height;
|
|
|
|
// If true, game is running as a screensaver
|
|
|
|
boolean screensaver_mode = false;
|
|
|
|
// Flag indicating whether the screen is currently visible:
|
|
// when the screen isnt visible, don't render the screen
|
|
|
|
boolean screenvisible;
|
|
|
|
// Mouse acceleration
|
|
//
|
|
// This emulates some of the behavior of DOS mouse drivers by increasing
|
|
// the speed when the mouse is moved fast.
|
|
//
|
|
// The mouse input values are input directly to the game, but when
|
|
// the values exceed the value of mouse_threshold, they are multiplied
|
|
// by mouse_acceleration to increase the speed.
|
|
|
|
float mouse_acceleration = 2.0;
|
|
int mouse_threshold = 10;
|
|
|
|
// Gamma correction level to use
|
|
|
|
int usegamma = 0;
|
|
|
|
int usemouse = 0;
|
|
|
|
// If true, keyboard mapping is ignored, like in Vanilla Doom.
|
|
// The sensible thing to do is to disable this if you have a non-US
|
|
// keyboard.
|
|
|
|
int vanilla_keyboard_mapping = true;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
byte r;
|
|
byte g;
|
|
byte b;
|
|
} col_t;
|
|
|
|
// Palette converted to RGB565
|
|
|
|
static uint16_t rgb565_palette[256];
|
|
|
|
// Last touch state
|
|
|
|
//static touch_state_t last_touch_state;
|
|
|
|
// Last button state
|
|
|
|
//static bool last_button_state;
|
|
|
|
// run state
|
|
|
|
//static bool run;
|
|
|
|
void I_InitGraphics (void)
|
|
{
|
|
// gfx_image_t keys_img;
|
|
// gfx_coord_t coords;
|
|
//
|
|
// gfx_init_img (&keys_img, 40, 320, GFX_PIXEL_FORMAT_RGB565, RGB565_BLACK);
|
|
// keys_img.pixel_data = (uint8_t*)img_keys;
|
|
// gfx_init_img_coord (&coords, &keys_img);
|
|
//
|
|
// gfx_draw_img (&keys_img, &coords);
|
|
// lcd_refresh ();
|
|
//
|
|
// gfx_draw_img (&keys_img, &coords);
|
|
// lcd_refresh ();
|
|
|
|
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);
|
|
//
|
|
I_VideoBuffer = (byte*)Z_Malloc (SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); // For DOOM to draw on
|
|
I_VideoBuffer_FB = (byte*)Z_Malloc (FB_WIDTH * FB_HEIGHT, PU_STATIC, NULL); // For a single write() syscall to fbdev
|
|
|
|
screenvisible = true;
|
|
}
|
|
|
|
void I_ShutdownGraphics (void)
|
|
{
|
|
Z_Free (I_VideoBuffer);
|
|
Z_Free (I_VideoBuffer_FB);
|
|
}
|
|
|
|
void I_StartFrame (void)
|
|
{
|
|
|
|
}
|
|
|
|
void I_GetEvent (void)
|
|
{
|
|
// event_t event;
|
|
// bool button_state;
|
|
//
|
|
// button_state = button_read ();
|
|
//
|
|
// if (last_button_state != button_state)
|
|
// {
|
|
// last_button_state = button_state;
|
|
//
|
|
// event.type = last_button_state ? ev_keydown : ev_keyup;
|
|
// event.data1 = KEY_FIRE;
|
|
// event.data2 = -1;
|
|
// event.data3 = -1;
|
|
//
|
|
// D_PostEvent (&event);
|
|
// }
|
|
//
|
|
// touch_main ();
|
|
//
|
|
// if ((touch_state.x != last_touch_state.x) || (touch_state.y != last_touch_state.y) || (touch_state.status != last_touch_state.status))
|
|
// {
|
|
// last_touch_state = touch_state;
|
|
//
|
|
// event.type = (touch_state.status == TOUCH_PRESSED) ? ev_keydown : ev_keyup;
|
|
// event.data1 = -1;
|
|
// event.data2 = -1;
|
|
// event.data3 = -1;
|
|
//
|
|
// if ((touch_state.x > 49)
|
|
// && (touch_state.x < 72)
|
|
// && (touch_state.y > 104)
|
|
// && (touch_state.y < 143))
|
|
// {
|
|
// // select weapon
|
|
// if (touch_state.x < 60)
|
|
// {
|
|
// // lower row (5-7)
|
|
// if (touch_state.y < 119)
|
|
// {
|
|
// event.data1 = '5';
|
|
// }
|
|
// else if (touch_state.y < 131)
|
|
// {
|
|
// event.data1 = '6';
|
|
// }
|
|
// else
|
|
// {
|
|
// event.data1 = '1';
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// // upper row (2-4)
|
|
// if (touch_state.y < 119)
|
|
// {
|
|
// event.data1 = '2';
|
|
// }
|
|
// else if (touch_state.y < 131)
|
|
// {
|
|
// event.data1 = '3';
|
|
// }
|
|
// else
|
|
// {
|
|
// event.data1 = '4';
|
|
// }
|
|
// }
|
|
// }
|
|
// else if (touch_state.x < 40)
|
|
// {
|
|
// // button bar at bottom screen
|
|
// if (touch_state.y < 40)
|
|
// {
|
|
// // enter
|
|
// event.data1 = KEY_ENTER;
|
|
// }
|
|
// else if (touch_state.y < 80)
|
|
// {
|
|
// // escape
|
|
// event.data1 = KEY_ESCAPE;
|
|
// }
|
|
// else if (touch_state.y < 120)
|
|
// {
|
|
// // use
|
|
// event.data1 = KEY_USE;
|
|
// }
|
|
// else if (touch_state.y < 160)
|
|
// {
|
|
// // map
|
|
// event.data1 = KEY_TAB;
|
|
// }
|
|
// else if (touch_state.y < 200)
|
|
// {
|
|
// // pause
|
|
// event.data1 = KEY_PAUSE;
|
|
// }
|
|
// else if (touch_state.y < 240)
|
|
// {
|
|
// // toggle run
|
|
// if (touch_state.status == TOUCH_PRESSED)
|
|
// {
|
|
// run = !run;
|
|
//
|
|
// event.data1 = KEY_RSHIFT;
|
|
//
|
|
// if (run)
|
|
// {
|
|
// event.type = ev_keydown;
|
|
// }
|
|
// else
|
|
// {
|
|
// event.type = ev_keyup;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// return;
|
|
// }
|
|
// }
|
|
// else if (touch_state.y < 280)
|
|
// {
|
|
// // save
|
|
// event.data1 = KEY_F2;
|
|
// }
|
|
// else if (touch_state.y < 320)
|
|
// {
|
|
// // load
|
|
// event.data1 = KEY_F3;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// // movement/menu navigation
|
|
// if (touch_state.x < 100)
|
|
// {
|
|
// if (touch_state.y < 100)
|
|
// {
|
|
// event.data1 = KEY_STRAFE_L;
|
|
// }
|
|
// else if (touch_state.y < 220)
|
|
// {
|
|
// event.data1 = KEY_DOWNARROW;
|
|
// }
|
|
// else
|
|
// {
|
|
// event.data1 = KEY_STRAFE_R;
|
|
// }
|
|
// }
|
|
// else if (touch_state.x < 180)
|
|
// {
|
|
// if (touch_state.y < 160)
|
|
// {
|
|
// event.data1 = KEY_LEFTARROW;
|
|
// }
|
|
// else
|
|
// {
|
|
// event.data1 = KEY_RIGHTARROW;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// event.data1 = KEY_UPARROW;
|
|
// }
|
|
// }
|
|
//
|
|
// D_PostEvent (&event);
|
|
// }
|
|
}
|
|
|
|
void I_StartTic (void)
|
|
{
|
|
I_GetEvent();
|
|
}
|
|
|
|
void I_UpdateNoBlit (void)
|
|
{
|
|
}
|
|
|
|
//
|
|
// I_FinishUpdate
|
|
//
|
|
|
|
void I_FinishUpdate (void)
|
|
{
|
|
#define CMAP256
|
|
int y;
|
|
int x_offset, y_offset, x_offset_end;
|
|
unsigned char *line_in, *line_out;
|
|
|
|
/* Offsets in case FB is bigger than DOOM */
|
|
y_offset = (FB_HEIGHT - SCREENHEIGHT + 1) / 2;
|
|
x_offset = (FB_WIDTH - SCREENWIDTH + 1) / 2;
|
|
x_offset_end = (FB_WIDTH - SCREENWIDTH - x_offset);
|
|
|
|
/* DRAW SCREEN */
|
|
line_in = (unsigned char *) I_VideoBuffer;
|
|
line_out = (unsigned char *) I_VideoBuffer_FB;
|
|
|
|
y = SCREENHEIGHT;
|
|
|
|
#ifdef CMAP256
|
|
while (y--)
|
|
{
|
|
line_out += x_offset;
|
|
memcpy(line_out, line_in, SCREENWIDTH); /* FB_WIDTH is bigger than Doom SCREENWIDTH... */
|
|
line_in += SCREENWIDTH;
|
|
line_out += SCREENWIDTH + x_offset_end;
|
|
}
|
|
|
|
/* Start drawing from y-offset */
|
|
lseek(fd_fb, y_offset * FB_WIDTH, SEEK_SET);
|
|
write(fd_fb, I_VideoBuffer_FB, SCREENHEIGHT * FB_WIDTH); /* draw only portion used by doom + x-offsets */
|
|
#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)
|
|
{
|
|
memcpy (scr, I_VideoBuffer, SCREENWIDTH * SCREENHEIGHT);
|
|
}
|
|
|
|
//
|
|
// I_SetPalette
|
|
//
|
|
#define GFX_RGB565(r, g, b) ((((r & 0xF8) >> 3) << 11) | (((g & 0xFC) >> 2) << 5) | ((b & 0xF8) >> 3))
|
|
#define GFX_RGB565_R(color) ((0xF800 & color) >> 11)
|
|
#define GFX_RGB565_G(color) ((0x07E0 & color) >> 5)
|
|
#define GFX_RGB565_B(color) (0x001F & color)
|
|
|
|
void I_SetPalette (byte* palette)
|
|
{
|
|
int i;
|
|
//col_t* c;
|
|
|
|
//for (i = 0; i < 256; i++)
|
|
//{
|
|
// c = (col_t*)palette;
|
|
|
|
// rgb565_palette[i] = GFX_RGB565(gammatable[usegamma][c->r],
|
|
// gammatable[usegamma][c->g],
|
|
// gammatable[usegamma][c->b]);
|
|
|
|
// palette += 3;
|
|
//}
|
|
|
|
for (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);
|
|
}
|
|
|
|
// Given an RGB value, find the closest matching palette index.
|
|
|
|
int I_GetPaletteIndex (int r, int g, int b)
|
|
{
|
|
int best, best_diff, diff;
|
|
int i;
|
|
col_t color;
|
|
|
|
//printf("I_GetPaletteIndex\n");
|
|
|
|
best = 0;
|
|
best_diff = INT_MAX;
|
|
|
|
for (i = 0; i < 256; ++i)
|
|
{
|
|
color.r = GFX_RGB565_R(rgb565_palette[i]);
|
|
color.g = GFX_RGB565_G(rgb565_palette[i]);
|
|
color.b = GFX_RGB565_B(rgb565_palette[i]);
|
|
|
|
diff = (r - color.r) * (r - color.r)
|
|
+ (g - color.g) * (g - color.g)
|
|
+ (b - color.b) * (b - color.b);
|
|
|
|
if (diff < best_diff)
|
|
{
|
|
best = i;
|
|
best_diff = diff;
|
|
}
|
|
|
|
if (diff == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return best;
|
|
}
|
|
|
|
void I_BeginRead (void)
|
|
{
|
|
}
|
|
|
|
void I_EndRead (void)
|
|
{
|
|
}
|
|
|
|
void I_SetWindowTitle (char *title)
|
|
{
|
|
}
|
|
|
|
void I_GraphicsCheckCommandLine (void)
|
|
{
|
|
}
|
|
|
|
void I_SetGrabMouseCallback (grabmouse_callback_t func)
|
|
{
|
|
}
|
|
|
|
void I_EnableLoadingDisk(void)
|
|
{
|
|
}
|
|
|
|
void I_BindVideoVariables (void)
|
|
{
|
|
}
|
|
|
|
void I_DisplayFPSDots (boolean dots_on)
|
|
{
|
|
}
|
|
|
|
void I_CheckIsScreensaver (void)
|
|
{
|
|
}
|