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:
Spoike 2017-05-19 03:32:02 +00:00
parent 5d2ff1286d
commit 445e7f476b
15 changed files with 1859 additions and 473 deletions

View file

@ -289,6 +289,12 @@ ifeq ($(FTE_TARGET),morphos)
endif endif
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 #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) ifeq ($(FTE_TARGET),linux32)
FTE_TARGET=linux FTE_TARGET=linux
@ -360,6 +366,7 @@ CLIENT_DIR=$(BASE_DIR)/client
GL_DIR=$(BASE_DIR)/gl GL_DIR=$(BASE_DIR)/gl
D3D_DIR=$(BASE_DIR)/d3d D3D_DIR=$(BASE_DIR)/d3d
VK_DIR=$(BASE_DIR)/vk VK_DIR=$(BASE_DIR)/vk
SW_DIR=$(BASE_DIR)/sw
SERVER_DIR=$(BASE_DIR)/server SERVER_DIR=$(BASE_DIR)/server
COMMON_DIR=$(BASE_DIR)/common COMMON_DIR=$(BASE_DIR)/common
HTTP_DIR=$(BASE_DIR)/http HTTP_DIR=$(BASE_DIR)/http
@ -399,6 +406,9 @@ endif
ifeq ($(FTE_TARGET),cyg) ifeq ($(FTE_TARGET),cyg)
BASELDFLAGS=-lm BASELDFLAGS=-lm
endif endif
ifeq ($(FTE_TARGET),dos)
BASELDFLAGS=-lm
endif
ifeq ($(FTE_TARGET),morphos) ifeq ($(FTE_TARGET),morphos)
BASELDFLAGS=-lm BASELDFLAGS=-lm
endif endif
@ -1369,6 +1379,30 @@ ifeq ($(FTE_TARGET),morphos)
SV_CFLAGS=$(SERVER_ONLY_CFLAGS) SV_CFLAGS=$(SERVER_ONLY_CFLAGS)
endif 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) ifeq ($(FTE_TARGET),cyg)
SV_DIR=sv_cygwin SV_DIR=sv_cygwin
@ -1510,7 +1544,7 @@ ifneq ($(OUT_DIR),)
endif 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)),) ifneq ($(findstring -DSPEEX_STATIC, $(CFLAGS)),)
#add these to statically link libspeex #add these to statically link libspeex

View file

@ -1,452 +1,465 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code. This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as 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, published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=========================================================================== ===========================================================================
*/ */
#ifndef __Q_PLATFORM_H #ifndef __Q_PLATFORM_H
#define __Q_PLATFORM_H #define __Q_PLATFORM_H
// this is for determining if we have an asm version of a C function // this is for determining if we have an asm version of a C function
#define idx64 0 #define idx64 0
#ifdef Q3_VM #ifdef Q3_VM
#define id386 0 #define id386 0
#define idppc 0 #define idppc 0
#define idppc_altivec 0 #define idppc_altivec 0
#define idsparc 0 #define idsparc 0
#else #else
#if (defined _M_IX86 || defined __i386__) && !defined(C_ONLY) #if (defined _M_IX86 || defined __i386__) && !defined(C_ONLY)
#define id386 1 #define id386 1
#else #else
#define id386 0 #define id386 0
#endif #endif
#if (defined(powerc) || defined(powerpc) || defined(ppc) || \ #if (defined(powerc) || defined(powerpc) || defined(ppc) || \
defined(__ppc) || defined(__ppc__)) && !defined(C_ONLY) defined(__ppc) || defined(__ppc__)) && !defined(C_ONLY)
#define idppc 1 #define idppc 1
#if defined(__VEC__) #if defined(__VEC__)
#define idppc_altivec 1 #define idppc_altivec 1
#ifdef MACOS_X // Apple's GCC does this differently than the FSF. #ifdef MACOS_X // Apple's GCC does this differently than the FSF.
#define VECCONST_UINT8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ #define VECCONST_UINT8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
(vector unsigned char) (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) (vector unsigned char) (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
#else #else
#define VECCONST_UINT8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ #define VECCONST_UINT8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
(vector unsigned char) {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p} (vector unsigned char) {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}
#endif #endif
#else #else
#define idppc_altivec 0 #define idppc_altivec 0
#endif #endif
#else #else
#define idppc 0 #define idppc 0
#define idppc_altivec 0 #define idppc_altivec 0
#endif #endif
#if defined(__sparc__) && !defined(C_ONLY) #if defined(__sparc__) && !defined(C_ONLY)
#define idsparc 1 #define idsparc 1
#else #else
#define idsparc 0 #define idsparc 0
#endif #endif
#endif #endif
#ifndef __ASM_I386__ // don't include the C bits if included from qasm.h #ifndef __ASM_I386__ // don't include the C bits if included from qasm.h
// for windows fastcall option // for windows fastcall option
#define QDECL #define QDECL
//================================================================= WIN64/32 === //================================================================= WIN64/32 ===
#if defined(_WIN64) || defined(__WIN64__) #if defined(_WIN64) || defined(__WIN64__)
#undef idx64 #undef idx64
#define idx64 1 #define idx64 1
#undef QDECL #undef QDECL
#define QDECL __cdecl #define QDECL __cdecl
#if defined( _MSC_VER ) #if defined( _MSC_VER )
#define OS_STRING "win_msvc64" #define OS_STRING "win_msvc64"
#elif defined __MINGW64__ #elif defined __MINGW64__
#define OS_STRING "win_mingw64" #define OS_STRING "win_mingw64"
#else #else
#define OS_STRING "win64" #define OS_STRING "win64"
#endif #endif
#define ID_INLINE static __inline #define ID_INLINE static __inline
#define PATH_SEP '\\' #define PATH_SEP '\\'
#if defined( __WIN64__ ) #if defined( __WIN64__ )
#define ARCH_STRING "x86_64" #define ARCH_STRING "x86_64"
#elif defined _M_ALPHA #elif defined _M_ALPHA
#define ARCH_STRING "AXP" #define ARCH_STRING "AXP"
#endif #endif
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#define DLL_EXT ".dll" #define DLL_EXT ".dll"
#elif defined(_WIN32) || defined(__WIN32__) #elif defined(_WIN32) || defined(__WIN32__)
#undef QDECL #undef QDECL
#define QDECL __cdecl #define QDECL __cdecl
#if defined( _MSC_VER ) #if defined( _MSC_VER )
#define OS_STRING "win_msvc" #define OS_STRING "win_msvc"
#elif defined __MINGW32__ #elif defined __MINGW32__
#define OS_STRING "win_mingw" #define OS_STRING "win_mingw"
#endif #endif
#define ID_INLINE static __inline #define ID_INLINE static __inline
#define PATH_SEP '\\' #define PATH_SEP '\\'
#if defined( _M_IX86 ) || defined( __i386__ ) #if defined( _M_IX86 ) || defined( __i386__ )
#define ARCH_STRING "x86" #define ARCH_STRING "x86"
#elif defined _M_ALPHA #elif defined _M_ALPHA
#define ARCH_STRING "AXP" #define ARCH_STRING "AXP"
#endif #endif
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#define DLL_EXT ".dll" #define DLL_EXT ".dll"
#endif #endif
//============================================================== MAC OS X === //============================================================== MAC OS X ===
#if defined(MACOS_X) || defined(__APPLE_CC__) #if defined(MACOS_X) || defined(__APPLE_CC__)
// make sure this is defined, just for sanity's sake... // make sure this is defined, just for sanity's sake...
#ifndef MACOS_X #ifndef MACOS_X
#define MACOS_X #define MACOS_X
#endif #endif
#define OS_STRING "macosx" #define OS_STRING "macosx"
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#ifdef __ppc__ #ifdef __ppc__
#define ARCH_STRING "ppc" #define ARCH_STRING "ppc"
#define Q3_BIG_ENDIAN #define Q3_BIG_ENDIAN
#elif defined __i386__ #elif defined __i386__
#define ARCH_STRING "i386" #define ARCH_STRING "i386"
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#elif defined __x86_64__ #elif defined __x86_64__
#undef idx64 #undef idx64
#define idx64 1 #define idx64 1
#define ARCH_STRING "x86_64" #define ARCH_STRING "x86_64"
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#endif #endif
#define DLL_EXT ".dylib" #define DLL_EXT ".dylib"
#endif #endif
//================================================================= LINUX === //================================================================= LINUX ===
#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(ANDROID) || defined(__ANDROID__) #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(ANDROID) || defined(__ANDROID__)
#include <endian.h> #include <endian.h>
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
#define OS_STRING "android" #define OS_STRING "android"
#elif defined(__linux__) #elif defined(__linux__)
#define OS_STRING "linux" #define OS_STRING "linux"
#else #else
#define OS_STRING "kFreeBSD" #define OS_STRING "kFreeBSD"
#endif #endif
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#if defined __i386__ #if defined __i386__
#define ARCH_STRING "i386" #define ARCH_STRING "i386"
#elif defined __x86_64__ #elif defined __x86_64__
#undef idx64 #undef idx64
#define idx64 1 #define idx64 1
#define ARCH_STRING "x86_64" #define ARCH_STRING "x86_64"
#elif defined __powerpc64__ #elif defined __powerpc64__
#define ARCH_STRING "ppc64" #define ARCH_STRING "ppc64"
#elif defined __powerpc__ #elif defined __powerpc__
#define ARCH_STRING "ppc" #define ARCH_STRING "ppc"
#elif defined __s390__ #elif defined __s390__
#define ARCH_STRING "s390" #define ARCH_STRING "s390"
#elif defined __s390x__ #elif defined __s390x__
#define ARCH_STRING "s390x" #define ARCH_STRING "s390x"
#elif defined __ia64__ #elif defined __ia64__
#define ARCH_STRING "ia64" #define ARCH_STRING "ia64"
#elif defined __alpha__ #elif defined __alpha__
#define ARCH_STRING "alpha" #define ARCH_STRING "alpha"
#elif defined __sparc__ #elif defined __sparc__
#define ARCH_STRING "sparc" #define ARCH_STRING "sparc"
#elif defined __arm__ #elif defined __arm__
#define ARCH_STRING "arm" #define ARCH_STRING "arm"
#elif defined __cris__ #elif defined __cris__
#define ARCH_STRING "cris" #define ARCH_STRING "cris"
#elif defined __hppa__ #elif defined __hppa__
#define ARCH_STRING "hppa" #define ARCH_STRING "hppa"
#elif defined __mips__ #elif defined __mips__
#define ARCH_STRING "mips" #define ARCH_STRING "mips"
#elif defined __sh__ #elif defined __sh__
#define ARCH_STRING "sh" #define ARCH_STRING "sh"
#endif #endif
#if __FLOAT_WORD_ORDER == __BIG_ENDIAN #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
#define Q3_BIG_ENDIAN #define Q3_BIG_ENDIAN
#else #else
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#endif #endif
#define DLL_EXT ".so" #define DLL_EXT ".so"
#endif #endif
//=================================================================== BSD === //=================================================================== BSD ===
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/types.h> #include <sys/types.h>
#include <machine/endian.h> #include <machine/endian.h>
#ifndef __BSD__ #ifndef __BSD__
#define __BSD__ #define __BSD__
#endif #endif
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#define OS_STRING "freebsd" #define OS_STRING "freebsd"
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
#define OS_STRING "openbsd" #define OS_STRING "openbsd"
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
#define OS_STRING "netbsd" #define OS_STRING "netbsd"
#endif #endif
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#ifdef __i386__ #ifdef __i386__
#define ARCH_STRING "i386" #define ARCH_STRING "i386"
#elif defined __amd64__ #elif defined __amd64__
#undef idx64 #undef idx64
#define idx64 1 #define idx64 1
#define ARCH_STRING "amd64" #define ARCH_STRING "amd64"
#elif defined __axp__ #elif defined __axp__
#define ARCH_STRING "alpha" #define ARCH_STRING "alpha"
#endif #endif
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
#define Q3_BIG_ENDIAN #define Q3_BIG_ENDIAN
#else #else
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#endif #endif
#define DLL_EXT ".so" #define DLL_EXT ".so"
#endif #endif
//================================================================= SUNOS === //================================================================= SUNOS ===
#ifdef __sun #ifdef __sun
#include <stdint.h> #include <stdint.h>
#include <sys/byteorder.h> #include <sys/byteorder.h>
#define OS_STRING "solaris" #define OS_STRING "solaris"
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#ifdef __i386__ #ifdef __i386__
#define ARCH_STRING "i386" #define ARCH_STRING "i386"
#elif defined __sparc #elif defined __sparc
#define ARCH_STRING "sparc" #define ARCH_STRING "sparc"
#endif #endif
#if defined( _BIG_ENDIAN ) #if defined( _BIG_ENDIAN )
#define Q3_BIG_ENDIAN #define Q3_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN ) #elif defined( _LITTLE_ENDIAN )
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#endif #endif
#define DLL_EXT ".so" #define DLL_EXT ".so"
#endif #endif
//================================================================== IRIX === //================================================================== IRIX ===
#ifdef __sgi #ifdef __sgi
#define OS_STRING "irix" #define OS_STRING "irix"
#define ID_INLINE static __inline #define ID_INLINE static __inline
#define PATH_SEP '/' #define PATH_SEP '/'
#define ARCH_STRING "mips" #define ARCH_STRING "mips"
#define Q3_BIG_ENDIAN // SGI's MIPS are always big endian #define Q3_BIG_ENDIAN // SGI's MIPS are always big endian
#define DLL_EXT ".so" #define DLL_EXT ".so"
#endif #endif
//=============================================================== MORPHOS === //=============================================================== MORPHOS ===
#ifdef __MORPHOS__ #ifdef __MORPHOS__
#define OS_STRING "morphos" #define OS_STRING "morphos"
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#define ARCH_STRING "ppc" #define ARCH_STRING "ppc"
#define Q3_BIG_ENDIAN #define Q3_BIG_ENDIAN
#define DLL_EXT ".so" #define DLL_EXT ".so"
#endif #endif
#ifdef __CYGWIN__ #ifdef __CYGWIN__
#define OS_STRING "cygwin" #define OS_STRING "cygwin"
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#define ARCH_STRING "x86" #define ARCH_STRING "x86"
#define Q3_BIG_ENDIAN #define Q3_LITTLE_ENDIAN
#define DLL_EXT ".dll" #define DLL_EXT ".dll"
#endif #endif
#ifdef FTE_TARGET_WEB #ifdef __DJGPP__
#define OS_STRING "emscripten" #define OS_STRING "msdos"
#define ID_INLINE static inline #define ID_INLINE static inline
#define PATH_SEP '/' #define PATH_SEP '/'
#define ARCH_STRING "web" #define ARCH_STRING "dos"
#define Q3_LITTLE_ENDIAN #define Q3_LITTLE_ENDIAN
#define DLL_EXT ".so" #define DLL_EXT ".dll"
#endif #endif
#ifdef NACL
#define OS_STRING "nacl" #ifdef FTE_TARGET_WEB
#define ID_INLINE static inline #define OS_STRING "emscripten"
#define PATH_SEP '/' #define ID_INLINE static inline
#define PATH_SEP '/'
#define ARCH_STRING "web"
#define ARCH_STRING "web"
#define Q3_LITTLE_ENDIAN
#define Q3_LITTLE_ENDIAN
#define DLL_EXT ".so"
#endif #define DLL_EXT ".so"
#endif
//================================================================== Q3VM ===
#ifdef NACL
#ifdef Q3_VM #define OS_STRING "nacl"
#define ID_INLINE static inline
#define OS_STRING "q3vm" #define PATH_SEP '/'
#define ID_INLINE static
#define PATH_SEP '/' #define ARCH_STRING "web"
#define ARCH_STRING "bytecode" #define Q3_LITTLE_ENDIAN
#define DLL_EXT ".qvm" #define DLL_EXT ".so"
#endif
#endif
//================================================================== Q3VM ===
//===========================================================================
#ifdef Q3_VM
//catch missing defines in above blocks
#if !defined( OS_STRING ) #define OS_STRING "q3vm"
#define ARCH_STRING "unknown" #define ID_INLINE static
//#error "Operating system not supported" #define PATH_SEP '/'
#endif
#define ARCH_STRING "bytecode"
#if !defined( ARCH_STRING )
#define ARCH_STRING "unk" #define DLL_EXT ".qvm"
//#error "Architecture not supported"
#endif #endif
#ifndef ID_INLINE //===========================================================================
#define ID_INLINE static
//#error "ID_INLINE not defined" //catch missing defines in above blocks
#endif #if !defined( OS_STRING )
#define ARCH_STRING "unknown"
#ifndef PATH_SEP //#error "Operating system not supported"
#define PATH_SEP '/' #endif
//#error "PATH_SEP not defined"
#endif #if !defined( ARCH_STRING )
#define ARCH_STRING "unk"
#ifndef DLL_EXT //#error "Architecture not supported"
#define DLL_EXT ".so" #endif
//#error "DLL_EXT not defined"
#endif #ifndef ID_INLINE
#define ID_INLINE static
//#error "ID_INLINE not defined"
//endianness #endif
short ShortSwap (short l);
int LongSwap (int l); #ifndef PATH_SEP
float FloatSwap (const float *f); #define PATH_SEP '/'
//#error "PATH_SEP not defined"
#if defined( Q3_BIG_ENDIAN ) && defined( Q3_LITTLE_ENDIAN ) #endif
#error "Endianness defined as both big and little"
#elif defined( Q3_BIG_ENDIAN ) #ifndef DLL_EXT
#define DLL_EXT ".so"
#define LittleShort(x) ShortSwap(x) //#error "DLL_EXT not defined"
#define LittleLong(x) LongSwap(x) #endif
#define LittleFloat(x) FloatSwap(&x)
#define BigShort
#define BigLong //endianness
#define BigFloat short ShortSwap (short l);
int LongSwap (int l);
#elif defined( Q3_LITTLE_ENDIAN ) float FloatSwap (const float *f);
#define LittleShort #if defined( Q3_BIG_ENDIAN ) && defined( Q3_LITTLE_ENDIAN )
#define LittleLong #error "Endianness defined as both big and little"
#define LittleFloat #elif defined( Q3_BIG_ENDIAN )
#define BigShort(x) ShortSwap(x)
#define BigLong(x) LongSwap(x) #define LittleShort(x) ShortSwap(x)
#define BigFloat(x) FloatSwap(&x) #define LittleLong(x) LongSwap(x)
#define LittleFloat(x) FloatSwap(&x)
#elif defined( Q3_VM ) #define BigShort
#define BigLong
#define LittleShort #define BigFloat
#define LittleLong
#define LittleFloat #elif defined( Q3_LITTLE_ENDIAN )
#define BigShort
#define BigLong #define LittleShort
#define BigFloat #define LittleLong
#define LittleFloat
#else #define BigShort(x) ShortSwap(x)
#error "Endianness not defined" #define BigLong(x) LongSwap(x)
#endif #define BigFloat(x) FloatSwap(&x)
#elif defined( Q3_VM )
//platform string
#ifdef NDEBUG #define LittleShort
#define PLATFORM_STRING OS_STRING "-" ARCH_STRING #define LittleLong
#else #define LittleFloat
#define PLATFORM_STRING OS_STRING "-" ARCH_STRING "-debug" #define BigShort
#endif #define BigLong
#define BigFloat
#endif
#else
#endif #error "Endianness not defined"
#endif
//platform string
#ifdef NDEBUG
#define PLATFORM_STRING OS_STRING "-" ARCH_STRING
#else
#define PLATFORM_STRING OS_STRING "-" ARCH_STRING "-debug"
#endif
#endif
#endif

View file

@ -91,7 +91,13 @@ cvar_t snd_noextraupdate = CVARAF( "s_noextraupdate", "0",
"snd_noextraupdate", 0); "snd_noextraupdate", 0);
cvar_t snd_show = CVARAF( "s_show", "0", cvar_t snd_show = CVARAF( "s_show", "0",
"snd_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."); "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", cvar_t snd_inactive = CVARAFD( "s_inactive", "1",
"snd_inactive", CVAR_ARCHIVE, "snd_inactive", CVAR_ARCHIVE,
@ -1507,11 +1513,16 @@ extern sounddriver_t XAUDIO2_Output;
extern sounddriver_t DSOUND_Output; extern sounddriver_t DSOUND_Output;
#endif #endif
sounddriver_t SDL_Output; sounddriver_t SDL_Output;
#ifdef __linux__
sounddriver_t ALSA_Output; sounddriver_t ALSA_Output;
#endif
sounddriver_t OSS_Output; sounddriver_t OSS_Output;
#ifdef AVAIL_OPENAL #ifdef AVAIL_OPENAL
extern sounddriver_t OPENAL_Output; extern sounddriver_t OPENAL_Output;
#endif #endif
#ifdef __DJGPP__
extern sounddriver_t SBLASTER_Output;
#endif
sounddriver pSNDIO_InitCard; sounddriver pSNDIO_InitCard;
sounddriver pOSS_InitCard; sounddriver pOSS_InitCard;
@ -1546,6 +1557,9 @@ static sounddriver_t *outputdrivers[] =
&ALSA_Output, //pure shite &ALSA_Output, //pure shite
#endif #endif
&OSS_Output, //good, but not likely to work any more &OSS_Output, //good, but not likely to work any more
#ifdef __DJGPP__
&SBLASTER_Output, //zomgwtfdos?
#endif
NULL NULL
}; };
typedef struct { typedef struct {

View 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
View 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, &regs);
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);
}

View file

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdio.h> #include <stdio.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <dirent.h> #include <dirent.h>
#ifndef __CYGWIN__ #if !defined(__CYGWIN__) && !defined(__DJGPP__)
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
#endif #endif
@ -46,7 +46,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <errno.h> #include <errno.h>
#ifndef __MACOSX__ #if !defined(__MACOSX__) && !defined(__DJGPP__)
#include <X11/Xlib.h> #include <X11/Xlib.h>
#endif #endif
#ifdef MULTITHREAD #ifdef MULTITHREAD
@ -255,8 +255,10 @@ void Sys_Printf (char *fmt, ...)
void Sys_Quit (void) void Sys_Quit (void)
{ {
Host_Shutdown(); Host_Shutdown();
#ifndef __DJGPP__
if (!noconinput) if (!noconinput)
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
#endif
#ifdef USE_LIBTOOL #ifdef USE_LIBTOOL
lt_dlexit(); lt_dlexit();
@ -400,9 +402,11 @@ void Sys_Error (const char *error, ...)
va_list argptr; va_list argptr;
char string[1024]; char string[1024];
#ifndef __DJGPP__
// change stdin to non blocking // change stdin to non blocking
if (!noconinput) if (!noconinput)
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
#endif
va_start (argptr,error); va_start (argptr,error);
vsnprintf (string,sizeof(string)-1, error,argptr); 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 // Sleeps for microseconds
// ======================================================================= // =======================================================================
static volatile int oktogo;
void alarm_handler(int x)
{
oktogo=1;
}
char *Sys_ConsoleInput(void) char *Sys_ConsoleInput(void)
{ {
#if 1 #if 1
@ -853,7 +850,9 @@ char *Sys_ConsoleInput(void)
// if (!qrenderer) // if (!qrenderer)
{ {
Con_Printf("ConsoleInput\n");
len = read (0, text, sizeof(text)); len = read (0, text, sizeof(text));
Con_Printf("ConsoleInput read %i\n", len);
if (len < 1) if (len < 1)
return NULL; return NULL;
@ -948,13 +947,17 @@ int main (int c, const char **v)
noconinput = COM_CheckParm("-noconinput"); noconinput = COM_CheckParm("-noconinput");
#ifndef __DJGPP__
if (!noconinput) if (!noconinput)
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
#endif
#ifdef SUBSERVERS #ifdef SUBSERVERS
if (COM_CheckParm("-clusterslave")) if (COM_CheckParm("-clusterslave"))
isDedicated = nostdout = isClusterSlave = true; isDedicated = nostdout = isClusterSlave = true;
#endif #endif
if (COM_CheckParm("-dedicated"))
isDedicated = true;
if (COM_CheckParm("-nostdout")) if (COM_CheckParm("-nostdout"))
nostdout = 1; nostdout = 1;
@ -963,7 +966,6 @@ int main (int c, const char **v)
for (i = 1; i < parms.argc; i++) for (i = 1; i < parms.argc; i++)
{ {
Con_Printf("Arg%i == %s\n", i, parms.argv[i]);
if (!parms.argv[i]) if (!parms.argv[i])
continue; continue;
if (*parms.argv[i] == '+' || *parms.argv[i] == '-') 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. //from the OS. This will cause problems with framebuffer-only setups.
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate) 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 //this about sums up the problem with this function
return false; return false;
#else #else

View file

@ -356,7 +356,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif #endif
//software rendering is just too glitchy, don't use it. //software rendering is just too glitchy, don't use it.
#if defined(SWQUAKE) && !defined(_DEBUG) #if defined(SWQUAKE) && !defined(_DEBUG) && !defined(__DJGPP__)
#undef SWQUAKE #undef SWQUAKE
#endif #endif
#if (defined(D3D8QUAKE) || defined(D3D9QUAKE) || defined(D3D11QUAKE)) && !defined(D3DQUAKE) #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. #undef WEBCLIENT //http/ftp clients.
#endif #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 #ifdef FTE_TARGET_WEB
//sandboxing... //sandboxing...
#undef HAVE_TCP //websockets are not real tcp. #undef HAVE_TCP //websockets are not real tcp.

View file

@ -71,7 +71,7 @@ void Mod_DoCRC(model_t *mod, char *buffer, int buffersize)
#ifdef _WIN32 #if defined(_WIN32) || defined(__DJGPP__)
#include <malloc.h> #include <malloc.h>
#else #else
#include <alloca.h> #include <alloca.h>

View file

@ -1717,7 +1717,7 @@ void MSG_ReadPos (vec3_t pos)
pos[2] = MSG_ReadCoord(); pos[2] = MSG_ReadCoord();
} }
#if defined(Q2SERVER) || !defined(SERVERONLY) #if 1//defined(Q2SERVER) || !defined(SERVERONLY)
#define Q2NUMVERTEXNORMALS 162 #define Q2NUMVERTEXNORMALS 162
vec3_t bytedirs[Q2NUMVERTEXNORMALS] = vec3_t bytedirs[Q2NUMVERTEXNORMALS] =
{ {
@ -2652,7 +2652,7 @@ unsigned int unicode_charofsfrombyteofs(const char *str, unsigned int byteofs, q
return chars; return chars;
} }
#ifdef FTE_TARGET_WEB #if defined(FTE_TARGET_WEB) || defined(__DJGPP__)
//targets that don't support towupper/towlower... //targets that don't support towupper/towlower...
#define towupper Q_towupper #define towupper Q_towupper
#define towlower Q_towlower #define towlower Q_towlower

View file

@ -4,7 +4,7 @@
#endif #endif
#include "com_mesh.h" #include "com_mesh.h"
#ifdef _WIN32 #if defined(_WIN32) || defined(__DJGPP__)
#include <malloc.h> #include <malloc.h>
#else #else
#include <alloca.h> #include <alloca.h>

View file

@ -17,7 +17,7 @@
#include "glquake.h" #include "glquake.h"
#ifndef SERVERONLY #ifndef SERVERONLY
#ifdef _WIN32 #if defined(_WIN32) || defined(__DJGPP__)
#include <malloc.h> #include <malloc.h>
#else #else
#include <alloca.h> #include <alloca.h>

View file

@ -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> #include <malloc.h>
#else #else
#include <alloca.h> #include <alloca.h>

View file

@ -120,6 +120,8 @@ struct q2gclient_s
// this point in the structure // this point in the structure
}; };
#endif
#if defined(Q2SERVER) || defined(Q2CLIENT)
typedef struct q2entity_state_s typedef struct q2entity_state_s
{ {
int number; // edict index int number; // edict index
@ -141,6 +143,8 @@ typedef struct q2entity_state_s
// events only go out for a single frame, they // events only go out for a single frame, they
// are automatically cleared each frame // are automatically cleared each frame
} q2entity_state_t; } q2entity_state_t;
#endif
#if defined(Q2SERVER)
struct q2edict_s struct q2edict_s

View file

@ -660,6 +660,165 @@ void SWBE_ClearVBO(struct vbo_s *vbo)
void SWBE_UploadAllLightmaps(void) 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) void SWBE_SelectEntity(struct entity_s *ent)
{ {
float modelmatrix[16]; float modelmatrix[16];
@ -670,7 +829,7 @@ void SWBE_SelectEntity(struct entity_s *ent)
return; return;
shaderstate.curentity = ent; 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); Matrix4_Multiply(r_refdef.m_projection, modelviewmatrix, shaderstate.m_mvp);
shaderstate.viewplane[0] = vpn[0];//-modelviewmatrix[0];//0*4+2]; shaderstate.viewplane[0] = vpn[0];//-modelviewmatrix[0];//0*4+2];
shaderstate.viewplane[1] = vpn[1];//-modelviewmatrix[1];//1*4+2]; shaderstate.viewplane[1] = vpn[1];//-modelviewmatrix[1];//1*4+2];

365
engine/sw/sw_viddos.c Normal file
View 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