aboutsummaryrefslogtreecommitdiffstats
path: root/QW/client
diff options
context:
space:
mode:
Diffstat (limited to 'QW/client')
-rw-r--r--QW/client/cvar.h6
-rw-r--r--QW/client/snd_dma.c12
-rw-r--r--QW/client/snd_sdl.c215
-rw-r--r--QW/client/sound.h7
-rw-r--r--QW/client/vid_x.c136
5 files changed, 354 insertions, 22 deletions
diff --git a/QW/client/cvar.h b/QW/client/cvar.h
index bc72791..58b4e41 100644
--- a/QW/client/cvar.h
+++ b/QW/client/cvar.h
@@ -53,6 +53,12 @@ Cvars are restricted from having the same names as commands to keep this
interface from being ambiguous.
*/
+/* for sdl */
+#if defined(USE_SDL2)
+#define CVAR_NONE 0
+#endif
+/* sdl end */
+
typedef struct cvar_s
{
char *name;
diff --git a/QW/client/snd_dma.c b/QW/client/snd_dma.c
index 4168315..8554836 100644
--- a/QW/client/snd_dma.c
+++ b/QW/client/snd_dma.c
@@ -77,6 +77,11 @@ cvar_t volume = {"volume", "0.7", true};
cvar_t nosound = {"nosound", "0"};
cvar_t precache = {"precache", "1"};
cvar_t loadas8bit = {"loadas8bit", "0"};
+/* for sdl */
+#if defined(USE_SDL2)
+cvar_t sndspeed = {"sndspeed", "11025", CVAR_NONE};
+cvar_t snd_mixspeed = {"snd_mixspeed", "44100", CVAR_NONE};
+#endif
cvar_t bgmbuffer = {"bgmbuffer", "4096"};
cvar_t ambient_level = {"ambient_level", "0.3"};
cvar_t ambient_fade = {"ambient_fade", "100"};
@@ -146,8 +151,13 @@ void S_Startup (void)
if (!fakedma)
{
+#if defined(USE_SDL2)
+ /* Since I borrowed a lot of the SDL2 code from Quakespasm, I
+ found this to be the easiest way to retrofit it: */
+ rc = SNDDMA_Init(&sn);
+#else
rc = SNDDMA_Init();
-
+#endif
if (!rc)
{
#ifndef _WIN32
diff --git a/QW/client/snd_sdl.c b/QW/client/snd_sdl.c
new file mode 100644
index 0000000..a65758c
--- /dev/null
+++ b/QW/client/snd_sdl.c
@@ -0,0 +1,215 @@
+/*
+ * snd_sdl.c - SDL audio driver for Hexen II: Hammer of Thyrion (uHexen2)
+ * based on implementations found in the quakeforge and ioquake3 projects.
+ *
+ * Copyright (C) 1999-2005 Id Software, Inc.
+ * Copyright (C) 2005-2012 O.Sezer <sezero@users.sourceforge.net>
+ * Copyright (C) 2010-2014 QuakeSpasm developers
+ *
+ * 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 lat er 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "quakedef.h"
+
+#if defined(SDL_FRAMEWORK) || defined(NO_SDL_CONFIG)
+#if defined(USE_SDL2)
+#include <SDL2/SDL.h>
+#else
+#include <SDL/SDL.h>
+#endif
+#else
+#include "SDL.h"
+#endif
+
+static int buffersize;
+
+
+static void SDLCALL paint_audio (void *unused, Uint8 *stream, int len)
+{
+ int pos, tobufend;
+ int len1, len2;
+
+ if (!shm)
+ { /* shouldn't happen, but just in case */
+ memset(stream, 0, len);
+ return;
+ }
+
+ pos = (shm->samplepos * (shm->samplebits / 8));
+ if (pos >= buffersize)
+ shm->samplepos = pos = 0;
+
+ tobufend = buffersize - pos; /* bytes to buffer's end. */
+ len1 = len;
+ len2 = 0;
+
+ if (len1 > tobufend)
+ {
+ len1 = tobufend;
+ len2 = len - len1;
+ }
+
+ memcpy(stream, shm->buffer + pos, len1);
+
+ if (len2 <= 0)
+ {
+ shm->samplepos += (len1 / (shm->samplebits / 8));
+ }
+ else
+ { /* wraparound? */
+ memcpy(stream + len1, shm->buffer, len2);
+ shm->samplepos = (len2 / (shm->samplebits / 8));
+ }
+
+ if (shm->samplepos >= buffersize)
+ shm->samplepos = 0;
+}
+
+qboolean SNDDMA_Init (dma_t *dma)
+{
+ SDL_AudioSpec desired;
+ int tmp, val;
+ char drivername[128];
+
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
+ {
+ Con_Printf("Couldn't init SDL audio: %s\n", SDL_GetError());
+ return false;
+ }
+
+ /* Set up the desired format */
+/* desired.freq = snd_mixspeed.value;*/
+ desired.freq = 44100;
+ desired.format = (loadas8bit.value) ? AUDIO_U8 : AUDIO_S16SYS;
+ desired.channels = 2; /* = desired_channels; */
+ if (desired.freq <= 11025)
+ desired.samples = 256;
+ else if (desired.freq <= 22050)
+ desired.samples = 512;
+ else if (desired.freq <= 44100)
+ desired.samples = 1024;
+ else if (desired.freq <= 56000)
+ desired.samples = 2048; /* for 48 kHz */
+ else
+ desired.samples = 4096; /* for 96 kHz */
+ desired.callback = paint_audio;
+ desired.userdata = NULL;
+
+ /* Open the audio device */
+ if (SDL_OpenAudio(&desired, NULL) == -1)
+ {
+ Con_Printf("Couldn't open SDL audio: %s\n", SDL_GetError());
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ return false;
+ }
+ /* i think i'm just zeroing dma mem here */
+ memset ((void *) dma, 0, sizeof(dma_t));
+ /*shm = dma;*/
+ shm = &sn;
+
+ /* Fill the audio DMA information block */
+ /* Since we passed NULL as the 'obtained' spec to SDL_OpenAudio(),
+ * SDL will convert to hardware format for us if needed, hence we
+ * directly use the desired values here. */
+ shm->samplebits = (desired.format & 0xFF); /* first byte of format is bits */
+/* shm->signed8 = (desired.format == AUDIO_S8);*/
+ shm->speed = desired.freq;
+ shm->channels = desired.channels;
+ tmp = (desired.samples * desired.channels) * 10;
+ if (tmp & (tmp - 1))
+ { /* make it a power of two */
+ val = 1;
+ while (val < tmp)
+ val <<= 1;
+
+ tmp = val;
+ }
+ shm->samples = tmp;
+ shm->samplepos = 0;
+ shm->submission_chunk = 1;
+
+ Con_Printf ("SDL audio spec : %d Hz, %d samples, %d channels\n",
+ desired.freq, desired.samples, desired.channels);
+#if defined(USE_SDL2)
+ {
+ const char *driver = SDL_GetCurrentAudioDriver();
+ const char *device = SDL_GetAudioDeviceName(0, SDL_FALSE);
+ snprintf(drivername, sizeof(drivername), "%s - %s",
+ driver != NULL ? driver : "(UNKNOWN)",
+ device != NULL ? device : "(UNKNOWN)");
+ }
+#else
+ if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL)
+ strcpy(drivername, "(UNKNOWN)");
+#endif
+ buffersize = shm->samples * (shm->samplebits / 8);
+ Con_Printf ("SDL audio driver: %s, %d bytes buffer\n", drivername, buffersize);
+
+ shm->buffer = (unsigned char *) calloc (1, buffersize);
+// if (!shm->buffer)
+ if (!shm->buffer || shm->buffer == (unsigned char *)-1)
+ {
+ SDL_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ shm = NULL;
+ Con_Printf ("Failed allocating memory for SDL audio\n");
+ return false;
+ }
+
+ SDL_PauseAudio(0);
+
+ return true;
+}
+
+int SNDDMA_GetDMAPos (void)
+{
+ return shm->samplepos;
+}
+
+void SNDDMA_Shutdown (void)
+{
+ if (shm)
+ {
+ Con_Printf ("Shutting down SDL sound\n");
+ SDL_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ if (shm->buffer)
+ free (shm->buffer);
+ shm->buffer = NULL;
+ shm = NULL;
+ }
+}
+
+void SNDDMA_LockBuffer (void)
+{
+ SDL_LockAudio ();
+}
+
+void SNDDMA_Submit (void)
+{
+ SDL_UnlockAudio();
+}
+
+void SNDDMA_BlockSound (void)
+{
+ SDL_PauseAudio(1);
+}
+
+void SNDDMA_UnblockSound (void)
+{
+ SDL_PauseAudio(0);
+}
+
diff --git a/QW/client/sound.h b/QW/client/sound.h
index 941e620..c1e90fa 100644
--- a/QW/client/sound.h
+++ b/QW/client/sound.h
@@ -111,9 +111,14 @@ channel_t *SND_PickChannel(int entnum, int entchannel);
// spatializes a channel
void SND_Spatialize(channel_t *ch);
+#if defined(USE_SDL2)
+/* Probably the easiest way to retrofit quakespasm's SDL2 audio code into
+ Id Quake. */
+qboolean SNDDMA_Init(dma_t *dma);
+#else
// initializes cycling through a DMA buffer and returns information on it
qboolean SNDDMA_Init(void);
-
+#endif
// gets the current DMA position
int SNDDMA_GetDMAPos(void);
diff --git a/QW/client/vid_x.c b/QW/client/vid_x.c
index 891fb3b..c96545c 100644
--- a/QW/client/vid_x.c
+++ b/QW/client/vid_x.c
@@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define _BSD
-typedef unsigned short PIXEL;
#include <ctype.h>
#include <sys/time.h>
@@ -50,7 +49,6 @@ float old_windowed_mouse;
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
byte *VGA_pagebase;
-
qboolean mouse_avail;
int mouse_buttons=3;
int mouse_oldbuttonstate;
@@ -112,7 +110,10 @@ void (*vid_menudrawfn)(void);
void (*vid_menukeyfn)(int key);
void VID_MenuKey (int key);
-static PIXEL st2d_8to16table[256];
+typedef unsigned short PIXEL16;
+typedef unsigned long PIXEL24;
+static PIXEL16 st2d_8to16table[256];
+static PIXEL24 st2d_8to24table[256];
static int shiftmask_fl=0;
static long r_shift,g_shift,b_shift;
static unsigned long r_mask,g_mask,b_mask;
@@ -129,9 +130,36 @@ void shiftmask_init()
shiftmask_fl=1;
}
-PIXEL xlib_rgb(int r,int g,int b)
+PIXEL16 xlib_rgb16(int r,int g,int b)
+{
+ PIXEL16 p;
+ if(shiftmask_fl==0) shiftmask_init();
+ p=0;
+
+ if(r_shift>0) {
+ p=(r<<(r_shift))&r_mask;
+ } else if(r_shift<0) {
+ p=(r>>(-r_shift))&r_mask;
+ } else p|=(r&r_mask);
+
+ if(g_shift>0) {
+ p|=(g<<(g_shift))&g_mask;
+ } else if(g_shift<0) {
+ p|=(g>>(-g_shift))&g_mask;
+ } else p|=(g&g_mask);
+
+ if(b_shift>0) {
+ p|=(b<<(b_shift))&b_mask;
+ } else if(b_shift<0) {
+ p|=(b>>(-b_shift))&b_mask;
+ } else p|=(b&b_mask);
+
+ return p;
+}
+
+PIXEL24 xlib_rgb24(int r,int g,int b)
{
- PIXEL p;
+ PIXEL24 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
@@ -160,16 +188,71 @@ void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
- PIXEL *dest;
+ PIXEL16 *dest;
+ register int count, n;
if( (x<0)||(y<0) )return;
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
- dest = (PIXEL*)src;
- for(xi = (x+width-1); xi >= x; xi--) {
- dest[xi] = st2d_8to16table[src[xi]];
+
+ // Duff's Device
+ count = width;
+ n = (count + 7) / 8;
+ dest = ((PIXEL16 *)src) + x+width - 1;
+ src += x+width - 1;
+
+ switch (count % 8) {
+ case 0: do { *dest-- = st2d_8to16table[*src--];
+ case 7: *dest-- = st2d_8to16table[*src--];
+ case 6: *dest-- = st2d_8to16table[*src--];
+ case 5: *dest-- = st2d_8to16table[*src--];
+ case 4: *dest-- = st2d_8to16table[*src--];
+ case 3: *dest-- = st2d_8to16table[*src--];
+ case 2: *dest-- = st2d_8to16table[*src--];
+ case 1: *dest-- = st2d_8to16table[*src--];
+ } while (--n > 0);
}
+
+// for(xi = (x+width-1); xi >= x; xi--) {
+// dest[xi] = st2d_8to16table[src[xi]];
+// }
+ }
+}
+
+void st3_fixup( XImage *framebuf, int x, int y, int width, int height)
+{
+ int xi,yi;
+ unsigned char *src;
+ PIXEL24 *dest;
+ register int count, n;
+
+ if( (x<0)||(y<0) )return;
+
+ for (yi = y; yi < (y+height); yi++) {
+ src = &framebuf->data [yi * framebuf->bytes_per_line];
+
+ // Duff's Device
+ count = width;
+ n = (count + 7) / 8;
+ dest = ((PIXEL24 *)src) + x+width - 1;
+ src += x+width - 1;
+
+ switch (count % 8) {
+ case 0: do { *dest-- = st2d_8to24table[*src--];
+ case 7: *dest-- = st2d_8to24table[*src--];
+ case 6: *dest-- = st2d_8to24table[*src--];
+ case 5: *dest-- = st2d_8to24table[*src--];
+ case 4: *dest-- = st2d_8to24table[*src--];
+ case 3: *dest-- = st2d_8to24table[*src--];
+ case 2: *dest-- = st2d_8to24table[*src--];
+ case 1: *dest-- = st2d_8to24table[*src--];
+ } while (--n > 0);
+ }
+
+// for(xi = (x+width-1); xi >= x; xi--) {
+// dest[xi] = st2d_8to16table[src[xi]];
+// }
}
}
@@ -367,8 +450,6 @@ void VID_Init (unsigned char *palette)
XVisualInfo template;
int num_visuals;
int template_mask;
-
- S_Init();
ignorenext=0;
vid.width = 320;
@@ -517,20 +598,17 @@ void VID_Init (unsigned char *palette)
if (x_visinfo->class != TrueColor)
XFreeColormap(x_disp, tmpcmap);
-
}
if (x_visinfo->depth == 8)
{
-
- // create and upload the palette
+ // create and upload the palette
if (x_visinfo->class == PseudoColor)
{
x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
VID_SetPalette(palette);
XSetWindowColormap(x_disp, x_win, x_cmap);
}
-
}
// inviso cursor
@@ -610,9 +688,10 @@ void VID_SetPalette(unsigned char *palette)
int i;
XColor colors[256];
- for(i=0;i<256;i++)
- st2d_8to16table[i]= xlib_rgb(palette[i*3],
- palette[i*3+1],palette[i*3+2]);
+ for(i=0;i<256;i++) {
+ st2d_8to16table[i]= xlib_rgb16(palette[i*3], palette[i*3+1],palette[i*3+2]);
+ st2d_8to24table[i]= xlib_rgb24(palette[i*3], palette[i*3+1],palette[i*3+2]);
+ }
if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
{
@@ -881,6 +960,7 @@ void GetEvent(void)
void VID_Update (vrect_t *rects)
{
+ vrect_t full;
// if the window changes dimension, skip this frame
@@ -906,15 +986,27 @@ void VID_Update (vrect_t *rects)
return;
}
+ // force full update if not 8bit
+ if (x_visinfo->depth != 8) {
+ extern int scr_fullupdate;
+
+ scr_fullupdate = 0;
+ }
+
+
if (doShm)
{
while (rects)
{
- if (x_visinfo->depth != 8)
+ if (x_visinfo->depth == 16)
st2_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
+ else if (x_visinfo->depth == 24)
+ st3_fixup( x_framebuffer[current_framebuffer],
+ rects->x, rects->y, rects->width,
+ rects->height);
if (!XShmPutImage(x_disp, x_win, x_gc,
x_framebuffer[current_framebuffer], rects->x, rects->y,
rects->x, rects->y, rects->width, rects->height, True))
@@ -932,10 +1024,14 @@ void VID_Update (vrect_t *rects)
{
while (rects)
{
- if (x_visinfo->depth != 8)
+ if (x_visinfo->depth == 16)
st2_fixup( x_framebuffer[current_framebuffer],
rects->x, rects->y, rects->width,
rects->height);
+ else if (x_visinfo->depth == 24)
+ st3_fixup( x_framebuffer[current_framebuffer],
+ rects->x, rects->y, rects->width,
+ rects->height);
XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x,
rects->y, rects->x, rects->y, rects->width, rects->height);
rects = rects->pnext;