425 lines
9.6 KiB
C
425 lines
9.6 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 macOS, SDL2.
|
|
// Replaces the X11/MIT-SHM implementation.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static const char
|
|
rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $";
|
|
|
|
#define SDL_MAIN_HANDLED
|
|
#include <SDL.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdarg.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <signal.h>
|
|
|
|
#include "doomstat.h"
|
|
#include "i_system.h"
|
|
#include "v_video.h"
|
|
#include "w_wad.h"
|
|
#include "z_zone.h"
|
|
#include "m_argv.h"
|
|
#include "m_misc.h"
|
|
#include "d_main.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
|
|
static SDL_Window* sdl_window;
|
|
static SDL_Renderer* sdl_renderer;
|
|
static SDL_Texture* sdl_texture;
|
|
|
|
// Framebuffer: screens[0] converted to 32bpp before upload.
|
|
static Uint32 framebuffer[SCREENWIDTH * SCREENHEIGHT];
|
|
|
|
// 8-bit palette (with gamma applied) expanded to ARGB8888.
|
|
static Uint32 argb_palette[256];
|
|
|
|
// Fake mouse handling.
|
|
boolean grabMouse;
|
|
|
|
#define MIN_WINDOW_WIDTH 640
|
|
#define MIN_WINDOW_HEIGHT 480
|
|
|
|
|
|
//
|
|
// Translates an SDL_Keycode to a DOOM key value.
|
|
//
|
|
int xlatekey(SDL_Keycode sym)
|
|
{
|
|
int rc = sym;
|
|
|
|
switch (sym)
|
|
{
|
|
case SDLK_LEFT: rc = KEY_LEFTARROW; break;
|
|
case SDLK_RIGHT: rc = KEY_RIGHTARROW; break;
|
|
case SDLK_DOWN: rc = KEY_DOWNARROW; break;
|
|
case SDLK_UP: rc = KEY_UPARROW; break;
|
|
case SDLK_ESCAPE: rc = KEY_ESCAPE; break;
|
|
case SDLK_RETURN: rc = KEY_ENTER; break;
|
|
case SDLK_TAB: rc = KEY_TAB; break;
|
|
case SDLK_F1: rc = KEY_F1; break;
|
|
case SDLK_F2: rc = KEY_F2; break;
|
|
case SDLK_F3: rc = KEY_F3; break;
|
|
case SDLK_F4: rc = KEY_F4; break;
|
|
case SDLK_F5: rc = KEY_F5; break;
|
|
case SDLK_F6: rc = KEY_F6; break;
|
|
case SDLK_F7: rc = KEY_F7; break;
|
|
case SDLK_F8: rc = KEY_F8; break;
|
|
case SDLK_F9: rc = KEY_F9; break;
|
|
case SDLK_F10: rc = KEY_F10; break;
|
|
case SDLK_F11: rc = KEY_F11; break;
|
|
case SDLK_F12: rc = KEY_F12; break;
|
|
|
|
case SDLK_BACKSPACE:
|
|
case SDLK_DELETE: rc = KEY_BACKSPACE; break;
|
|
|
|
case SDLK_PAUSE: rc = KEY_PAUSE; break;
|
|
|
|
case SDLK_KP_EQUALS:
|
|
case SDLK_EQUALS: rc = KEY_EQUALS; break;
|
|
|
|
case SDLK_KP_MINUS:
|
|
case SDLK_MINUS: rc = KEY_MINUS; break;
|
|
|
|
case SDLK_LSHIFT:
|
|
case SDLK_RSHIFT: rc = KEY_RSHIFT; break;
|
|
|
|
case SDLK_LCTRL:
|
|
case SDLK_RCTRL: rc = KEY_RCTRL; break;
|
|
|
|
case SDLK_LALT:
|
|
case SDLK_RALT: rc = KEY_RALT; break;
|
|
|
|
default:
|
|
// SDL_Keycode values for printable keys are ASCII.
|
|
if (rc >= 'A' && rc <= 'Z')
|
|
rc = rc - 'A' + 'a';
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
void I_ShutdownGraphics(void)
|
|
{
|
|
if (sdl_texture)
|
|
SDL_DestroyTexture(sdl_texture);
|
|
if (sdl_renderer)
|
|
SDL_DestroyRenderer(sdl_renderer);
|
|
if (sdl_window)
|
|
SDL_DestroyWindow(sdl_window);
|
|
sdl_texture = NULL;
|
|
sdl_renderer = NULL;
|
|
sdl_window = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// I_StartFrame
|
|
//
|
|
void I_StartFrame (void)
|
|
{
|
|
// er?
|
|
}
|
|
|
|
|
|
//
|
|
// Mouse button bitmask in DOOM order:
|
|
// bit0 = left, bit1 = middle, bit2 = right.
|
|
//
|
|
static int mousebuttons(void)
|
|
{
|
|
Uint32 state = SDL_GetMouseState(NULL, NULL);
|
|
int bits = 0;
|
|
|
|
if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) bits |= 1;
|
|
if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) bits |= 2;
|
|
if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) bits |= 4;
|
|
|
|
return bits;
|
|
}
|
|
|
|
void I_GetEvent(void)
|
|
{
|
|
SDL_Event sdl_event;
|
|
event_t event;
|
|
|
|
while (SDL_PollEvent(&sdl_event))
|
|
{
|
|
switch (sdl_event.type)
|
|
{
|
|
case SDL_KEYDOWN:
|
|
event.type = ev_keydown;
|
|
event.data1 = xlatekey(sdl_event.key.keysym.sym);
|
|
D_PostEvent(&event);
|
|
break;
|
|
|
|
case SDL_KEYUP:
|
|
event.type = ev_keyup;
|
|
event.data1 = xlatekey(sdl_event.key.keysym.sym);
|
|
D_PostEvent(&event);
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
case SDL_MOUSEBUTTONUP:
|
|
event.type = ev_mouse;
|
|
event.data1 = mousebuttons();
|
|
event.data2 = event.data3 = 0;
|
|
D_PostEvent(&event);
|
|
break;
|
|
|
|
case SDL_MOUSEMOTION:
|
|
event.type = ev_mouse;
|
|
event.data1 = mousebuttons();
|
|
event.data2 = sdl_event.motion.xrel << 2;
|
|
event.data3 = -sdl_event.motion.yrel << 2;
|
|
if (event.data2 || event.data3 || grabMouse)
|
|
D_PostEvent(&event);
|
|
break;
|
|
|
|
case SDL_WINDOWEVENT:
|
|
if (sdl_event.window.event == SDL_WINDOWEVENT_RESIZED
|
|
&& !(SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_FULLSCREEN))
|
|
{
|
|
window_width = sdl_event.window.data1;
|
|
window_height = sdl_event.window.data2;
|
|
}
|
|
break;
|
|
|
|
case SDL_QUIT:
|
|
I_Quit();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// I_StartTic
|
|
//
|
|
void I_StartTic (void)
|
|
{
|
|
I_GetEvent();
|
|
}
|
|
|
|
|
|
//
|
|
// I_UpdateNoBlit
|
|
//
|
|
void I_UpdateNoBlit (void)
|
|
{
|
|
// what is this?
|
|
}
|
|
|
|
//
|
|
// I_FinishUpdate
|
|
//
|
|
void I_FinishUpdate (void)
|
|
{
|
|
|
|
static int lasttic;
|
|
int tics;
|
|
int i;
|
|
int output_width;
|
|
int output_height;
|
|
SDL_Rect dest;
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
// expand the 8-bit palettized screen to the 32-bit framebuffer
|
|
{
|
|
const byte* src = screens[0];
|
|
Uint32* dst = framebuffer;
|
|
int count = SCREENWIDTH * SCREENHEIGHT;
|
|
|
|
while (count--)
|
|
*dst++ = argb_palette[*src++];
|
|
}
|
|
|
|
SDL_UpdateTexture(sdl_texture, NULL, framebuffer, SCREENWIDTH * sizeof(Uint32));
|
|
|
|
if (SDL_GetRendererOutputSize(sdl_renderer, &output_width, &output_height) != 0)
|
|
SDL_GetWindowSize(sdl_window, &output_width, &output_height);
|
|
|
|
if (output_width * 3 > output_height * 4)
|
|
{
|
|
dest.h = output_height;
|
|
dest.w = output_height * 4 / 3;
|
|
}
|
|
else
|
|
{
|
|
dest.w = output_width;
|
|
dest.h = output_width * 3 / 4;
|
|
}
|
|
dest.x = (output_width - dest.w) / 2;
|
|
dest.y = (output_height - dest.h) / 2;
|
|
|
|
SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(sdl_renderer);
|
|
SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, &dest);
|
|
SDL_RenderPresent(sdl_renderer);
|
|
}
|
|
|
|
|
|
//
|
|
// I_ReadScreen
|
|
//
|
|
void I_ReadScreen (byte* scr)
|
|
{
|
|
memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
|
|
}
|
|
|
|
|
|
//
|
|
// I_SetPalette
|
|
//
|
|
void I_SetPalette (byte* palette)
|
|
{
|
|
int i;
|
|
int c;
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
c = gammatable[usegamma][*palette++];
|
|
argb_palette[i] = 0xff000000 | (c<<16);
|
|
c = gammatable[usegamma][*palette++];
|
|
argb_palette[i] |= (c<<8);
|
|
c = gammatable[usegamma][*palette++];
|
|
argb_palette[i] |= c;
|
|
}
|
|
}
|
|
|
|
|
|
void I_InitGraphics(void)
|
|
{
|
|
Uint32 flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
|
|
SDL_Rect usable_bounds;
|
|
int start_width;
|
|
int start_height;
|
|
|
|
static int firsttime = 1;
|
|
if (!firsttime)
|
|
return;
|
|
firsttime = 0;
|
|
|
|
signal(SIGINT, (void (*)(int)) I_Quit);
|
|
|
|
if (M_CheckParm("-fullscreen"))
|
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
// check if the user wants to grab the mouse
|
|
grabMouse = !!M_CheckParm("-grabmouse");
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE) != 0)
|
|
I_Error("SDL_Init() failed: %s", SDL_GetError());
|
|
|
|
// Normalize saved dimensions before applying temporary command-line presets.
|
|
if (window_width < MIN_WINDOW_WIDTH)
|
|
window_width = MIN_WINDOW_WIDTH;
|
|
if (window_height < MIN_WINDOW_HEIGHT)
|
|
window_height = MIN_WINDOW_HEIGHT;
|
|
if (SDL_GetDisplayUsableBounds(0, &usable_bounds) == 0)
|
|
{
|
|
if (window_width > usable_bounds.w)
|
|
window_width = usable_bounds.w;
|
|
if (window_height > usable_bounds.h)
|
|
window_height = usable_bounds.h;
|
|
}
|
|
|
|
start_width = window_width;
|
|
start_height = window_height;
|
|
|
|
if (M_CheckParm("-2"))
|
|
{
|
|
start_width = 640;
|
|
start_height = 480;
|
|
}
|
|
if (M_CheckParm("-3"))
|
|
{
|
|
start_width = 960;
|
|
start_height = 720;
|
|
}
|
|
if (M_CheckParm("-4"))
|
|
{
|
|
start_width = 1280;
|
|
start_height = 960;
|
|
}
|
|
|
|
sdl_window = SDL_CreateWindow("DOOM",
|
|
SDL_WINDOWPOS_CENTERED,
|
|
SDL_WINDOWPOS_CENTERED,
|
|
start_width,
|
|
start_height,
|
|
flags);
|
|
if (!sdl_window)
|
|
I_Error("SDL_CreateWindow() failed: %s", SDL_GetError());
|
|
|
|
SDL_SetWindowMinimumSize(sdl_window, MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
|
|
|
|
sdl_renderer = SDL_CreateRenderer(sdl_window, -1,
|
|
SDL_RENDERER_ACCELERATED);
|
|
if (!sdl_renderer)
|
|
I_Error("SDL_CreateRenderer() failed: %s", SDL_GetError());
|
|
|
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
|
|
|
|
sdl_texture = SDL_CreateTexture(sdl_renderer,
|
|
SDL_PIXELFORMAT_ARGB8888,
|
|
SDL_TEXTUREACCESS_STREAMING,
|
|
SCREENWIDTH,
|
|
SCREENHEIGHT);
|
|
if (!sdl_texture)
|
|
I_Error("SDL_CreateTexture() failed: %s", SDL_GetError());
|
|
|
|
if (SDL_SetTextureScaleMode(sdl_texture, SDL_ScaleModeNearest) != 0)
|
|
I_Error("SDL_SetTextureScaleMode() failed: %s", SDL_GetError());
|
|
|
|
if (grabMouse)
|
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
|
|
|
// screens[0] was already allocated by V_Init.
|
|
// Fill the palette with something sane until I_SetPalette is called.
|
|
I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE));
|
|
|
|
}
|