Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

742 lines (629 sloc) 14.965 kB
#include "wl_def.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>
#include <X11/Xatom.h>
#include <X11/extensions/XShm.h>
byte *gfxbuf = NULL;
byte *disbuf = NULL;
Display *dpy;
myint screen;
Window root, win;
XVisualInfo *vi;
GC gc;
XImage *img;
Colormap cmap;
Atom wmDeleteWindow;
XShmSegmentInfo shminfo;
XColor clr[256];
myint indexmode;
myint shmmode;
static byte cpal[768];
static word spal[768];
static dword ipal[768];
static myint ByteOrder; /* 0 = LSBFirst, 1 = MSBFirst */
static myint NeedSwap;
myint MyDepth;
void GetVisual()
{
XVisualInfo vitemp;
myint i, numVisuals;
vitemp.screen = screen;
vitemp.depth = 8;
vitemp.class = PseudoColor;
vi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask |
VisualClassMask, &vitemp, &numVisuals);
if (vi && (numVisuals > 0)) {
indexmode = 1;
cmap = XCreateColormap(dpy, root, vi->visual, AllocAll);
for (i = 0; i < 256; i++) {
clr[i].pixel = i;
clr[i].flags = DoRed|DoGreen|DoBlue;
}
return;
}
vitemp.depth = 15;
vitemp.class = TrueColor;
vitemp.red_mask = 0x7C00;
vitemp.green_mask = 0x03E0;
vitemp.blue_mask = 0x001F;
vi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask |
VisualClassMask, &vitemp, &numVisuals);
if (vi && (numVisuals > 0)) {
indexmode = 0;
cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
return;
}
vitemp.depth = 16;
vitemp.red_mask = 0xF800;
vitemp.green_mask = 0x07E0;
vitemp.blue_mask = 0x001F;
vi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask |
VisualClassMask, &vitemp, &numVisuals);
if (vi && (numVisuals > 0)) {
indexmode = 0;
cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
return;
}
vitemp.depth = 24;
vitemp.red_mask = 0xFF0000;
vitemp.green_mask = 0x00FF00;
vitemp.blue_mask = 0x0000FF;
vi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask |
VisualClassMask, &vitemp, &numVisuals);
if (vi && (numVisuals > 0)) {
indexmode = 0;
cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
return;
}
vitemp.depth = 32;
vi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask |
VisualClassMask, &vitemp, &numVisuals);
if (vi && (numVisuals > 0)) {
indexmode = 0;
cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
return;
}
Quit("No usable visual found!");
}
myint GetBPP()
{
switch(img->depth) {
case 4:
break;
case 8:
if (img->bits_per_pixel == 8)
return 8;
break;
case 15:
if (img->bits_per_pixel == 16)
return 15;
break;
case 16:
if (img->bits_per_pixel == 16)
return 16;
break;
case 24:
if (img->bits_per_pixel == 24)
return 24;
else
return 32;
break;
case 32:
if (img->bits_per_pixel == 32)
return 32;
break;
}
fprintf(stderr, "Unsupported combination of depth %d and bits per pixel %d...\n", img->depth, img->bits_per_pixel);
fprintf(stderr, "pad = %d, unit = %d, bits = %d, bpl = %d, rgb = %d, depth = %d (%d)\n", img->bitmap_pad, img->bitmap_unit, img->bits_per_pixel, img->bytes_per_line, vi->bits_per_rgb, img->depth, vi->depth);
exit(EXIT_FAILURE);
}
void VL_Startup()
{
XSetWindowAttributes attr;
XSizeHints sizehints;
XGCValues gcvalues;
Pixmap bitmap;
Cursor cursor;
XColor bg = { 0 };
XColor fg = { 0 };
char data[8] = { 0x01 };
char *disp;
myint attrmask;
disp = getenv("DISPLAY");
dpy = XOpenDisplay(disp);
if (dpy == NULL) {
fprintf(stderr, "Unable to open display %s!\n", XDisplayName(disp));
exit(EXIT_FAILURE);
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
GetVisual();
attr.colormap = cmap;
attr.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask
| FocusChangeMask | StructureNotifyMask;
attrmask = CWColormap | CWEventMask;
win = XCreateWindow(dpy, root, 0, 0, vwidth, vheight, 0, CopyFromParent,
InputOutput, vi->visual, attrmask, &attr);
if (win == None) {
Quit("Unable to create window!");
}
gcvalues.foreground = BlackPixel(dpy, screen);
gcvalues.background = WhitePixel(dpy, screen);
gc = XCreateGC(dpy, win, GCForeground | GCBackground, &gcvalues);
sizehints.min_width = vwidth;
sizehints.min_height = vheight;
sizehints.max_width = vwidth;
sizehints.max_height = vheight;
sizehints.base_width = vwidth;
sizehints.base_height = vheight;
sizehints.flags = PMinSize | PMaxSize | PBaseSize;
XSetWMProperties(dpy, win, NULL, NULL, _argv, _argc, &sizehints, None, None);
XStoreName(dpy, win, GAMENAME);
XSetIconName(dpy, win, GAMENAME);
wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, win, &wmDeleteWindow, 1);
bitmap = XCreateBitmapFromData(dpy, win, data, 8, 8);
cursor = XCreatePixmapCursor(dpy, bitmap, bitmap, &fg, &bg, 0, 0);
XDefineCursor(dpy, win, cursor);
shmmode = 0;
if (
#ifndef EMBEDDED
!MS_CheckParm("noshm") &&
#endif
(XShmQueryExtension(dpy) == True)) {
img = XShmCreateImage(dpy, vi->visual, vi->depth, ZPixmap,
NULL, &shminfo, vwidth, vheight);
shminfo.shmid = shmget(IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT | 0777);
shminfo.shmaddr = img->data = shmat(shminfo.shmid, 0, 0);
shminfo.readOnly = False;
disbuf = (byte *)img->data;
if (indexmode)
gfxbuf = disbuf;
else
gfxbuf = malloc(vwidth * vheight * 1);
if (XShmAttach(dpy, &shminfo) == True) {
printf("Using XShm Extension...\n");
shmmode = 1;
shmctl(shminfo.shmid, IPC_RMID, 0);
} else {
printf("Error with XShm...\n");
}
}
if (img == NULL) {
XImage *imgtmp;
char *gb;
printf("Falling back on XImage...\n");
gb = (char *)malloc(320);
imgtmp = XCreateImage(dpy, vi->visual, vi->depth, ZPixmap, 0,
gb, 16, 1, 8, 16*4);
if (gfxbuf == NULL)
gfxbuf = malloc(vwidth * vheight * 1);
if (indexmode)
disbuf = gfxbuf;
else
disbuf = malloc(vwidth * vheight * (imgtmp->bits_per_pixel / 8));
img = XCreateImage(dpy, vi->visual, vi->depth, ZPixmap, 0,
(char *)disbuf, vwidth, vheight, 8, 0 * (imgtmp->bits_per_pixel / 8));
if (img == NULL) {
Quit("XCreateImage returned NULL");
}
XInitImage(img);
XDestroyImage(imgtmp);
}
MyDepth = GetBPP();
#if BYTE_ORDER == BIG_ENDIAN
ByteOrder = 1;
#else
ByteOrder = 0;
#endif
NeedSwap = (ByteOrder != img->byte_order);
XMapRaised(dpy, win);
}
void VL_Shutdown()
{
if ( !shmmode && (gfxbuf != NULL) ) {
free(gfxbuf);
gfxbuf = NULL;
}
if ( shmmode && !indexmode && (gfxbuf != NULL) ) {
free(gfxbuf);
gfxbuf = NULL;
}
if (shmmode) {
XShmDetach(dpy, &shminfo);
XDestroyImage(img);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
} else if ( (indexmode == 0) && (disbuf != NULL) ) {
free(disbuf);
disbuf = NULL;
}
}
void VL_WaitVBL(myint vbls)
{
/* hack - but it works for me */
long last = get_TimeCount() + vbls;
while (last > get_TimeCount()) ;
}
void VW_UpdateScreen()
{
dword *ptri;
word *ptrs;
byte *ptrb;
int size;
myint i;
#if 0
for (i = 0; i < 64; i++) {
gfxbuf[i] = i;
gfxbuf[i*128 + 1] = i;
gfxbuf[i*128 + 2] = i;
gfxbuf[i*128 + 3] = i;
gfxbuf[i*128 + 4] = i + 0x40;
gfxbuf[i*128 + 5] = i + 0x40;
gfxbuf[i*128 + 6] = i + 0x40;
gfxbuf[i*128 + 7] = i + 0x40;
gfxbuf[i*128 + 8] = i + 0x80;
gfxbuf[i*128 + 9] = i + 0x80;
gfxbuf[i*128 + 10] = i + 0x80;
gfxbuf[i*128 + 11] = i + 0x80;
gfxbuf[i*128 + 12] = i + 0xc0;
gfxbuf[i*128 + 13] = i + 0xc0;
gfxbuf[i*128 + 14] = i + 0xc0;
gfxbuf[i*128 + 15] = i + 0xc0;
}
#endif
#if 0
for (i = 0; i < 128 * 64; i++) {
gfxbuf[i] = 0x1f - pal4bit[gfxbuf[i]];
}
#endif
size = vwidth * vheight;
if (indexmode == 0) {
switch(MyDepth) {
case 15:
case 16:
ptrs = (word *)disbuf;
for (i = 0; i < size; i++) {
*ptrs = spal[gfxbuf[i]];
ptrs++;
}
break;
case 24: /* Endian Safe? Untested. */
ptrb = disbuf;
for (i = 0; i < size; i++) {
*ptrb = cpal[gfxbuf[i]*3+2] << 2; ptrb++;
*ptrb = cpal[gfxbuf[i]*3+1] << 2; ptrb++;
*ptrb = cpal[gfxbuf[i]*3+0] << 2; ptrb++;
}
break;
case 32:
ptri = (dword *)disbuf;
for (i = 0; i < size; i++) {
*ptri = ipal[gfxbuf[i]];
ptri++;
}
break;
default:
break;
/* ... */
}
}
if (shmmode)
XShmPutImage(dpy, win, gc, img, 0, 0, 0, 0, vwidth, vheight, False);
else
XPutImage(dpy, win, gc, img, 0, 0, 0, 0, vwidth, vheight);
}
void keyboard_handler(myint code, myint press);
static myint XKeysymToScancode(KeySym keysym);
static void HandleXEvents()
{
XEvent event;
if (XPending(dpy)) {
do {
XNextEvent(dpy, &event);
switch(event.type) {
case KeyPress:
keyboard_handler(XKeysymToScancode(XKeycodeToKeysym(dpy, event.xkey.keycode, 0)), 1);
break;
case KeyRelease:
keyboard_handler(XKeysymToScancode(XKeycodeToKeysym(dpy, event.xkey.keycode, 0)), 0);
break;
case Expose:
VW_UpdateScreen();
break;
case ClientMessage:
if (event.xclient.data.l[0] == wmDeleteWindow)
Quit(NULL);
break;
case ConfigureNotify:
break;
case FocusIn:
break;
case FocusOut:
break;
default:
break;
}
} while (XPending(dpy));
}
}
/* ======================================================================== */
/*
=================
=
= VL_SetPalette
=
=================
*/
void VL_SetPalette(const byte *palette)
{
myint i;
VL_WaitVBL(1);
if (indexmode) {
for (i = 0; i < 256; i++) {
clr[i].red = palette[i*3+0] << 10;
clr[i].green = palette[i*3+1] << 10;
clr[i].blue = palette[i*3+2] << 10;
}
XStoreColors(dpy, cmap, clr, 256);
} else {
memcpy(cpal, palette, 768);
for (i = 0; i < 256; i++) {
/* TODO: this should really use the visual for creating the pixel */
switch(MyDepth) {
case 8:
break;
case 15: /* Endian Safe? Untested. */
spal[i] = ((palette[i*3+0] >> 1) << 10) | ((palette[i*3+1] >> 1) << 5) | ((palette[i*3+2] >> 1) << 0);
if (NeedSwap)
spal[i] = SwapInt16(spal[i]);
break;
case 16:
spal[i] = ((palette[i*3+0] >> 1) << 11) | ((palette[i*3+1] >> 0) << 5) | ((palette[i*3+2] >> 1) << 0);
if (NeedSwap)
spal[i] = SwapInt16(spal[i]);
break;
case 32:
ipal[i] = (palette[i*3+0] << 18) | (palette[i*3+1] << 10) | (palette[i*3+2] << 2);
if (NeedSwap)
ipal[i] = SwapInt32(ipal[i]);
break;
}
}
VW_UpdateScreen();
}
}
/*
=================
=
= VL_GetPalette
=
=================
*/
void VL_GetPalette(byte *palette)
{
myint i;
if (indexmode) {
for (i = 0; i < 256; i++) {
palette[i*3+0] = clr[i].red >> 10;
palette[i*3+1] = clr[i].green >> 10;
palette[i*3+2] = clr[i].blue >> 10;
}
} else {
memcpy(palette, cpal, 768);
}
}
myint main(myint argc, char *argv[])
{
#ifdef EMBEDDED
vwidth = 128;
vheight = 96;
#else
vwidth = 320;
vheight = 200;
#endif
return WolfMain(argc, argv);
}
/*
==========================
=
= Quit
=
==========================
*/
void DisplayTextSplash(const byte *text, myint l);
void Quit(const char *error)
{
memptr screen = NULL;
myint l = 0;
#ifdef ENABLE_QUITMSG
if (!error || !*error) {
CA_CacheGrChunk(ORDERSCREEN);
screen = grsegs[ORDERSCREEN];
l = 24;
WriteConfig();
} else if (error) {
CA_CacheGrChunk(ERRORSCREEN);
screen = grsegs[ERRORSCREEN];
l = 7;
}
#endif
ShutdownId();
#ifndef EMBEDDED
if (screen) {
DisplayTextSplash(screen, l);
}
#endif
if (error && *error) {
fprintf(stderr, "Quit: %s\n", error);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
static myint XKeysymToScancode(KeySym keysym)
{
switch (keysym) {
case XK_1:
return sc_1;
case XK_2:
return sc_2;
case XK_3:
return sc_3;
case XK_4:
return sc_4;
case XK_5:
return sc_5;
case XK_6:
return sc_6;
case XK_a:
return sc_A;
case XK_b:
return sc_B;
case XK_c:
return sc_C;
case XK_d:
return sc_D;
case XK_g:
return sc_G;
case XK_h:
return sc_H;
case XK_i:
return sc_I;
case XK_l:
return sc_L;
case XK_m:
return sc_M;
case XK_n:
return sc_N;
case XK_q:
return sc_Q;
case XK_s:
return sc_S;
case XK_t:
return sc_T;
case XK_y:
return sc_Y;
case XK_F1:
return sc_F1;
case XK_F2:
return sc_F2;
case XK_F3:
return sc_F3;
case XK_F10:
return sc_F10;
case XK_F11:
return sc_F11;
case XK_F12:
return sc_F12;
case XK_Left:
case XK_KP_Left:
return sc_LeftArrow;
case XK_Right:
case XK_KP_Right:
return sc_RightArrow;
case XK_Up:
case XK_KP_Up:
return sc_UpArrow;
case XK_Down:
case XK_KP_Down:
return sc_DownArrow;
case XK_Control_L:
case XK_Control_R:
return sc_Control;
case XK_Alt_L:
case XK_Alt_R:
return sc_Alt;
case XK_Shift_L:
return sc_LShift;
case XK_Shift_R:
return sc_RShift;
case XK_Escape:
return sc_Escape;
case XK_space:
case XK_KP_Space:
return sc_Space;
case XK_KP_Enter:
case XK_Return:
return sc_Enter;
case XK_Tab:
return sc_Tab;
case XK_BackSpace:
return sc_BackSpace;
case XK_Pause:
return 0xE1;
default:
printf("unknown: %s\n", XKeysymToString(keysym));
return sc_None;
}
}
byte IN_MouseButtons()
{
return 0;
}
void IN_GetMouseDelta(myint *dx, myint *dy)
{
}
#ifdef ENABLE_JOYSTICK
/*
===================
=
= IN_JoyButtons
=
===================
*/
byte IN_JoyButtons()
{
return 0;
}
///////////////////////////////////////////////////////////////////////////
//
// IN_GetJoyAbs() - Reads the absolute position of the specified joystick
//
///////////////////////////////////////////////////////////////////////////
void IN_GetJoyAbs(word joy,word *xp,word *yp)
{
*xp = 0;
*yp = 0;
}
///////////////////////////////////////////////////////////////////////////
//
// INL_GetJoyDelta() - Returns the relative movement of the specified
// joystick (from +/-127)
//
///////////////////////////////////////////////////////////////////////////
void INL_GetJoyDelta(word joy,myint *dx,myint *dy)
{
*dx = 0;
*dy = 0;
}
///////////////////////////////////////////////////////////////////////////
//
// INL_GetJoyButtons() - Returns the button status of the specified
// joystick
//
///////////////////////////////////////////////////////////////////////////
word INL_GetJoyButtons(word joy)
{
return 0;
}
///////////////////////////////////////////////////////////////////////////
//
// IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
// to set up scaling values
//
///////////////////////////////////////////////////////////////////////////
void IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)
{
}
#endif
void INL_Update()
{
HandleXEvents();
}
Jump to Line
Something went wrong with that request. Please try again.