a dos port, as a dig at eukara about his xbox port project.
mouse+kb+soundblaster devices should work. you can compile a dedicated server, but the lack of any networking support makes it a bit pointless. the software renderer will work, but its crap and gets absolutely dire framerates. there's no code to init mesa or anything, so its crappy-software rendering only. I doubt anything useful will ever result from this, but it was still interesting to do. possibly the only useful thing to come from this will be from limiting ram use. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5104 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
5d2ff1286d
commit
445e7f476b
15 changed files with 1859 additions and 473 deletions
|
@ -289,6 +289,12 @@ ifeq ($(FTE_TARGET),morphos)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(FTE_TARGET),dos)
|
||||
#at least from dos.
|
||||
CC=i586-pc-msdosdjgpp-gcc
|
||||
CFLAGS+=-DNO_ZLIB
|
||||
endif
|
||||
|
||||
#if you have an x86, you can get gcc to build binaries using 3 different ABIs, instead of builds for just the default ABI
|
||||
ifeq ($(FTE_TARGET),linux32)
|
||||
FTE_TARGET=linux
|
||||
|
@ -360,6 +366,7 @@ CLIENT_DIR=$(BASE_DIR)/client
|
|||
GL_DIR=$(BASE_DIR)/gl
|
||||
D3D_DIR=$(BASE_DIR)/d3d
|
||||
VK_DIR=$(BASE_DIR)/vk
|
||||
SW_DIR=$(BASE_DIR)/sw
|
||||
SERVER_DIR=$(BASE_DIR)/server
|
||||
COMMON_DIR=$(BASE_DIR)/common
|
||||
HTTP_DIR=$(BASE_DIR)/http
|
||||
|
@ -399,6 +406,9 @@ endif
|
|||
ifeq ($(FTE_TARGET),cyg)
|
||||
BASELDFLAGS=-lm
|
||||
endif
|
||||
ifeq ($(FTE_TARGET),dos)
|
||||
BASELDFLAGS=-lm
|
||||
endif
|
||||
ifeq ($(FTE_TARGET),morphos)
|
||||
BASELDFLAGS=-lm
|
||||
endif
|
||||
|
@ -1369,6 +1379,30 @@ ifeq ($(FTE_TARGET),morphos)
|
|||
SV_CFLAGS=$(SERVER_ONLY_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(FTE_TARGET),dos)
|
||||
EXEPOSTFIX=.exe
|
||||
SV_DIR=sv_dos
|
||||
GLB_DIR=gl_dos
|
||||
MB_DIR=m_dos
|
||||
MCL_DIR=mcl_dos
|
||||
MINGL_DIR=mingl_dos
|
||||
VKB_DIR=vk_dos
|
||||
VKCL_DIR=vkcl_dos
|
||||
|
||||
IMAGELDFLAGS=
|
||||
OGGVORBISLDFLAGS=
|
||||
|
||||
SOFTWARE_OBJS=sw_rast.o sw_backend.o sw_image.o
|
||||
|
||||
M_LDFLAGS=
|
||||
M_CFLAGS=-DSWQUAKE -DNO_ZLIB
|
||||
MCL_OBJS=$(SOFTWARE_OBJS) $(D3DGL_OBJS) sw_viddos.o cd_null.o sys_dos.o snd_sblaster.o
|
||||
M_EXE_NAME=../$(EXE_NAME)$(EXEPOSTFIX)
|
||||
SV_EXE_NAME=../$(EXE_NAME)sv$(BITS)$(EXEPOSTFIX)
|
||||
VK_EXE_NAME=../$(EXE_NAME)-vk$(BITS)$(EXEPOSTFIX)
|
||||
|
||||
VKCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) cd_null.o sys_dos.o snd_sblaster.o
|
||||
endif
|
||||
|
||||
ifeq ($(FTE_TARGET),cyg)
|
||||
SV_DIR=sv_cygwin
|
||||
|
@ -1510,7 +1544,7 @@ ifneq ($(OUT_DIR),)
|
|||
endif
|
||||
|
||||
|
||||
VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(D3D_DIR) : $(VK_DIR) : $(BOTLIB_DIR) : $(BASE_DIR)/libs/speex/libspeex : $(BASE_DIR)/web
|
||||
VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(SW_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(D3D_DIR) : $(VK_DIR) : $(BOTLIB_DIR) : $(BASE_DIR)/libs/speex/libspeex : $(BASE_DIR)/web
|
||||
|
||||
ifneq ($(findstring -DSPEEX_STATIC, $(CFLAGS)),)
|
||||
#add these to statically link libspeex
|
||||
|
|
|
@ -328,12 +328,25 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#define ARCH_STRING "x86"
|
||||
|
||||
#define Q3_BIG_ENDIAN
|
||||
#define Q3_LITTLE_ENDIAN
|
||||
|
||||
#define DLL_EXT ".dll"
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __DJGPP__
|
||||
#define OS_STRING "msdos"
|
||||
#define ID_INLINE static inline
|
||||
#define PATH_SEP '/'
|
||||
|
||||
#define ARCH_STRING "dos"
|
||||
|
||||
#define Q3_LITTLE_ENDIAN
|
||||
|
||||
#define DLL_EXT ".dll"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
#define OS_STRING "emscripten"
|
||||
#define ID_INLINE static inline
|
||||
|
|
|
@ -91,7 +91,13 @@ cvar_t snd_noextraupdate = CVARAF( "s_noextraupdate", "0",
|
|||
"snd_noextraupdate", 0);
|
||||
cvar_t snd_show = CVARAF( "s_show", "0",
|
||||
"snd_show", 0);
|
||||
cvar_t snd_khz = CVARAFD( "s_khz", "48",
|
||||
#ifdef __DJGPP__
|
||||
#define DEFAULT_SND_KHZ "11"
|
||||
#else
|
||||
//fixme: are android devices more likely to use 44.1khz?
|
||||
#define DEFAULT_SND_KHZ "48" //most modern systems should go with 48khz audio (dvd quality). various hardware codecs support nothing else.
|
||||
#endif
|
||||
cvar_t snd_khz = CVARAFD( "s_khz", DEFAULT_SND_KHZ,
|
||||
"snd_khz", CVAR_ARCHIVE, "Sound speed, in kilohertz. Common values are 11, 22, 44, 48. Values above 1000 are explicitly in hertz.");
|
||||
cvar_t snd_inactive = CVARAFD( "s_inactive", "1",
|
||||
"snd_inactive", CVAR_ARCHIVE,
|
||||
|
@ -1507,11 +1513,16 @@ extern sounddriver_t XAUDIO2_Output;
|
|||
extern sounddriver_t DSOUND_Output;
|
||||
#endif
|
||||
sounddriver_t SDL_Output;
|
||||
#ifdef __linux__
|
||||
sounddriver_t ALSA_Output;
|
||||
#endif
|
||||
sounddriver_t OSS_Output;
|
||||
#ifdef AVAIL_OPENAL
|
||||
extern sounddriver_t OPENAL_Output;
|
||||
#endif
|
||||
#ifdef __DJGPP__
|
||||
extern sounddriver_t SBLASTER_Output;
|
||||
#endif
|
||||
|
||||
sounddriver pSNDIO_InitCard;
|
||||
sounddriver pOSS_InitCard;
|
||||
|
@ -1546,6 +1557,9 @@ static sounddriver_t *outputdrivers[] =
|
|||
&ALSA_Output, //pure shite
|
||||
#endif
|
||||
&OSS_Output, //good, but not likely to work any more
|
||||
#ifdef __DJGPP__
|
||||
&SBLASTER_Output, //zomgwtfdos?
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
typedef struct {
|
||||
|
|
590
engine/client/snd_sblaster.c
Normal file
590
engine/client/snd_sblaster.c
Normal file
|
@ -0,0 +1,590 @@
|
|||
/*
|
||||
Copyright (C) 1996-1997 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.
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//I had one at least, back in the day.
|
||||
//should be fine for dosbox, if nothing else.
|
||||
|
||||
//warning: this sound code doesn't seem to cope well with low framerates. the dma buffer is too small.
|
||||
//4096 bytes 16bit stereo means 1024 samples. so less than 10 fps and the mixer will miss buffer wraps.
|
||||
|
||||
|
||||
#include <quakedef.h>
|
||||
|
||||
#include <dos.h>
|
||||
#include <dpmi.h>
|
||||
#include <go32.h>
|
||||
#include <sys/nearptr.h>
|
||||
|
||||
#define SDRVNAME "SoundBlaster"
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
BLASTER SUPPORT
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
_go32_dpmi_seginfo dma_buffer_memory;
|
||||
static short *dma_buffer=0; //realigned pointer
|
||||
quintptr_t dma_buffer_phys; //realigned physical address - must be within the first 16mb
|
||||
static int dma_size;
|
||||
static int dma;
|
||||
|
||||
static int dsp_port;
|
||||
static int irq;
|
||||
static int low_dma;
|
||||
static int high_dma;
|
||||
static int mixer_port;
|
||||
static int mpu401_port;
|
||||
|
||||
static int dsp_version;
|
||||
static int dsp_minor_version;
|
||||
|
||||
static int timeconstant=-1;
|
||||
static int oldmixervalue;
|
||||
|
||||
static int mode_reg;
|
||||
static int flipflop_reg;
|
||||
static int disable_reg;
|
||||
static int clear_reg;
|
||||
|
||||
static soundcardinfo_t *becauseglobalssuck; //just protects against multiple devices being spawned at once.
|
||||
|
||||
|
||||
static void PrintBits (qbyte b)
|
||||
{
|
||||
int i;
|
||||
char str[9];
|
||||
|
||||
for (i=0 ; i<8 ; i++)
|
||||
str[i] = '0' + ((b & (1<<(7-i))) > 0);
|
||||
|
||||
str[8] = 0;
|
||||
Con_Printf ("%s (%i)", str, b);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Interprets BLASTER variable
|
||||
// =======================================================================
|
||||
|
||||
static int GetBLASTER(void)
|
||||
{
|
||||
char *BLASTER;
|
||||
char *param;
|
||||
|
||||
BLASTER = getenv("BLASTER");
|
||||
if (!BLASTER)
|
||||
return 0;
|
||||
|
||||
param = strchr(BLASTER, 'A');
|
||||
if (!param)
|
||||
param = strchr(BLASTER, 'a');
|
||||
if (!param)
|
||||
return 0;
|
||||
sscanf(param+1, "%x", &dsp_port);
|
||||
|
||||
param = strchr(BLASTER, 'I');
|
||||
if (!param)
|
||||
param = strchr(BLASTER, 'i');
|
||||
if (!param)
|
||||
return 0;
|
||||
sscanf(param+1, "%d", &irq);
|
||||
|
||||
param = strchr(BLASTER, 'D');
|
||||
if (!param)
|
||||
param = strchr(BLASTER, 'd');
|
||||
if (!param)
|
||||
return 0;
|
||||
sscanf(param+1, "%d", &low_dma);
|
||||
|
||||
param = strchr(BLASTER, 'H');
|
||||
if (!param)
|
||||
param = strchr(BLASTER, 'h');
|
||||
if (param)
|
||||
sscanf(param+1, "%d", &high_dma);
|
||||
|
||||
param = strchr(BLASTER, 'M');
|
||||
if (!param)
|
||||
param = strchr(BLASTER, 'm');
|
||||
if (param)
|
||||
sscanf(param+1, "%x", &mixer_port);
|
||||
else
|
||||
mixer_port = dsp_port;
|
||||
|
||||
param = strchr(BLASTER, 'P');
|
||||
if (!param)
|
||||
param = strchr(BLASTER, 'p');
|
||||
if (param)
|
||||
sscanf(param+1, "%x", &mpu401_port);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// Resets DSP. Returns 0 on success.
|
||||
// ==================================================================
|
||||
|
||||
static int ResetDSP(void)
|
||||
{
|
||||
volatile int i;
|
||||
|
||||
outportb(dsp_port + 6, 1);
|
||||
for (i=65536 ; i ; i--) ;
|
||||
outportb(dsp_port + 6, 0);
|
||||
for (i=65536 ; i ; i--)
|
||||
{
|
||||
if (!(inportb(dsp_port + 0xe) & 0x80)) continue;
|
||||
if (inportb(dsp_port + 0xa) == 0xaa) break;
|
||||
}
|
||||
if (i) return 0;
|
||||
else return 1;
|
||||
|
||||
}
|
||||
|
||||
static int ReadDSP(void)
|
||||
{
|
||||
while (!(inportb(dsp_port+0xe)&0x80)) ;
|
||||
return inportb(dsp_port+0xa);
|
||||
}
|
||||
|
||||
static void WriteDSP(int val)
|
||||
{
|
||||
while ((inportb(dsp_port+0xc)&0x80)) ;
|
||||
outportb(dsp_port+0xc, val);
|
||||
}
|
||||
|
||||
static int ReadMixer(int addr)
|
||||
{
|
||||
outportb(mixer_port+4, addr);
|
||||
return inportb(mixer_port+5);
|
||||
}
|
||||
|
||||
static void WriteMixer(int addr, int val)
|
||||
{
|
||||
outportb(mixer_port+4, addr);
|
||||
outportb(mixer_port+5, val);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
StartSB
|
||||
|
||||
================
|
||||
*/
|
||||
static void StartSB(soundcardinfo_t *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
// version 4.xx startup code
|
||||
if (dsp_version >= 4)
|
||||
{
|
||||
Con_Printf("Version 4 SB startup\n");
|
||||
WriteDSP(0xd1); // turn on speaker
|
||||
|
||||
WriteDSP(0x41);
|
||||
|
||||
WriteDSP(sc->sn.speed>>8);
|
||||
WriteDSP(sc->sn.speed&0xff);
|
||||
|
||||
WriteDSP(0xb6); // 16-bit output
|
||||
WriteDSP(0x30); // stereo
|
||||
WriteDSP((sc->sn.samples-1) & 0xff); // # of samples - 1
|
||||
WriteDSP((sc->sn.samples-1) >> 8);
|
||||
}
|
||||
// version 3.xx startup code
|
||||
else if (dsp_version == 3)
|
||||
{
|
||||
Con_Printf("Version 3 SB startup\n");
|
||||
WriteDSP(0xd1); // turn on speaker
|
||||
|
||||
oldmixervalue = ReadMixer (0xe);
|
||||
WriteMixer (0xe, oldmixervalue | 0x2);// turn on stereo
|
||||
|
||||
WriteDSP(0x14); // send one byte
|
||||
WriteDSP(0x0);
|
||||
WriteDSP(0x0);
|
||||
|
||||
for (i=0 ; i<0x10000 ; i++)
|
||||
inportb(dsp_port+0xe); // ack the dsp
|
||||
|
||||
timeconstant = 65536-(256000000/(sc->sn.numchannels*sc->sn.speed));
|
||||
WriteDSP(0x40);
|
||||
WriteDSP(timeconstant>>8);
|
||||
|
||||
WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter
|
||||
|
||||
WriteDSP(0x48);
|
||||
WriteDSP((sc->sn.samples-1) & 0xff); // # of samples - 1
|
||||
WriteDSP((sc->sn.samples-1) >> 8);
|
||||
|
||||
WriteDSP(0x90); // high speed 8 bit stereo
|
||||
}
|
||||
// normal speed mono
|
||||
else
|
||||
{
|
||||
Con_Printf("Version 2 SB startup\n");
|
||||
WriteDSP(0xd1); // turn on speaker
|
||||
|
||||
timeconstant = 65536-(256000000/(sc->sn.numchannels*sc->sn.speed));
|
||||
WriteDSP(0x40);
|
||||
WriteDSP(timeconstant>>8);
|
||||
|
||||
WriteDSP(0x48);
|
||||
WriteDSP((sc->sn.samples-1) & 0xff); // # of samples - 1
|
||||
WriteDSP((sc->sn.samples-1) >> 8);
|
||||
|
||||
WriteDSP(0x1c); // normal speed 8 bit mono
|
||||
}
|
||||
}
|
||||
|
||||
static const int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
|
||||
static const int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
|
||||
static const int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };
|
||||
|
||||
/*
|
||||
================
|
||||
StartDMA
|
||||
|
||||
================
|
||||
*/
|
||||
static void StartDMA(void)
|
||||
{
|
||||
int mode;
|
||||
|
||||
// use a high dma channel if specified
|
||||
if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma
|
||||
dma = high_dma;
|
||||
else
|
||||
dma = low_dma;
|
||||
|
||||
Con_Printf ("Using DMA channel %i\n", dma);
|
||||
|
||||
if (dma > 3)
|
||||
{
|
||||
mode_reg = 0xd6;
|
||||
flipflop_reg = 0xd8;
|
||||
disable_reg = 0xd4;
|
||||
clear_reg = 0xdc;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode_reg = 0xb;
|
||||
flipflop_reg = 0xc;
|
||||
disable_reg = 0xa;
|
||||
clear_reg = 0xe;
|
||||
}
|
||||
|
||||
outportb(disable_reg, dma|4); // disable channel
|
||||
// set mode- see "undocumented pc", p.876
|
||||
mode = (1<<6) // single-cycle
|
||||
+(0<<5) // address increment
|
||||
+(1<<4) // auto-init dma
|
||||
+(2<<2) // read
|
||||
+(dma&3); // channel #
|
||||
outportb(mode_reg, mode);
|
||||
|
||||
// set address
|
||||
// set page
|
||||
outportb(page_reg[dma], dma_buffer_phys >> 16);
|
||||
|
||||
if (dma > 3)
|
||||
{ // address is in words
|
||||
outportb(flipflop_reg, 0); // prepare to send 16-bit value
|
||||
outportb(addr_reg[dma], (dma_buffer_phys>>1) & 0xff);
|
||||
outportb(addr_reg[dma], (dma_buffer_phys>>9) & 0xff);
|
||||
|
||||
outportb(flipflop_reg, 0); // prepare to send 16-bit value
|
||||
outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff);
|
||||
outportb(count_reg[dma], ((dma_size>>1)-1) >> 8);
|
||||
}
|
||||
else
|
||||
{ // address is in bytes
|
||||
outportb(flipflop_reg, 0); // prepare to send 16-bit value
|
||||
outportb(addr_reg[dma], dma_buffer_phys & 0xff);
|
||||
outportb(addr_reg[dma], (dma_buffer_phys>>8) & 0xff);
|
||||
|
||||
outportb(flipflop_reg, 0); // prepare to send 16-bit value
|
||||
outportb(count_reg[dma], (dma_size-1) & 0xff);
|
||||
outportb(count_reg[dma], (dma_size-1) >> 8);
|
||||
}
|
||||
|
||||
outportb(clear_reg, 0); // clear write mask
|
||||
outportb(disable_reg, dma&~4);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
BLASTER_GetDMAPos
|
||||
|
||||
return the current sample position (in mono samples read)
|
||||
inside the recirculating dma buffer, so the mixing code will know
|
||||
how many sample are required to fill it up.
|
||||
===============
|
||||
*/
|
||||
static unsigned int SBLASTER_GetDMAPos(soundcardinfo_t *sc)
|
||||
{
|
||||
int count;
|
||||
|
||||
// this function is called often. acknowledge the transfer completions
|
||||
// all the time so that it loops
|
||||
if (dsp_version >= 4)
|
||||
inportb(dsp_port+0xf); // 16 bit audio
|
||||
else
|
||||
inportb(dsp_port+0xe); // 8 bit audio
|
||||
|
||||
// clear 16-bit reg flip-flop
|
||||
// load the current dma count register
|
||||
if (dma < 4)
|
||||
{
|
||||
outportb(0xc, 0);
|
||||
count = inportb(dma*2+1);
|
||||
count += inportb(dma*2+1) << 8;
|
||||
if (sc->sn.samplebits == 16)
|
||||
count /= 2;
|
||||
count = sc->sn.samples - (count+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
outportb(0xd8, 0);
|
||||
count = inportb(0xc0+(dma-4)*4+2);
|
||||
count += inportb(0xc0+(dma-4)*4+2) << 8;
|
||||
if (sc->sn.samplebits == 8)
|
||||
count *= 2;
|
||||
count = sc->sn.samples - (count+1);
|
||||
}
|
||||
|
||||
// Con_Printf("DMA pos = 0x%x\n", count);
|
||||
|
||||
// sc->sn.samplepos = count & (sc->sn.samples-1);
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
BLASTER_Shutdown
|
||||
|
||||
Reset the sound device for exiting
|
||||
===============
|
||||
*/
|
||||
static void SBLASTER_Shutdown(soundcardinfo_t *sc)
|
||||
{
|
||||
if (becauseglobalssuck == sc)
|
||||
becauseglobalssuck = NULL;
|
||||
|
||||
if (dsp_version >= 4)
|
||||
{
|
||||
}
|
||||
else if (dsp_version == 3)
|
||||
{
|
||||
ResetDSP (); // stop high speed mode
|
||||
WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WriteDSP(0xd3); // turn off speaker
|
||||
ResetDSP ();
|
||||
|
||||
outportb(disable_reg, dma|4); // disable dma channel
|
||||
|
||||
_go32_dpmi_free_dos_memory(&dma_buffer_memory);
|
||||
}
|
||||
|
||||
//simple ring buffer
|
||||
static void *SBLASTER_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
|
||||
{
|
||||
return sc->sn.buffer;
|
||||
}
|
||||
|
||||
//that's permanently locked
|
||||
static void SBLASTER_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
|
||||
{
|
||||
}
|
||||
|
||||
//that the hardware has direct access to.
|
||||
static void SBLASTER_Submit (soundcardinfo_t *sc, int start, int end)
|
||||
{
|
||||
}
|
||||
|
||||
//returns the address of some memory.
|
||||
//ctx is required to free the memory afterwards
|
||||
static qboolean dosmem_alloc(_go32_dpmi_seginfo *ctx, size_t size)
|
||||
{
|
||||
ctx->size = (size+15)>>4;
|
||||
if (_go32_dpmi_allocate_dos_memory(ctx))
|
||||
return false; //failed
|
||||
return true;
|
||||
}
|
||||
|
||||
static quintptr_t dosmem_phys(_go32_dpmi_seginfo *ctx)
|
||||
{
|
||||
return ctx->rm_segment<<4;
|
||||
}
|
||||
static void *dosmem_ptr(_go32_dpmi_seginfo *ctx)
|
||||
{
|
||||
__djgpp_nearptr_enable();
|
||||
return (void*)(__djgpp_conventional_base+dosmem_phys(ctx));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
BLASTER_Init
|
||||
|
||||
Returns false if nothing is found.
|
||||
==================
|
||||
*/
|
||||
static qboolean SBLASTER_InitCard(soundcardinfo_t *sc, const char *pcmname)
|
||||
{
|
||||
int size;
|
||||
int p;
|
||||
|
||||
if (becauseglobalssuck)
|
||||
return 0;
|
||||
|
||||
//
|
||||
// must have a blaster variable set
|
||||
//
|
||||
if (!GetBLASTER())
|
||||
{
|
||||
Con_NotifyBox (
|
||||
"The BLASTER environment variable\n"
|
||||
"is not set, sound effects are\n"
|
||||
"disabled. See README.TXT for help.\n"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ResetDSP())
|
||||
{
|
||||
Con_Printf("Could not reset SB");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// get dsp version
|
||||
//
|
||||
WriteDSP(0xe1);
|
||||
dsp_version = ReadDSP();
|
||||
dsp_minor_version = ReadDSP();
|
||||
|
||||
// we need at least v2 for auto-init dma
|
||||
if (dsp_version < 2)
|
||||
{
|
||||
Con_Printf ("Sound blaster must be at least v2.0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allow command line parm to set quality down
|
||||
p = COM_CheckParm ("-dsp");
|
||||
if (p && p < com_argc - 1)
|
||||
{
|
||||
p = Q_atoi (com_argv[p+1]);
|
||||
if (p < 2 || p > 4)
|
||||
Con_Printf ("-dsp parameter can only be 2, 3, or 4\n");
|
||||
else if (p > dsp_version)
|
||||
Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version);
|
||||
else
|
||||
dsp_version = p;
|
||||
}
|
||||
|
||||
|
||||
// everyone does 11khz sampling rate unless told otherwise
|
||||
// sc->sn.speed = 11025;
|
||||
// rc = COM_CheckParm("-sspeed");
|
||||
// if (rc)
|
||||
// sc->sn.speed = Q_atoi(com_argv[rc+1]);
|
||||
|
||||
// version 4 cards (sb 16) do 16 bit stereo
|
||||
if (dsp_version >= 4)
|
||||
{
|
||||
if (sc->sn.numchannels != 1)
|
||||
sc->sn.numchannels = 2;
|
||||
if (sc->sn.samplebits != 8)
|
||||
sc->sn.samplebits = 16;
|
||||
}
|
||||
// version 3 cards (sb pro) do 8 bit stereo
|
||||
else if (dsp_version == 3)
|
||||
{
|
||||
if (sc->sn.numchannels != 1)
|
||||
sc->sn.numchannels = 2;
|
||||
sc->sn.samplebits = 8;
|
||||
}
|
||||
// v2 cards do 8 bit mono
|
||||
else
|
||||
{
|
||||
sc->sn.numchannels = 1;
|
||||
sc->sn.samplebits = 8;
|
||||
}
|
||||
|
||||
sc->Lock = SBLASTER_LockBuffer;
|
||||
sc->Unlock = SBLASTER_UnlockBuffer;
|
||||
sc->Shutdown = SBLASTER_Shutdown;
|
||||
sc->GetDMAPos = SBLASTER_GetDMAPos;
|
||||
sc->Submit = SBLASTER_Submit;
|
||||
|
||||
size = 4096;
|
||||
|
||||
// allocate 8k and get a 4k-aligned buffer from it
|
||||
if (!dosmem_alloc(&dma_buffer_memory, size*2))
|
||||
{
|
||||
Con_Printf("Couldn't allocate sound dma buffer");
|
||||
return false;
|
||||
}
|
||||
dma_buffer_phys = ((dosmem_phys(&dma_buffer_memory) + size) & ~(size-1));
|
||||
dma_buffer = (short *)((qbyte*)dosmem_ptr(&dma_buffer_memory) + dma_buffer_phys-dosmem_phys(&dma_buffer_memory));
|
||||
|
||||
dma_size = size;
|
||||
memset(dma_buffer, 0, dma_size);
|
||||
|
||||
sc->sn.samples = size/(sc->sn.samplebits/8);
|
||||
sc->sn.samplepos = 0;
|
||||
sc->sn.buffer = (unsigned char *) dma_buffer;
|
||||
sc->sn.samples = size/(sc->sn.samplebits/8);
|
||||
|
||||
StartDMA();
|
||||
StartSB(sc);
|
||||
|
||||
becauseglobalssuck = sc;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static qboolean QDECL SBLASTER_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sounddriver_t SBLASTER_Output =
|
||||
{
|
||||
SDRVNAME,
|
||||
SBLASTER_InitCard,
|
||||
SBLASTER_Enumerate
|
||||
};
|
||||
|
185
engine/client/sys_dos.c
Normal file
185
engine/client/sys_dos.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include <quakedef.h>
|
||||
|
||||
//because cake.
|
||||
#include "sys_linux.c"
|
||||
|
||||
#include <dos.h>
|
||||
#include <dpmi.h>
|
||||
_go32_dpmi_registers regs;
|
||||
int dos_int86(int vec)
|
||||
{
|
||||
int rc;
|
||||
regs.x.ss = regs.x.sp = 0;
|
||||
rc = _go32_dpmi_simulate_int(vec, ®s);
|
||||
return rc || (regs.x.flags & 1);
|
||||
}
|
||||
|
||||
|
||||
static int mouse_buttons;
|
||||
static int mouse_numbuttons;
|
||||
static unsigned int dosmousedeviceid;
|
||||
|
||||
static unsigned int doskeyboarddeviceid;
|
||||
|
||||
#define KBRINGSIZE 256
|
||||
static struct
|
||||
{
|
||||
unsigned char buf[KBRINGSIZE];
|
||||
int write;
|
||||
int read;
|
||||
} kbring;
|
||||
|
||||
void TheKBHandler(void)
|
||||
{ //this needs to be kept simple and small.
|
||||
//we write to a really simple ringbuffer to avoid needing to lock various code/data pages.
|
||||
kbring.buf[kbring.write++&(KBRINGSIZE-1)] = inportb(0x60);
|
||||
outportb(0x20, 0x20);
|
||||
}
|
||||
|
||||
unsigned char keymap[256] =
|
||||
{
|
||||
//this is a copy of the US keymap from vanilla quake.
|
||||
//its so very tempting to switch it to a UK keymap...
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 8 9 A B C D E F
|
||||
0 , 27, '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', K_BACKSPACE,K_TAB, // 0
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
||||
'o', 'p', '[', ']', 13 , K_CTRL, 'a', 's', // 1
|
||||
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
||||
'\'' , '`', K_LSHIFT,'\\', 'z', 'x', 'c', 'v', // 2
|
||||
'b', 'n', 'm', ',', '.', '/', K_RSHIFT, '*',
|
||||
K_ALT, ' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
||||
K_F6, K_F7, K_F8, K_F9, K_F10, 0 , 0 , K_HOME,
|
||||
K_UPARROW, K_PGUP, '-', K_LEFTARROW,'5', K_RIGHTARROW,'+', K_END, // 4
|
||||
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0 , 0, K_F11,
|
||||
K_F12, 0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 7
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 8 9 A B C D E F
|
||||
0 , 27, '!', '@', '#', '$', '%', '^',
|
||||
'&', '*', '(', ')', '_', '+', K_BACKSPACE,K_TAB, // 0
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
|
||||
'O', 'P', '{', '}', 13 , K_CTRL, 'A', 'S', // 1
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
|
||||
'\"', '~', K_LSHIFT,'|', 'Z', 'X', 'C', 'V', // 2
|
||||
'B', 'N', 'M', '<', '>', '?', K_RSHIFT, '*',
|
||||
K_ALT, ' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
||||
K_F6, K_F7, K_F8, K_F9, K_F10, 0 , 0 , K_HOME,
|
||||
K_UPARROW, K_PGUP, '_', K_LEFTARROW,'%', K_RIGHTARROW,'+', K_END, // 4
|
||||
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
|
||||
K_F12, 0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
|
||||
};
|
||||
|
||||
void INS_Init(void)
|
||||
{
|
||||
//make sure the kb handler and its data won't get paged out.
|
||||
_go32_dpmi_lock_code((void *) TheKBHandler, 512);
|
||||
_go32_dpmi_lock_data((void *) &kbring, sizeof(kbring));
|
||||
|
||||
//set up our interrupt handler.
|
||||
_go32_dpmi_seginfo info;
|
||||
info.pm_offset = (int) TheKBHandler;
|
||||
_go32_dpmi_allocate_iret_wrapper(&info);
|
||||
_go32_dpmi_set_protected_mode_interrupt_vector(9, &info);
|
||||
}
|
||||
|
||||
void Sys_SendKeyEvents(void)
|
||||
{ //this is kinda silly, but the handler can't do it if we want to be correct with respect to virtual memory.
|
||||
static int shift_down;
|
||||
while (kbring.read != kbring.write)
|
||||
{ //keyboard maps are complicated, annoyingly so. left/right/extended.... and don't get me started on sysreq. some keys don't even have release events!
|
||||
unsigned char c = kbring.buf[kbring.read++&(KBRINGSIZE-1)];
|
||||
unsigned int qkey, ukey;
|
||||
|
||||
qkey = keymap[c&0x7f];
|
||||
ukey = (qkey >= 32 && qkey < 127)?keymap[(c&0x7f)|(shift_down?128:0)]:0;
|
||||
if (c == 0xe0)
|
||||
{ //extended keys...
|
||||
if (kbring.buf[kbring.read&(KBRINGSIZE-1)] == 0x1d)
|
||||
qkey = K_RSHIFT;
|
||||
else
|
||||
continue; //annoying extended keys.
|
||||
ukey = 0;
|
||||
kbring.read++;
|
||||
}
|
||||
if (qkey == K_LSHIFT)
|
||||
shift_down = (shift_down&~1) | ((c&0x80)?0:1);
|
||||
if (qkey == K_RSHIFT)
|
||||
shift_down = (shift_down&~2) | ((c&0x80)?0:2);
|
||||
// Con_Printf("Keyboard: %x\n", c);
|
||||
IN_KeyEvent(doskeyboarddeviceid, !(c&0x80), qkey, ukey);
|
||||
}
|
||||
}
|
||||
|
||||
void INS_Move(float *movements, int pnum)
|
||||
{
|
||||
}
|
||||
void INS_Commands(void)
|
||||
{
|
||||
if (!mouse_numbuttons)
|
||||
return;
|
||||
|
||||
regs.x.ax = 11; // read move
|
||||
dos_int86(0x33);
|
||||
if (regs.x.cx || regs.x.dx)
|
||||
{
|
||||
IN_MouseMove(dosmousedeviceid, false, (short)regs.x.cx, (short)regs.x.dx, 0, 0);
|
||||
|
||||
Con_Printf("Mouse Move: %i %i\n", (short)regs.x.cx, (short)regs.x.dx);
|
||||
}
|
||||
|
||||
regs.x.ax = 3; // read buttons
|
||||
dos_int86(0x33);
|
||||
int b = mouse_buttons ^ regs.x.bx;
|
||||
mouse_buttons = regs.x.bx;
|
||||
for (int i = 0; i < mouse_numbuttons; i++)
|
||||
{
|
||||
if (b&(1u<<i))
|
||||
IN_KeyEvent(dosmousedeviceid, !!(mouse_buttons&(1u<<i)), K_MOUSE1+i, 0);
|
||||
}
|
||||
|
||||
Sys_SendKeyEvents();
|
||||
}
|
||||
void INS_ReInit(void)
|
||||
{
|
||||
dosmousedeviceid = 0;
|
||||
mouse_buttons = 0;
|
||||
mouse_numbuttons = 0;
|
||||
|
||||
regs.x.ax = 0;
|
||||
dos_int86(0x33);
|
||||
if (!regs.x.ax)
|
||||
{
|
||||
Con_Printf ("No mouse found\n");
|
||||
return;
|
||||
}
|
||||
mouse_numbuttons = regs.x.bx;
|
||||
if (mouse_numbuttons >= 255)
|
||||
mouse_numbuttons = 2;
|
||||
if (mouse_numbuttons > 10)
|
||||
mouse_numbuttons = 10;
|
||||
Con_Printf("%d-button mouse available\n", mouse_numbuttons);
|
||||
}
|
||||
void INS_Shutdown(void)
|
||||
{
|
||||
}
|
||||
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
|
||||
{
|
||||
callback(ctx, "mouse", "dosmouse", &dosmousedeviceid);
|
||||
callback(ctx, "keyboard", "doskeyboard", &doskeyboarddeviceid);
|
||||
}
|
||||
|
||||
void Sys_Sleep (double seconds)
|
||||
{
|
||||
usleep(seconds * 1000000);
|
||||
}
|
|
@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#ifndef __CYGWIN__
|
||||
#if !defined(__CYGWIN__) && !defined(__DJGPP__)
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
@ -46,7 +46,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#ifndef __MACOSX__
|
||||
#if !defined(__MACOSX__) && !defined(__DJGPP__)
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
#ifdef MULTITHREAD
|
||||
|
@ -255,8 +255,10 @@ void Sys_Printf (char *fmt, ...)
|
|||
void Sys_Quit (void)
|
||||
{
|
||||
Host_Shutdown();
|
||||
#ifndef __DJGPP__
|
||||
if (!noconinput)
|
||||
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBTOOL
|
||||
lt_dlexit();
|
||||
|
@ -400,9 +402,11 @@ void Sys_Error (const char *error, ...)
|
|||
va_list argptr;
|
||||
char string[1024];
|
||||
|
||||
#ifndef __DJGPP__
|
||||
// change stdin to non blocking
|
||||
if (!noconinput)
|
||||
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
|
||||
#endif
|
||||
|
||||
va_start (argptr,error);
|
||||
vsnprintf (string,sizeof(string)-1, error,argptr);
|
||||
|
@ -827,13 +831,6 @@ static void Friendly_Crash_Handler(int sig, siginfo_t *info, void *vcontext)
|
|||
// Sleeps for microseconds
|
||||
// =======================================================================
|
||||
|
||||
static volatile int oktogo;
|
||||
|
||||
void alarm_handler(int x)
|
||||
{
|
||||
oktogo=1;
|
||||
}
|
||||
|
||||
char *Sys_ConsoleInput(void)
|
||||
{
|
||||
#if 1
|
||||
|
@ -853,7 +850,9 @@ char *Sys_ConsoleInput(void)
|
|||
|
||||
// if (!qrenderer)
|
||||
{
|
||||
Con_Printf("ConsoleInput\n");
|
||||
len = read (0, text, sizeof(text));
|
||||
Con_Printf("ConsoleInput read %i\n", len);
|
||||
if (len < 1)
|
||||
return NULL;
|
||||
|
||||
|
@ -948,13 +947,17 @@ int main (int c, const char **v)
|
|||
|
||||
|
||||
noconinput = COM_CheckParm("-noconinput");
|
||||
#ifndef __DJGPP__
|
||||
if (!noconinput)
|
||||
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
|
||||
#endif
|
||||
|
||||
#ifdef SUBSERVERS
|
||||
if (COM_CheckParm("-clusterslave"))
|
||||
isDedicated = nostdout = isClusterSlave = true;
|
||||
#endif
|
||||
if (COM_CheckParm("-dedicated"))
|
||||
isDedicated = true;
|
||||
|
||||
if (COM_CheckParm("-nostdout"))
|
||||
nostdout = 1;
|
||||
|
@ -963,7 +966,6 @@ int main (int c, const char **v)
|
|||
|
||||
for (i = 1; i < parms.argc; i++)
|
||||
{
|
||||
Con_Printf("Arg%i == %s\n", i, parms.argv[i]);
|
||||
if (!parms.argv[i])
|
||||
continue;
|
||||
if (*parms.argv[i] == '+' || *parms.argv[i] == '-')
|
||||
|
@ -1033,7 +1035,7 @@ void Sys_ServerActivity(void)
|
|||
//from the OS. This will cause problems with framebuffer-only setups.
|
||||
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate)
|
||||
{
|
||||
#ifdef __MACOSX__
|
||||
#if defined(__MACOSX__) || defined(__DJGPP__)
|
||||
//this about sums up the problem with this function
|
||||
return false;
|
||||
#else
|
||||
|
|
|
@ -356,7 +356,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#endif
|
||||
|
||||
//software rendering is just too glitchy, don't use it.
|
||||
#if defined(SWQUAKE) && !defined(_DEBUG)
|
||||
#if defined(SWQUAKE) && !defined(_DEBUG) && !defined(__DJGPP__)
|
||||
#undef SWQUAKE
|
||||
#endif
|
||||
#if (defined(D3D8QUAKE) || defined(D3D9QUAKE) || defined(D3D11QUAKE)) && !defined(D3DQUAKE)
|
||||
|
@ -444,6 +444,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#undef WEBCLIENT //http/ftp clients.
|
||||
#endif
|
||||
|
||||
#ifdef __DJGPP__
|
||||
//no bsd sockets library.
|
||||
#undef HAVE_TCP
|
||||
#undef HAVE_PACKET
|
||||
#undef SUPPORT_ICE
|
||||
//too lazy to deal with no dlopen
|
||||
#undef PLUGINS
|
||||
#undef Q2SERVER
|
||||
#undef Q3SERVER
|
||||
#undef Q2CLIENT //fixme...
|
||||
#undef Q3CLIENT //might as well.
|
||||
//too lazy to write the code to boot up more cores. dosbox would probably hate it so why bother.
|
||||
#undef MULTITHREAD
|
||||
//too lazy to deal with various libraries
|
||||
#undef VOICECHAT
|
||||
#undef AVAIL_JPEGLIB
|
||||
#undef AVAIL_PNGLIB
|
||||
#undef AVAIL_OGGVORBIS
|
||||
#endif
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
//sandboxing...
|
||||
#undef HAVE_TCP //websockets are not real tcp.
|
||||
|
|
|
@ -71,7 +71,7 @@ void Mod_DoCRC(model_t *mod, char *buffer, int buffersize)
|
|||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__DJGPP__)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
|
|
|
@ -1717,7 +1717,7 @@ void MSG_ReadPos (vec3_t pos)
|
|||
pos[2] = MSG_ReadCoord();
|
||||
}
|
||||
|
||||
#if defined(Q2SERVER) || !defined(SERVERONLY)
|
||||
#if 1//defined(Q2SERVER) || !defined(SERVERONLY)
|
||||
#define Q2NUMVERTEXNORMALS 162
|
||||
vec3_t bytedirs[Q2NUMVERTEXNORMALS] =
|
||||
{
|
||||
|
@ -2652,7 +2652,7 @@ unsigned int unicode_charofsfrombyteofs(const char *str, unsigned int byteofs, q
|
|||
return chars;
|
||||
}
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
#if defined(FTE_TARGET_WEB) || defined(__DJGPP__)
|
||||
//targets that don't support towupper/towlower...
|
||||
#define towupper Q_towupper
|
||||
#define towlower Q_towlower
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#endif
|
||||
#include "com_mesh.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__DJGPP__)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "glquake.h"
|
||||
#ifndef SERVERONLY
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__DJGPP__)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
|
|
|
@ -6057,7 +6057,7 @@ static qboolean Terr_Brush_DeleteId(heightmap_t *hm, unsigned int brushid)
|
|||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__DJGPP__)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
|
|
|
@ -120,6 +120,8 @@ struct q2gclient_s
|
|||
// this point in the structure
|
||||
};
|
||||
|
||||
#endif
|
||||
#if defined(Q2SERVER) || defined(Q2CLIENT)
|
||||
typedef struct q2entity_state_s
|
||||
{
|
||||
int number; // edict index
|
||||
|
@ -141,6 +143,8 @@ typedef struct q2entity_state_s
|
|||
// events only go out for a single frame, they
|
||||
// are automatically cleared each frame
|
||||
} q2entity_state_t;
|
||||
#endif
|
||||
#if defined(Q2SERVER)
|
||||
|
||||
|
||||
struct q2edict_s
|
||||
|
|
|
@ -660,6 +660,165 @@ void SWBE_ClearVBO(struct vbo_s *vbo)
|
|||
void SWBE_UploadAllLightmaps(void)
|
||||
{
|
||||
}
|
||||
static void SWR_RotateForEntity (float *m, float *modelview, const entity_t *e, const model_t *mod)
|
||||
{
|
||||
if ((e->flags & RF_WEAPONMODEL) && r_refdef.playerview->viewentity > 0)
|
||||
{
|
||||
float em[16];
|
||||
float vm[16];
|
||||
|
||||
if (e->flags & RF_WEAPONMODELNOBOB)
|
||||
{
|
||||
vm[0] = vpn[0];
|
||||
vm[1] = vpn[1];
|
||||
vm[2] = vpn[2];
|
||||
vm[3] = 0;
|
||||
|
||||
vm[4] = -vright[0];
|
||||
vm[5] = -vright[1];
|
||||
vm[6] = -vright[2];
|
||||
vm[7] = 0;
|
||||
|
||||
vm[8] = vup[0];
|
||||
vm[9] = vup[1];
|
||||
vm[10] = vup[2];
|
||||
vm[11] = 0;
|
||||
|
||||
vm[12] = r_refdef.vieworg[0];
|
||||
vm[13] = r_refdef.vieworg[1];
|
||||
vm[14] = r_refdef.vieworg[2];
|
||||
vm[15] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm[0] = r_refdef.playerview->vw_axis[0][0];
|
||||
vm[1] = r_refdef.playerview->vw_axis[0][1];
|
||||
vm[2] = r_refdef.playerview->vw_axis[0][2];
|
||||
vm[3] = 0;
|
||||
|
||||
vm[4] = r_refdef.playerview->vw_axis[1][0];
|
||||
vm[5] = r_refdef.playerview->vw_axis[1][1];
|
||||
vm[6] = r_refdef.playerview->vw_axis[1][2];
|
||||
vm[7] = 0;
|
||||
|
||||
vm[8] = r_refdef.playerview->vw_axis[2][0];
|
||||
vm[9] = r_refdef.playerview->vw_axis[2][1];
|
||||
vm[10] = r_refdef.playerview->vw_axis[2][2];
|
||||
vm[11] = 0;
|
||||
|
||||
vm[12] = r_refdef.playerview->vw_origin[0];
|
||||
vm[13] = r_refdef.playerview->vw_origin[1];
|
||||
vm[14] = r_refdef.playerview->vw_origin[2];
|
||||
vm[15] = 1;
|
||||
}
|
||||
|
||||
em[0] = e->axis[0][0];
|
||||
em[1] = e->axis[0][1];
|
||||
em[2] = e->axis[0][2];
|
||||
em[3] = 0;
|
||||
|
||||
em[4] = e->axis[1][0];
|
||||
em[5] = e->axis[1][1];
|
||||
em[6] = e->axis[1][2];
|
||||
em[7] = 0;
|
||||
|
||||
em[8] = e->axis[2][0];
|
||||
em[9] = e->axis[2][1];
|
||||
em[10] = e->axis[2][2];
|
||||
em[11] = 0;
|
||||
|
||||
em[12] = e->origin[0];
|
||||
em[13] = e->origin[1];
|
||||
em[14] = e->origin[2];
|
||||
em[15] = 1;
|
||||
|
||||
Matrix4_Multiply(vm, em, m);
|
||||
}
|
||||
else
|
||||
{
|
||||
m[0] = e->axis[0][0];
|
||||
m[1] = e->axis[0][1];
|
||||
m[2] = e->axis[0][2];
|
||||
m[3] = 0;
|
||||
|
||||
m[4] = e->axis[1][0];
|
||||
m[5] = e->axis[1][1];
|
||||
m[6] = e->axis[1][2];
|
||||
m[7] = 0;
|
||||
|
||||
m[8] = e->axis[2][0];
|
||||
m[9] = e->axis[2][1];
|
||||
m[10] = e->axis[2][2];
|
||||
m[11] = 0;
|
||||
|
||||
m[12] = e->origin[0];
|
||||
m[13] = e->origin[1];
|
||||
m[14] = e->origin[2];
|
||||
m[15] = 1;
|
||||
}
|
||||
|
||||
if (e->scale != 1 && e->scale != 0) //hexen 2 stuff
|
||||
{
|
||||
#ifdef HEXEN2
|
||||
float z;
|
||||
float escale;
|
||||
escale = e->scale;
|
||||
switch(e->drawflags&SCALE_TYPE_MASK)
|
||||
{
|
||||
default:
|
||||
case SCALE_TYPE_UNIFORM:
|
||||
VectorScale((m+0), escale, (m+0));
|
||||
VectorScale((m+4), escale, (m+4));
|
||||
VectorScale((m+8), escale, (m+8));
|
||||
break;
|
||||
case SCALE_TYPE_XYONLY:
|
||||
VectorScale((m+0), escale, (m+0));
|
||||
VectorScale((m+4), escale, (m+4));
|
||||
break;
|
||||
case SCALE_TYPE_ZONLY:
|
||||
VectorScale((m+8), escale, (m+8));
|
||||
break;
|
||||
}
|
||||
if (mod && (e->drawflags&SCALE_TYPE_MASK) != SCALE_TYPE_XYONLY)
|
||||
{
|
||||
switch(e->drawflags&SCALE_ORIGIN_MASK)
|
||||
{
|
||||
case SCALE_ORIGIN_CENTER:
|
||||
z = ((mod->maxs[2] + mod->mins[2]) * (1-escale))/2;
|
||||
VectorMA((m+12), z, e->axis[2], (m+12));
|
||||
break;
|
||||
case SCALE_ORIGIN_BOTTOM:
|
||||
VectorMA((m+12), mod->mins[2]*(1-escale), e->axis[2], (m+12));
|
||||
break;
|
||||
case SCALE_ORIGIN_TOP:
|
||||
VectorMA((m+12), -mod->maxs[2], e->axis[2], (m+12));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
VectorScale((m+0), e->scale, (m+0));
|
||||
VectorScale((m+4), e->scale, (m+4));
|
||||
VectorScale((m+8), e->scale, (m+8));
|
||||
#endif
|
||||
}
|
||||
else if (mod && !strcmp(mod->name, "progs/eyes.mdl"))
|
||||
{
|
||||
/*resize eyes, to make them easier to see*/
|
||||
m[14] -= (22 + 8);
|
||||
VectorScale((m+0), 2, (m+0));
|
||||
VectorScale((m+4), 2, (m+4));
|
||||
VectorScale((m+8), 2, (m+8));
|
||||
}
|
||||
if (mod && !ruleset_allow_larger_models.ival && mod->clampscale != 1 && mod->type == mod_alias)
|
||||
{ //possibly this should be on a per-frame basis, but that's a real pain to do
|
||||
Con_DPrintf("Rescaling %s by %f\n", mod->name, mod->clampscale);
|
||||
VectorScale((m+0), mod->clampscale, (m+0));
|
||||
VectorScale((m+4), mod->clampscale, (m+4));
|
||||
VectorScale((m+8), mod->clampscale, (m+8));
|
||||
}
|
||||
|
||||
Matrix4_Multiply(r_refdef.m_view, m, modelview);
|
||||
}
|
||||
void SWBE_SelectEntity(struct entity_s *ent)
|
||||
{
|
||||
float modelmatrix[16];
|
||||
|
@ -670,7 +829,7 @@ void SWBE_SelectEntity(struct entity_s *ent)
|
|||
return;
|
||||
shaderstate.curentity = ent;
|
||||
|
||||
R_RotateForEntity(modelmatrix, modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model);
|
||||
SWR_RotateForEntity(modelmatrix, modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model);
|
||||
Matrix4_Multiply(r_refdef.m_projection, modelviewmatrix, shaderstate.m_mvp);
|
||||
shaderstate.viewplane[0] = vpn[0];//-modelviewmatrix[0];//0*4+2];
|
||||
shaderstate.viewplane[1] = vpn[1];//-modelviewmatrix[1];//1*4+2];
|
||||
|
|
365
engine/sw/sw_viddos.c
Normal file
365
engine/sw/sw_viddos.c
Normal file
|
@ -0,0 +1,365 @@
|
|||
#include "quakedef.h"
|
||||
#ifdef SWQUAKE
|
||||
#include "sw.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* from http://www.delorie.com/djgpp/doc/ug/graphics/vesa.html */
|
||||
typedef struct VESA_INFO
|
||||
{
|
||||
unsigned char VESASignature[4];
|
||||
unsigned short VESAVersion __attribute__ ((packed));
|
||||
unsigned long OEMStringPtr __attribute__ ((packed));
|
||||
unsigned char Capabilities[4];
|
||||
unsigned long VideoModePtr __attribute__ ((packed));
|
||||
unsigned short TotalMemory __attribute__ ((packed));
|
||||
unsigned short OemSoftwareRev __attribute__ ((packed));
|
||||
unsigned long OemVendorNamePtr __attribute__ ((packed));
|
||||
unsigned long OemProductNamePtr __attribute__ ((packed));
|
||||
unsigned long OemProductRevPtr __attribute__ ((packed));
|
||||
unsigned char Reserved[222];
|
||||
unsigned char OemData[256];
|
||||
} VESA_INFO;
|
||||
|
||||
|
||||
|
||||
#include <dpmi.h>
|
||||
#include <go32.h>
|
||||
#include <sys/farptr.h>
|
||||
|
||||
|
||||
static VESA_INFO vesa_info;
|
||||
|
||||
|
||||
static int get_vesa_info()
|
||||
{
|
||||
__dpmi_regs r;
|
||||
long dosbuf;
|
||||
int c;
|
||||
|
||||
/* use the conventional memory transfer buffer */
|
||||
dosbuf = __tb & 0xFFFFF;
|
||||
|
||||
/* initialize the buffer to zero */
|
||||
for (c=0; c<sizeof(VESA_INFO); c++)
|
||||
_farpokeb(_dos_ds, dosbuf+c, 0);
|
||||
|
||||
dosmemput("VBE2", 4, dosbuf);
|
||||
|
||||
/* call the VESA function */
|
||||
r.x.ax = 0x4F00;
|
||||
r.x.di = dosbuf & 0xF;
|
||||
r.x.es = (dosbuf>>4) & 0xFFFF;
|
||||
__dpmi_int(0x10, &r);
|
||||
|
||||
/* quit if there was an error */
|
||||
if (r.h.ah)
|
||||
return -1;
|
||||
|
||||
/* copy the resulting data into our structure */
|
||||
dosmemget(dosbuf, sizeof(VESA_INFO), &vesa_info);
|
||||
|
||||
/* check that we got the right magic marker value */
|
||||
if (strncmp(vesa_info.VESASignature, "VESA", 4) != 0)
|
||||
return -1;
|
||||
|
||||
/* it worked! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct MODE_INFO
|
||||
{
|
||||
unsigned short ModeAttributes __attribute__ ((packed));
|
||||
unsigned char WinAAttributes;
|
||||
unsigned char WinBAttributes;
|
||||
unsigned short WinGranularity __attribute__ ((packed));
|
||||
unsigned short WinSize __attribute__ ((packed));
|
||||
unsigned short WinASegment __attribute__ ((packed));
|
||||
unsigned short WinBSegment __attribute__ ((packed));
|
||||
unsigned long WinFuncPtr __attribute__ ((packed));
|
||||
unsigned short BytesPerScanLine __attribute__ ((packed));
|
||||
unsigned short XResolution __attribute__ ((packed));
|
||||
unsigned short YResolution __attribute__ ((packed));
|
||||
unsigned char XCharSize;
|
||||
unsigned char YCharSize;
|
||||
unsigned char NumberOfPlanes;
|
||||
unsigned char BitsPerPixel;
|
||||
unsigned char NumberOfBanks;
|
||||
unsigned char MemoryModel;
|
||||
unsigned char BankSize;
|
||||
unsigned char NumberOfImagePages;
|
||||
unsigned char Reserved_page;
|
||||
unsigned char RedMaskSize;
|
||||
unsigned char RedMaskPos;
|
||||
unsigned char GreenMaskSize;
|
||||
unsigned char GreenMaskPos;
|
||||
unsigned char BlueMaskSize;
|
||||
unsigned char BlueMaskPos;
|
||||
unsigned char ReservedMaskSize;
|
||||
unsigned char ReservedMaskPos;
|
||||
unsigned char DirectColorModeInfo;
|
||||
unsigned long PhysBasePtr __attribute__ ((packed));
|
||||
unsigned long OffScreenMemOffset __attribute__ ((packed));
|
||||
unsigned short OffScreenMemSize __attribute__ ((packed));
|
||||
unsigned char Reserved[206];
|
||||
} MODE_INFO;
|
||||
|
||||
|
||||
static MODE_INFO mode_info;
|
||||
|
||||
|
||||
static int get_mode_info(int mode)
|
||||
{
|
||||
__dpmi_regs r;
|
||||
long dosbuf;
|
||||
int c;
|
||||
|
||||
/* use the conventional memory transfer buffer */
|
||||
dosbuf = __tb & 0xFFFFF;
|
||||
|
||||
/* initialize the buffer to zero */
|
||||
for (c=0; c<sizeof(MODE_INFO); c++)
|
||||
_farpokeb(_dos_ds, dosbuf+c, 0);
|
||||
|
||||
/* call the VESA function */
|
||||
r.x.ax = 0x4F01;
|
||||
r.x.di = dosbuf & 0xF;
|
||||
r.x.es = (dosbuf>>4) & 0xFFFF;
|
||||
r.x.cx = mode;
|
||||
__dpmi_int(0x10, &r);
|
||||
|
||||
/* quit if there was an error */
|
||||
if (r.h.ah)
|
||||
return -1;
|
||||
|
||||
/* copy the resulting data into our structure */
|
||||
dosmemget(dosbuf, sizeof(MODE_INFO), &mode_info);
|
||||
|
||||
/* it worked! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int find_vesa_mode(int w, int h, int bpp)
|
||||
{
|
||||
int mode_list[256];
|
||||
int number_of_modes;
|
||||
long mode_ptr;
|
||||
int c;
|
||||
|
||||
/* check that the VESA driver exists, and get information about it */
|
||||
if (get_vesa_info() != 0)
|
||||
return 0;
|
||||
|
||||
/* convert the mode list pointer from seg:offset to a linear address */
|
||||
mode_ptr = ((vesa_info.VideoModePtr & 0xFFFF0000) >> 12) + (vesa_info.VideoModePtr & 0xFFFF);
|
||||
|
||||
number_of_modes = 0;
|
||||
|
||||
/* read the list of available modes */
|
||||
while (_farpeekw(_dos_ds, mode_ptr) != 0xFFFF)
|
||||
{
|
||||
mode_list[number_of_modes] = _farpeekw(_dos_ds, mode_ptr);
|
||||
number_of_modes++;
|
||||
mode_ptr += 2;
|
||||
}
|
||||
|
||||
/* scan through the list of modes looking for the one that we want */
|
||||
for (c=0; c<number_of_modes; c++)
|
||||
{
|
||||
/* get information about this mode */
|
||||
if (get_mode_info(mode_list[c]) != 0)
|
||||
continue;
|
||||
|
||||
/* check the flags field to make sure this is a color graphics mode,
|
||||
* and that it is supported by the current hardware */
|
||||
if ((mode_info.ModeAttributes & 0x19) != 0x19)
|
||||
continue;
|
||||
|
||||
/* check that this mode is the right size */
|
||||
if ((mode_info.XResolution != w) || (mode_info.YResolution != h))
|
||||
continue;
|
||||
|
||||
/* check that there is only one color plane */
|
||||
if (mode_info.NumberOfPlanes != 1)
|
||||
continue;
|
||||
|
||||
/* check that it is a packed-pixel mode (other values are used for
|
||||
* different memory layouts, eg. 6 for a truecolor resolution) */
|
||||
if (mode_info.MemoryModel != ((bpp==8)?4:6))
|
||||
continue;
|
||||
|
||||
/* check that this is an 8-bit (256 color) mode */
|
||||
if (mode_info.BitsPerPixel != bpp)
|
||||
continue;
|
||||
|
||||
/* if it passed all those checks, this must be the mode we want! */
|
||||
return mode_list[c];
|
||||
}
|
||||
|
||||
/* oh dear, there was no mode matching the one we wanted! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int set_vesa_mode(int w, int h, int bpp)
|
||||
{
|
||||
__dpmi_regs r;
|
||||
int mode_number;
|
||||
|
||||
/* find the number for this mode */
|
||||
mode_number = find_vesa_mode(w, h, bpp);
|
||||
if (!mode_number)
|
||||
return -1;
|
||||
|
||||
/* call the VESA mode set function */
|
||||
r.x.ax = 0x4F02;
|
||||
r.x.bx = mode_number;
|
||||
__dpmi_int(0x10, &r);
|
||||
if (r.h.ah)
|
||||
return -1;
|
||||
|
||||
/* it worked! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_vesa_bank(int bank_number)
|
||||
{
|
||||
__dpmi_regs r;
|
||||
|
||||
r.x.ax = 0x4F05;
|
||||
r.x.bx = 0;
|
||||
r.x.dx = bank_number;
|
||||
__dpmi_int(0x10, &r);
|
||||
}
|
||||
|
||||
static void copy_to_vesa_screen(char *memory_buffer, int screen_size)
|
||||
{
|
||||
//FIXME: use OffScreenMemOffset if possible.
|
||||
|
||||
int bank_size = mode_info.WinSize*1024;
|
||||
int bank_granularity = mode_info.WinGranularity*1024;
|
||||
int bank_number = 0;
|
||||
int todo = screen_size;
|
||||
int copy_size;
|
||||
|
||||
while (todo > 0)
|
||||
{
|
||||
/* select the appropriate bank */
|
||||
set_vesa_bank(bank_number);
|
||||
|
||||
/* how much can we copy in one go? */
|
||||
if (todo > bank_size)
|
||||
copy_size = bank_size;
|
||||
else
|
||||
copy_size = todo;
|
||||
|
||||
/* copy a bank of data to the screen */
|
||||
dosmemput(memory_buffer, copy_size, 0xA0000);
|
||||
|
||||
/* move on to the next bank of data */
|
||||
todo -= copy_size;
|
||||
memory_buffer += copy_size;
|
||||
bank_number += bank_size/bank_granularity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern int nostdout; //we flag with 0x800 to disable printfs while displaying stuff.
|
||||
static qboolean videoatexitregistered;
|
||||
static void videoatexit(void)
|
||||
{
|
||||
if (nostdout & 0x800)
|
||||
{
|
||||
nostdout &= ~0x800;
|
||||
|
||||
__dpmi_regs r;
|
||||
r.x.ax = 0x0000 | 3;
|
||||
__dpmi_int(0x10, &r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned int *backbuffer;
|
||||
static unsigned int *depthbuffer;
|
||||
static unsigned int framenumber;
|
||||
|
||||
//#define NORENDER
|
||||
|
||||
qboolean SW_VID_Init(rendererstate_t *info, unsigned char *palette)
|
||||
{
|
||||
int bpp = info->bpp;
|
||||
vid.pixelwidth = info->width;
|
||||
vid.pixelheight = info->height;
|
||||
|
||||
if (bpp != 32)
|
||||
bpp = 32; //sw renderer supports only this
|
||||
|
||||
#ifndef NORENDER
|
||||
nostdout |= 0x800;
|
||||
if (set_vesa_mode(vid.pixelwidth, vid.pixelheight, bpp) < 0)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!videoatexitregistered)
|
||||
{
|
||||
videoatexitregistered = true;
|
||||
atexit(videoatexit);
|
||||
}
|
||||
|
||||
backbuffer = BZ_Malloc(vid.pixelwidth * vid.pixelheight * sizeof(*backbuffer));
|
||||
if (!backbuffer)
|
||||
return false;
|
||||
depthbuffer = BZ_Malloc(vid.pixelwidth * vid.pixelheight * sizeof(*depthbuffer));
|
||||
if (!depthbuffer)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void SW_VID_DeInit(void)
|
||||
{
|
||||
BZ_Free(backbuffer);
|
||||
backbuffer = NULL;
|
||||
BZ_Free(depthbuffer);
|
||||
depthbuffer = NULL;
|
||||
}
|
||||
qboolean SW_VID_ApplyGammaRamps (unsigned int rampcount, unsigned short *ramps)
|
||||
{ //no gamma ramps with VESA.
|
||||
return false;
|
||||
}
|
||||
char *SW_VID_GetRGBInfo(int *bytestride, int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
|
||||
{
|
||||
void *ret = BZ_Malloc(vid.pixelwidth*vid.pixelheight*4);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
memcpy(ret, backbuffer, vid.pixelwidth*vid.pixelheight*4);
|
||||
*bytestride = vid.pixelwidth*4;
|
||||
*truevidwidth = vid.pixelwidth;
|
||||
*truevidheight = vid.pixelheight;
|
||||
*fmt = TF_BGRX32;
|
||||
return ret;
|
||||
}
|
||||
void SW_VID_SetWindowCaption(const char *msg)
|
||||
{
|
||||
}
|
||||
void SW_VID_SwapBuffers(void)
|
||||
{
|
||||
#ifndef NORENDER
|
||||
copy_to_vesa_screen((char*)backbuffer, vid.pixelwidth*vid.pixelheight*4);
|
||||
#endif
|
||||
framenumber++;
|
||||
}
|
||||
void SW_VID_UpdateViewport(wqcom_t *com)
|
||||
{
|
||||
com->viewport.cbuf = backbuffer + vid.pixelwidth*(vid.pixelheight-1);
|
||||
com->viewport.dbuf = depthbuffer;
|
||||
com->viewport.width = vid.pixelwidth;
|
||||
com->viewport.height = vid.pixelheight;
|
||||
com->viewport.stride = -vid.pixelwidth; //this is in pixels. which is stupid.
|
||||
com->viewport.framenum = framenumber;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue