Clean up legacy glquake files from other platforms

This commit is contained in:
cypress 2024-09-04 20:43:20 -07:00
parent 664cfe3b99
commit d657027ab0
80 changed files with 0 additions and 24293 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,151 +0,0 @@
/*
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.
*/
//
// asm_draw.h
//
// Include file for asm drawing routines.
//
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// !!! if this is changed, it must be changed in r_local.h too !!!
#define NEAR_CLIP 0.01
// !!! if this is changed, it must be changed in r_local.h too !!!
#define CYCLE 128
// espan_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define espan_t_u 0
#define espan_t_v 4
#define espan_t_count 8
#define espan_t_pnext 12
#define espan_t_size 16
// sspan_t structure
// !!! if this is changed, it must be changed in d_local.h too !!!
#define sspan_t_u 0
#define sspan_t_v 4
#define sspan_t_count 8
#define sspan_t_size 12
// spanpackage_t structure
// !!! if this is changed, it must be changed in d_polyset.c too !!!
#define spanpackage_t_pdest 0
#define spanpackage_t_pz 4
#define spanpackage_t_count 8
#define spanpackage_t_ptex 12
#define spanpackage_t_sfrac 16
#define spanpackage_t_tfrac 20
#define spanpackage_t_light 24
#define spanpackage_t_zi 28
#define spanpackage_t_size 32
// edge_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define et_u 0
#define et_u_step 4
#define et_prev 8
#define et_next 12
#define et_surfs 16
#define et_nextremove 20
#define et_nearzi 24
#define et_owner 28
#define et_size 32
// surf_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define SURF_T_SHIFT 6
#define st_next 0
#define st_prev 4
#define st_spans 8
#define st_key 12
#define st_last_u 16
#define st_spanstate 20
#define st_flags 24
#define st_data 28
#define st_entity 32
#define st_nearzi 36
#define st_insubmodel 40
#define st_d_ziorigin 44
#define st_d_zistepu 48
#define st_d_zistepv 52
#define st_pad 56
#define st_size 64
// clipplane_t structure
// !!! if this is changed, it must be changed in r_local.h too !!!
#define cp_normal 0
#define cp_dist 12
#define cp_next 16
#define cp_leftedge 20
#define cp_rightedge 21
#define cp_reserved 22
#define cp_size 24
// medge_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define me_v 0
#define me_cachededgeoffset 4
#define me_size 8
// mvertex_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mv_position 0
#define mv_size 12
// refdef_t structure
// !!! if this is changed, it must be changed in render.h too !!!
#define rd_vrect 0
#define rd_aliasvrect 20
#define rd_vrectright 40
#define rd_vrectbottom 44
#define rd_aliasvrectright 48
#define rd_aliasvrectbottom 52
#define rd_vrectrightedge 56
#define rd_fvrectx 60
#define rd_fvrecty 64
#define rd_fvrectx_adj 68
#define rd_fvrecty_adj 72
#define rd_vrect_x_adj_shift20 76
#define rd_vrectright_adj_shift20 80
#define rd_fvrectright_adj 84
#define rd_fvrectbottom_adj 88
#define rd_fvrectright 92
#define rd_fvrectbottom 96
#define rd_horizontalFieldOfView 100
#define rd_xOrigin 104
#define rd_yOrigin 108
#define rd_vieworg 112
#define rd_viewangles 124
#define rd_ambientlight 136
#define rd_size 140
// mtriangle_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mtri_facesfront 0
#define mtri_vertindex 4
#define mtri_size 16 // !!! if this changes, array indexing in !!!
// !!! d_polysa.s must be changed to match !!!
#define mtri_shift 4

View file

@ -1,97 +0,0 @@
/*
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.
*/
#ifndef __ASM_I386__
#define __ASM_I386__
#ifdef ELF
#define C(label) label
#else
#define C(label) _##label
#endif
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// plane_t structure
// !!! if this is changed, it must be changed in model.h too !!!
// !!! if the size of this is changed, the array lookup in SV_HullPointContents
// must be changed too !!!
#define pl_normal 0
#define pl_dist 12
#define pl_type 16
#define pl_signbits 17
#define pl_pad 18
#define pl_size 20
// hull_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define hu_clipnodes 0
#define hu_planes 4
#define hu_firstclipnode 8
#define hu_lastclipnode 12
#define hu_clip_mins 16
#define hu_clip_maxs 28
#define hu_size 40
// dnode_t structure
// !!! if this is changed, it must be changed in bspfile.h too !!!
#define nd_planenum 0
#define nd_children 4
#define nd_mins 8
#define nd_maxs 20
#define nd_firstface 32
#define nd_numfaces 36
#define nd_size 40
// sfxcache_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define sfxc_length 0
#define sfxc_loopstart 4
#define sfxc_speed 8
#define sfxc_width 12
#define sfxc_stereo 16
#define sfxc_data 20
// channel_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define ch_sfx 0
#define ch_leftvol 4
#define ch_rightvol 8
#define ch_end 12
#define ch_pos 16
#define ch_looping 20
#define ch_entnum 24
#define ch_entchannel 28
#define ch_origin 32
#define ch_dist_mult 44
#define ch_master_vol 48
#define ch_size 52
// portable_samplepair_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define psp_left 0
#define psp_right 4
#define psp_size 8
#endif

View file

@ -1,142 +0,0 @@
/*
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.
*/
LEnter16_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch0:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch1:
movw %cx,2(%edi)
addl $0x4,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch2:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch3:
movw %cx,2(%edi)
addl $0x4,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch4:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch5:
movw %cx,2(%edi)
addl $0x4,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch6:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch7:
movw %cx,2(%edi)
addl $0x4,%edi
LEnter8_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch8:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch9:
movw %cx,2(%edi)
addl $0x4,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch10:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch11:
movw %cx,2(%edi)
addl $0x4,%edi
LEnter4_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch12:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch13:
movw %cx,2(%edi)
addl $0x4,%edi
LEnter2_16:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movw 0x12345678(,%eax,2),%ax
LBPatch14:
addl %ebp,%edx
movw %ax,(%edi)
movw 0x12345678(,%ecx,2),%cx
LBPatch15:
movw %cx,2(%edi)
addl $0x4,%edi

View file

@ -1,143 +0,0 @@
/*
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.
*/
LEnter16_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch0:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch1:
movb %cl,1(%edi)
addl $0x2,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch2:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch3:
movb %cl,1(%edi)
addl $0x2,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch4:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch5:
movb %cl,1(%edi)
addl $0x2,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch6:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch7:
movb %cl,1(%edi)
addl $0x2,%edi
LEnter8_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch8:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch9:
movb %cl,1(%edi)
addl $0x2,%edi
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch10:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch11:
movb %cl,1(%edi)
addl $0x2,%edi
LEnter4_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch12:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch13:
movb %cl,1(%edi)
addl $0x2,%edi
LEnter2_8:
movb (%esi),%al
movb (%esi,%ebx,),%cl
movb %dh,%ah
addl %ebp,%edx
movb %dh,%ch
leal (%esi,%ebx,2),%esi
movb 0x12345678(%eax),%al
LBPatch14:
addl %ebp,%edx
movb %al,(%edi)
movb 0x12345678(%ecx),%cl
LBPatch15:
movb %cl,1(%edi)
addl $0x2,%edi

View file

@ -152,7 +152,6 @@ typedef struct
#define CONTENTS_CURRENT_DOWN -14
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
int planenum;

View file

@ -1,886 +0,0 @@
/*
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.
*/
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
// rights reserved.
#include <dpmi.h>
#include "quakedef.h"
#include "dosisms.h"
extern cvar_t bgmvolume;
#define ADDRESS_MODE_HSG 0
#define ADDRESS_MODE_RED_BOOK 1
#define STATUS_ERROR_BIT 0x8000
#define STATUS_BUSY_BIT 0x0200
#define STATUS_DONE_BIT 0x0100
#define STATUS_ERROR_MASK 0x00ff
#define ERROR_WRITE_PROTECT 0
#define ERROR_UNKNOWN_UNIT 1
#define ERROR_DRIVE_NOT_READY 2
#define ERROR_UNKNOWN_COMMAND 3
#define ERROR_CRC_ERROR 4
#define ERROR_BAD_REQUEST_LEN 5
#define ERROR_SEEK_ERROR 6
#define ERROR_UNKNOWN_MEDIA 7
#define ERROR_SECTOR_NOT_FOUND 8
#define ERROR_OUT_OF_PAPER 9
#define ERROR_WRITE_FAULT 10
#define ERROR_READ_FAULT 11
#define ERROR_GENERAL_FAILURE 12
#define ERROR_RESERVED_13 13
#define ERROR_RESERVED_14 14
#define ERROR_BAD_DISK_CHANGE 15
#define COMMAND_READ 3
#define COMMAND_WRITE 12
#define COMMAND_PLAY_AUDIO 132
#define COMMAND_STOP_AUDIO 133
#define COMMAND_RESUME_AUDIO 136
#define READ_REQUEST_AUDIO_CHANNEL_INFO 4
#define READ_REQUEST_DEVICE_STATUS 6
#define READ_REQUEST_MEDIA_CHANGE 9
#define READ_REQUEST_AUDIO_DISK_INFO 10
#define READ_REQUEST_AUDIO_TRACK_INFO 11
#define READ_REQUEST_AUDIO_STATUS 15
#define WRITE_REQUEST_EJECT 0
#define WRITE_REQUEST_RESET 2
#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3
#define STATUS_DOOR_OPEN 0x00000001
#define STATUS_DOOR_UNLOCKED 0x00000002
#define STATUS_RAW_SUPPORT 0x00000004
#define STATUS_READ_WRITE 0x00000008
#define STATUS_AUDIO_SUPPORT 0x00000010
#define STATUS_INTERLEAVE_SUPPORT 0x00000020
#define STATUS_BIT_6_RESERVED 0x00000040
#define STATUS_PREFETCH_SUPPORT 0x00000080
#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100
#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200
#define MEDIA_NOT_CHANGED 1
#define MEDIA_STATUS_UNKNOWN 0
#define MEDIA_CHANGED -1
#define AUDIO_CONTROL_MASK 0xd0
#define AUDIO_CONTROL_DATA_TRACK 0x40
#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00
#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10
#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80
#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90
#define AUDIO_STATUS_PAUSED 0x0001
#pragma pack(1)
struct playAudioRequest
{
char addressingMode;
int startLocation;
int sectors;
};
struct readRequest
{
char mediaDescriptor;
short bufferOffset;
short bufferSegment;
short length;
short startSector;
int volumeID;
};
struct writeRequest
{
char mediaDescriptor;
short bufferOffset;
short bufferSegment;
short length;
short startSector;
int volumeID;
};
struct cd_request
{
char headerLength;
char unit;
char command;
short status;
char reserved[8];
union
{
struct playAudioRequest playAudio;
struct readRequest read;
struct writeRequest write;
} x;
};
struct audioChannelInfo_s
{
char code;
char channel0input;
char channel0volume;
char channel1input;
char channel1volume;
char channel2input;
char channel2volume;
char channel3input;
char channel3volume;
};
struct deviceStatus_s
{
char code;
int status;
};
struct mediaChange_s
{
char code;
char status;
};
struct audioDiskInfo_s
{
char code;
char lowTrack;
char highTrack;
int leadOutStart;
};
struct audioTrackInfo_s
{
char code;
char track;
int start;
char control;
};
struct audioStatus_s
{
char code;
short status;
int PRstartLocation;
int PRendLocation;
};
struct reset_s
{
char code;
};
union readInfo_u
{
struct audioChannelInfo_s audioChannelInfo;
struct deviceStatus_s deviceStatus;
struct mediaChange_s mediaChange;
struct audioDiskInfo_s audioDiskInfo;
struct audioTrackInfo_s audioTrackInfo;
struct audioStatus_s audioStatus;
struct reset_s reset;
};
#pragma pack()
#define MAXIMUM_TRACKS 100
typedef struct
{
int start;
int length;
qboolean isData;
} track_info;
typedef struct
{
qboolean valid;
int leadOutAddress;
track_info track[MAXIMUM_TRACKS];
byte lowTrack;
byte highTrack;
} cd_info;
static struct cd_request *cdRequest;
static union readInfo_u *readInfo;
static cd_info cd;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean mediaCheck = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static short cdRequestSegment;
static short cdRequestOffset;
static short readInfoSegment;
static short readInfoOffset;
static byte remap[256];
static byte cdrom;
static byte playTrack;
static byte cdvolume;
static int RedBookToSector(int rb)
{
byte minute;
byte second;
byte frame;
minute = (rb >> 16) & 0xff;
second = (rb >> 8) & 0xff;
frame = rb & 0xff;
return minute * 60 * 75 + second * 75 + frame;
}
static void CDAudio_Reset(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_WRITE;
cdRequest->status = 0;
cdRequest->x.write.mediaDescriptor = 0;
cdRequest->x.write.bufferOffset = readInfoOffset;
cdRequest->x.write.bufferSegment = readInfoSegment;
cdRequest->x.write.length = sizeof(struct reset_s);
cdRequest->x.write.startSector = 0;
cdRequest->x.write.volumeID = 0;
readInfo->reset.code = WRITE_REQUEST_RESET;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
}
static void CDAudio_Eject(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_WRITE;
cdRequest->status = 0;
cdRequest->x.write.mediaDescriptor = 0;
cdRequest->x.write.bufferOffset = readInfoOffset;
cdRequest->x.write.bufferSegment = readInfoSegment;
cdRequest->x.write.length = sizeof(struct reset_s);
cdRequest->x.write.startSector = 0;
cdRequest->x.write.volumeID = 0;
readInfo->reset.code = WRITE_REQUEST_EJECT;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
}
static int CDAudio_GetAudioTrackInfo(byte track, int *start)
{
byte control;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
readInfo->audioTrackInfo.track = track;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
if (cdRequest->status & STATUS_ERROR_BIT)
{
Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff);
return -1;
}
*start = readInfo->audioTrackInfo.start;
control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
return (control & AUDIO_CONTROL_DATA_TRACK);
}
static int CDAudio_GetAudioDiskInfo(void)
{
int n;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
if (cdRequest->status & STATUS_ERROR_BIT)
{
Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff);
return -1;
}
cd.valid = true;
cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
cd.highTrack = readInfo->audioDiskInfo.highTrack;
cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
for (n = cd.lowTrack; n <= cd.highTrack; n++)
{
cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
if (n > cd.lowTrack)
{
cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
if (n == cd.highTrack)
cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
}
}
return 0;
}
static int CDAudio_GetAudioStatus(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioStatus_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
if (cdRequest->status & STATUS_ERROR_BIT)
return -1;
return 0;
}
static int CDAudio_MediaChange(void)
{
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_READ;
cdRequest->status = 0;
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct mediaChange_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
return readInfo->mediaChange.status;
}
// we set the volume to 0 first and then to the desired volume
// some cd-rom drivers seem to need it done this way
void CDAudio_SetVolume (byte volume)
{
if (!initialized || !enabled)
return;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_WRITE;
cdRequest->status = 0;
cdRequest->x.read.mediaDescriptor = 0;
cdRequest->x.read.bufferOffset = readInfoOffset;
cdRequest->x.read.bufferSegment = readInfoSegment;
cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
cdRequest->x.read.startSector = 0;
cdRequest->x.read.volumeID = 0;
readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
readInfo->audioChannelInfo.channel0input = 0;
readInfo->audioChannelInfo.channel0volume = 0;
readInfo->audioChannelInfo.channel1input = 1;
readInfo->audioChannelInfo.channel1volume = 0;
readInfo->audioChannelInfo.channel2input = 2;
readInfo->audioChannelInfo.channel2volume = 0;
readInfo->audioChannelInfo.channel3input = 3;
readInfo->audioChannelInfo.channel3volume = 0;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
readInfo->audioChannelInfo.channel0volume = volume;
readInfo->audioChannelInfo.channel1volume = volume;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
cdvolume = volume;
}
void CDAudio_Play(byte track, qboolean looping)
{
int volume;
if (!initialized || !enabled)
return;
if (!cd.valid)
return;
track = remap[track];
if (playing)
{
if (playTrack == track)
return;
CDAudio_Stop();
}
playLooping = looping;
if (track < cd.lowTrack || track > cd.highTrack)
{
Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
return;
}
playTrack = track;
if (cd.track[track].isData)
{
Con_DPrintf("CDAudio_Play: Can not play data.\n");
return;
}
volume = (int)(bgmvolume.value * 255.0);
if (volume < 0)
{
Cvar_SetValue ("bgmvolume", 0.0);
volume = 0;
}
else if (volume > 255)
{
Cvar_SetValue ("bgmvolume", 1.0);
volume = 255;
}
CDAudio_SetVolume (volume);
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_PLAY_AUDIO;
cdRequest->status = 0;
cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
cdRequest->x.playAudio.startLocation = cd.track[track].start;
cdRequest->x.playAudio.sectors = cd.track[track].length;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
if (cdRequest->status & STATUS_ERROR_BIT)
{
Con_DPrintf("CDAudio_Play: track %u failed\n", track);
cd.valid = false;
playing = false;
return;
}
playing = true;
}
void CDAudio_Stop(void)
{
if (!initialized || !enabled)
return;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_STOP_AUDIO;
cdRequest->status = 0;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
wasPlaying = playing;
playing = false;
}
void CDAudio_Pause(void)
{
CDAudio_Stop();
}
void CDAudio_Resume(void)
{
if (!initialized || !enabled)
return;
if (!cd.valid)
return;
if (!wasPlaying)
return;
cdRequest->headerLength = 13;
cdRequest->unit = 0;
cdRequest->command = COMMAND_RESUME_AUDIO;
cdRequest->status = 0;
regs.x.ax = 0x1510;
regs.x.cx = cdrom;
regs.x.es = cdRequestSegment;
regs.x.bx = cdRequestOffset;
dos_int86 (0x2f);
playing = true;
}
static void CD_f (void)
{
char *command;
int ret;
int n;
int startAddress;
if (Cmd_Argc() < 2)
return;
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (Q_strcasecmp(command, "off") == 0)
{
if (playing)
CDAudio_Stop();
enabled = false;
return;
}
if (Q_strcasecmp(command, "reset") == 0)
{
enabled = true;
if (playing)
CDAudio_Stop();
for (n = 0; n < 256; n++)
remap[n] = n;
CDAudio_Reset();
CDAudio_GetAudioDiskInfo();
return;
}
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 256; n++)
if (remap[n] != n)
Con_Printf(" %u -> %u\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
remap[n] = Q_atoi(Cmd_Argv (n+1));
return;
}
if (!cd.valid)
{
Con_Printf("No CD in player.\n");
return;
}
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play(Q_atoi(Cmd_Argv (2)), true);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
CDAudio_Stop();
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
CDAudio_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
CDAudio_Resume();
return;
}
if (Q_strcasecmp(command, "eject") == 0)
{
if (playing)
CDAudio_Stop();
CDAudio_Eject();
cd.valid = false;
return;
}
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
for (n = cd.lowTrack; n <= cd.highTrack; n++)
{
ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
}
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %u\n", cdvolume);
CDAudio_MediaChange();
Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
return;
}
}
void CDAudio_Update(void)
{
int ret;
int newVolume;
static double lastUpdate;
if (!initialized || !enabled)
return;
if ((realtime - lastUpdate) < 0.25)
return;
lastUpdate = realtime;
if (mediaCheck)
{
static double lastCheck;
if ((realtime - lastCheck) < 5.0)
return;
lastCheck = realtime;
ret = CDAudio_MediaChange();
if (ret == MEDIA_CHANGED)
{
Con_DPrintf("CDAudio: media changed\n");
playing = false;
wasPlaying = false;
cd.valid = false;
CDAudio_GetAudioDiskInfo();
return;
}
}
newVolume = (int)(bgmvolume.value * 255.0);
if (newVolume != cdvolume)
{
if (newVolume < 0)
{
Cvar_SetValue ("bgmvolume", 0.0);
newVolume = 0;
}
else if (newVolume > 255)
{
Cvar_SetValue ("bgmvolume", 1.0);
newVolume = 255;
}
CDAudio_SetVolume (newVolume);
}
if (playing)
{
CDAudio_GetAudioStatus();
if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
{
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
}
}
int CDAudio_Init(void)
{
char *memory;
int n;
if (cls.state == ca_dedicated)
return -1;
if (COM_CheckParm("-nocdaudio"))
return -1;
if (COM_CheckParm("-cdmediacheck"))
mediaCheck = true;
regs.x.ax = 0x1500;
regs.x.bx = 0;
dos_int86 (0x2f);
if (regs.x.bx == 0)
{
Con_NotifyBox (
"MSCDEX not loaded, music is\n"
"disabled. Use \"-nocdaudio\" if you\n"
"wish to avoid this message in the\n"
"future. See README.TXT for help.\n"
);
return -1;
}
if (regs.x.bx > 1)
Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
cdrom = regs.x.cx;
regs.x.ax = 0x150c;
regs.x.bx = 0;
dos_int86 (0x2f);
if (regs.x.bx == 0)
{
Con_NotifyBox (
"MSCDEX version 2.00 or later\n"
"required for music. See README.TXT\n"
"for help.\n"
);
Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
return -1;
}
memory = dos_getmemory(sizeof(struct cd_request
) + sizeof(union readInfo_u));
if (memory == NULL)
{
Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
return -1;
}
cdRequest = (struct cd_request *)memory;
cdRequestSegment = ptr2real(cdRequest) >> 4;
cdRequestOffset = ptr2real(cdRequest) & 0xf;
readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
readInfoSegment = ptr2real(readInfo) >> 4;
readInfoOffset = ptr2real(readInfo) & 0xf;
for (n = 0; n < 256; n++)
remap[n] = n;
initialized = true;
CDAudio_SetVolume (255);
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in player.\n");
enabled = false;
}
Cmd_AddCommand ("cd", CD_f);
Con_Printf("CD Audio Initialized\n");
return 0;
}
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
}

View file

@ -1,416 +0,0 @@
/*
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.
*/
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
// rights reserved.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <linux/cdrom.h>
#include "quakedef.h"
static qboolean cdValid = false;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static float cdvolume;
static byte remap[100];
static byte playTrack;
static byte maxTrack;
static int cdfile = -1;
static char cd_dev[64] = "/dev/cdrom";
static void CDAudio_Eject(void)
{
if (cdfile == -1 || !enabled)
return; // no cd init'd
if ( ioctl(cdfile, CDROMEJECT) == -1 )
Con_DPrintf("ioctl cdromeject failed\n");
}
static void CDAudio_CloseDoor(void)
{
if (cdfile == -1 || !enabled)
return; // no cd init'd
if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 )
Con_DPrintf("ioctl cdromclosetray failed\n");
}
static int CDAudio_GetAudioDiskInfo(void)
{
struct cdrom_tochdr tochdr;
cdValid = false;
if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 )
{
Con_DPrintf("ioctl cdromreadtochdr failed\n");
return -1;
}
if (tochdr.cdth_trk0 < 1)
{
Con_DPrintf("CDAudio: no music tracks\n");
return -1;
}
cdValid = true;
maxTrack = tochdr.cdth_trk1;
return 0;
}
void CDAudio_Play(byte track, qboolean looping)
{
struct cdrom_tocentry entry;
struct cdrom_ti ti;
if (cdfile == -1 || !enabled)
return;
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
return;
}
track = remap[track];
if (track < 1 || track > maxTrack)
{
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return;
}
// don't try to play a non-audio track
entry.cdte_track = track;
entry.cdte_format = CDROM_MSF;
if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
{
Con_DPrintf("ioctl cdromreadtocentry failed\n");
return;
}
if (entry.cdte_ctrl == CDROM_DATA_TRACK)
{
Con_Printf("CDAudio: track %i is not audio\n", track);
return;
}
if (playing)
{
if (playTrack == track)
return;
CDAudio_Stop();
}
ti.cdti_trk0 = track;
ti.cdti_trk1 = track;
ti.cdti_ind0 = 1;
ti.cdti_ind1 = 99;
if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 )
{
Con_DPrintf("ioctl cdromplaytrkind failed\n");
return;
}
if ( ioctl(cdfile, CDROMRESUME) == -1 )
Con_DPrintf("ioctl cdromresume failed\n");
playLooping = looping;
playTrack = track;
playing = true;
if (cdvolume == 0.0)
CDAudio_Pause ();
}
void CDAudio_Stop(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
if ( ioctl(cdfile, CDROMSTOP) == -1 )
Con_DPrintf("ioctl cdromstop failed (%d)\n", errno);
wasPlaying = false;
playing = false;
}
void CDAudio_Pause(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
if ( ioctl(cdfile, CDROMPAUSE) == -1 )
Con_DPrintf("ioctl cdrompause failed\n");
wasPlaying = playing;
playing = false;
}
void CDAudio_Resume(void)
{
if (cdfile == -1 || !enabled)
return;
if (!cdValid)
return;
if (!wasPlaying)
return;
if ( ioctl(cdfile, CDROMRESUME) == -1 )
Con_DPrintf("ioctl cdromresume failed\n");
playing = true;
}
static void CD_f (void)
{
char *command;
int ret;
int n;
if (Cmd_Argc() < 2)
return;
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (Q_strcasecmp(command, "off") == 0)
{
if (playing)
CDAudio_Stop();
enabled = false;
return;
}
if (Q_strcasecmp(command, "reset") == 0)
{
enabled = true;
if (playing)
CDAudio_Stop();
for (n = 0; n < 100; n++)
remap[n] = n;
CDAudio_GetAudioDiskInfo();
return;
}
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 100; n++)
if (remap[n] != n)
Con_Printf(" %u -> %u\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
remap[n] = Q_atoi(Cmd_Argv (n+1));
return;
}
if (Q_strcasecmp(command, "close") == 0)
{
CDAudio_CloseDoor();
return;
}
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
{
Con_Printf("No CD in player.\n");
return;
}
}
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
CDAudio_Stop();
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
CDAudio_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
CDAudio_Resume();
return;
}
if (Q_strcasecmp(command, "eject") == 0)
{
if (playing)
CDAudio_Stop();
CDAudio_Eject();
cdValid = false;
return;
}
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", maxTrack);
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
else if (wasPlaying)
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %f\n", cdvolume);
return;
}
}
void CDAudio_Update(void)
{
struct cdrom_subchnl subchnl;
static time_t lastchk;
if (!enabled)
return;
if (bgmvolume.value != cdvolume)
{
if (cdvolume)
{
Cvar_SetValue ("bgmvolume", 0.0);
cdvolume = bgmvolume.value;
CDAudio_Pause ();
}
else
{
Cvar_SetValue ("bgmvolume", 1.0);
cdvolume = bgmvolume.value;
CDAudio_Resume ();
}
}
if (playing && lastchk < time(NULL)) {
lastchk = time(NULL) + 2; //two seconds between chks
subchnl.cdsc_format = CDROM_MSF;
if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
Con_DPrintf("ioctl cdromsubchnl failed\n");
playing = false;
return;
}
if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
}
}
int CDAudio_Init(void)
{
int i;
if (cls.state == ca_dedicated)
return -1;
if (COM_CheckParm("-nocdaudio"))
return -1;
if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1) {
strncpy(cd_dev, com_argv[i + 1], sizeof(cd_dev));
cd_dev[sizeof(cd_dev) - 1] = 0;
}
if ((cdfile = open(cd_dev, O_RDONLY)) == -1) {
Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
cdfile = -1;
return -1;
}
for (i = 0; i < 100; i++)
remap[i] = i;
initialized = true;
enabled = true;
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in player.\n");
cdValid = false;
}
Cmd_AddCommand ("cd", CD_f);
Con_Printf("CD Audio Initialized\n");
return 0;
}
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
close(cdfile);
cdfile = -1;
}

View file

@ -1,477 +0,0 @@
/*
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.
*/
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
// rights reserved.
#include <windows.h>
#include "quakedef.h"
extern HWND mainwindow;
extern cvar_t bgmvolume;
static qboolean cdValid = false;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = false;
static qboolean playLooping = false;
static float cdvolume;
static byte remap[100];
static byte cdrom;
static byte playTrack;
static byte maxTrack;
UINT wDeviceID;
static void CDAudio_Eject(void)
{
DWORD dwReturn;
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
}
static void CDAudio_CloseDoor(void)
{
DWORD dwReturn;
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
}
static int CDAudio_GetAudioDiskInfo(void)
{
DWORD dwReturn;
MCI_STATUS_PARMS mciStatusParms;
cdValid = false;
mciStatusParms.dwItem = MCI_STATUS_READY;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: drive ready test - get status failed\n");
return -1;
}
if (!mciStatusParms.dwReturn)
{
Con_DPrintf("CDAudio: drive not ready\n");
return -1;
}
mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: get tracks - status failed\n");
return -1;
}
if (mciStatusParms.dwReturn < 1)
{
Con_DPrintf("CDAudio: no music tracks\n");
return -1;
}
cdValid = true;
maxTrack = mciStatusParms.dwReturn;
return 0;
}
void CDAudio_Play(byte track, qboolean looping)
{
DWORD dwReturn;
MCI_PLAY_PARMS mciPlayParms;
MCI_STATUS_PARMS mciStatusParms;
if (!enabled)
return;
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
return;
}
track = remap[track];
if (track < 1 || track > maxTrack)
{
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return;
}
// don't try to play a non-audio track
mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
mciStatusParms.dwTrack = track;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
return;
}
if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
{
Con_Printf("CDAudio: track %i is not audio\n", track);
return;
}
// get the length of the track to be played
mciStatusParms.dwItem = MCI_STATUS_LENGTH;
mciStatusParms.dwTrack = track;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
return;
}
if (playing)
{
if (playTrack == track)
return;
CDAudio_Stop();
}
mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
mciPlayParms.dwCallback = (DWORD)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
return;
}
playLooping = looping;
playTrack = track;
playing = true;
if (cdvolume == 0.0)
CDAudio_Pause ();
}
void CDAudio_Stop(void)
{
DWORD dwReturn;
if (!enabled)
return;
if (!playing)
return;
if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
Con_DPrintf("MCI_STOP failed (%i)", dwReturn);
wasPlaying = false;
playing = false;
}
void CDAudio_Pause(void)
{
DWORD dwReturn;
MCI_GENERIC_PARMS mciGenericParms;
if (!enabled)
return;
if (!playing)
return;
mciGenericParms.dwCallback = (DWORD)mainwindow;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
wasPlaying = playing;
playing = false;
}
void CDAudio_Resume(void)
{
DWORD dwReturn;
MCI_PLAY_PARMS mciPlayParms;
if (!enabled)
return;
if (!cdValid)
return;
if (!wasPlaying)
return;
mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
mciPlayParms.dwCallback = (DWORD)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
return;
}
playing = true;
}
static void CD_f (void)
{
char *command;
int ret;
int n;
int startAddress;
if (Cmd_Argc() < 2)
return;
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (Q_strcasecmp(command, "off") == 0)
{
if (playing)
CDAudio_Stop();
enabled = false;
return;
}
if (Q_strcasecmp(command, "reset") == 0)
{
enabled = true;
if (playing)
CDAudio_Stop();
for (n = 0; n < 100; n++)
remap[n] = n;
CDAudio_GetAudioDiskInfo();
return;
}
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 100; n++)
if (remap[n] != n)
Con_Printf(" %u -> %u\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
remap[n] = Q_atoi(Cmd_Argv (n+1));
return;
}
if (Q_strcasecmp(command, "close") == 0)
{
CDAudio_CloseDoor();
return;
}
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
{
Con_Printf("No CD in player.\n");
return;
}
}
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
CDAudio_Stop();
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
CDAudio_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
CDAudio_Resume();
return;
}
if (Q_strcasecmp(command, "eject") == 0)
{
if (playing)
CDAudio_Stop();
CDAudio_Eject();
cdValid = false;
return;
}
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", maxTrack);
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
else if (wasPlaying)
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %f\n", cdvolume);
return;
}
}
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (lParam != wDeviceID)
return 1;
switch (wParam)
{
case MCI_NOTIFY_SUCCESSFUL:
if (playing)
{
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
break;
case MCI_NOTIFY_ABORTED:
case MCI_NOTIFY_SUPERSEDED:
break;
case MCI_NOTIFY_FAILURE:
Con_DPrintf("MCI_NOTIFY_FAILURE\n");
CDAudio_Stop ();
cdValid = false;
break;
default:
Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
return 1;
}
return 0;
}
void CDAudio_Update(void)
{
if (!enabled)
return;
if (bgmvolume.value != cdvolume)
{
if (cdvolume)
{
Cvar_SetValue ("bgmvolume", 0.0);
cdvolume = bgmvolume.value;
CDAudio_Pause ();
}
else
{
Cvar_SetValue ("bgmvolume", 1.0);
cdvolume = bgmvolume.value;
CDAudio_Resume ();
}
}
}
int CDAudio_Init(void)
{
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_SET_PARMS mciSetParms;
int n;
if (cls.state == ca_dedicated)
return -1;
if (COM_CheckParm("-nocdaudio"))
return -1;
mciOpenParms.lpstrDeviceType = "cdaudio";
if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
{
Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
return -1;
}
wDeviceID = mciOpenParms.wDeviceID;
// Set the time format to track/minute/second/frame (TMSF).
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
{
Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
return -1;
}
for (n = 0; n < 100; n++)
remap[n] = n;
initialized = true;
enabled = true;
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in player.\n");
cdValid = false;
}
Cmd_AddCommand ("cd", CD_f);
Con_Printf("CD Audio Initialized\n");
return 0;
}
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
}

View file

@ -1,365 +0,0 @@
/*
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.
*/
// conproc.c
#include <windows.h>
#include "conproc.h"
#include "quakedef.h"
HANDLE heventDone;
HANDLE hfileBuffer;
HANDLE heventChildSend;
HANDLE heventParentSend;
HANDLE hStdout;
HANDLE hStdin;
DWORD RequestProc (DWORD dwNichts);
LPVOID GetMappedBuffer (HANDLE hfileBuffer);
void ReleaseMappedBuffer (LPVOID pBuffer);
BOOL GetScreenBufferLines (int *piLines);
BOOL SetScreenBufferLines (int iLines);
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
BOOL WriteText (LPCTSTR szText);
int CharToCode (char c);
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild)
{
DWORD dwID;
CONSOLE_SCREEN_BUFFER_INFO info;
int wheight, wwidth;
// ignore if we don't have all the events.
if (!hFile || !heventParent || !heventChild)
return;
hfileBuffer = hFile;
heventParentSend = heventParent;
heventChildSend = heventChild;
// so we'll know when to go away.
heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!heventDone)
{
Con_SafePrintf ("Couldn't create heventDone\n");
return;
}
if (!CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE) RequestProc,
0,
0,
&dwID))
{
CloseHandle (heventDone);
Con_SafePrintf ("Couldn't create QHOST thread\n");
return;
}
// save off the input/output handles.
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
hStdin = GetStdHandle (STD_INPUT_HANDLE);
// force 80 character width, at least 25 character height
SetConsoleCXCY (hStdout, 80, 25);
}
void DeinitConProc (void)
{
if (heventDone)
SetEvent (heventDone);
}
DWORD RequestProc (DWORD dwNichts)
{
int *pBuffer;
DWORD dwRet;
HANDLE heventWait[2];
int iBeginLine, iEndLine;
heventWait[0] = heventParentSend;
heventWait[1] = heventDone;
while (1)
{
dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
// heventDone fired, so we're exiting.
if (dwRet == WAIT_OBJECT_0 + 1)
break;
pBuffer = (int *) GetMappedBuffer (hfileBuffer);
// hfileBuffer is invalid. Just leave.
if (!pBuffer)
{
Con_SafePrintf ("Invalid hfileBuffer\n");
break;
}
switch (pBuffer[0])
{
case CCOM_WRITE_TEXT:
// Param1 : Text
pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
break;
case CCOM_GET_TEXT:
// Param1 : Begin line
// Param2 : End line
iBeginLine = pBuffer[1];
iEndLine = pBuffer[2];
pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
iEndLine);
break;
case CCOM_GET_SCR_LINES:
// No params
pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
break;
case CCOM_SET_SCR_LINES:
// Param1 : Number of lines
pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
break;
}
ReleaseMappedBuffer (pBuffer);
SetEvent (heventChildSend);
}
return 0;
}
LPVOID GetMappedBuffer (HANDLE hfileBuffer)
{
LPVOID pBuffer;
pBuffer = MapViewOfFile (hfileBuffer,
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
return pBuffer;
}
void ReleaseMappedBuffer (LPVOID pBuffer)
{
UnmapViewOfFile (pBuffer);
}
BOOL GetScreenBufferLines (int *piLines)
{
CONSOLE_SCREEN_BUFFER_INFO info;
BOOL bRet;
bRet = GetConsoleScreenBufferInfo (hStdout, &info);
if (bRet)
*piLines = info.dwSize.Y;
return bRet;
}
BOOL SetScreenBufferLines (int iLines)
{
return SetConsoleCXCY (hStdout, 80, iLines);
}
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
{
COORD coord;
DWORD dwRead;
BOOL bRet;
coord.X = 0;
coord.Y = iBeginLine;
bRet = ReadConsoleOutputCharacter(
hStdout,
pszText,
80 * (iEndLine - iBeginLine + 1),
coord,
&dwRead);
// Make sure it's null terminated.
if (bRet)
pszText[dwRead] = '\0';
return bRet;
}
BOOL WriteText (LPCTSTR szText)
{
DWORD dwWritten;
INPUT_RECORD rec;
char upper, *sz;
sz = (LPTSTR) szText;
while (*sz)
{
// 13 is the code for a carriage return (\n) instead of 10.
if (*sz == 10)
*sz = 13;
upper = toupper(*sz);
rec.EventType = KEY_EVENT;
rec.Event.KeyEvent.bKeyDown = TRUE;
rec.Event.KeyEvent.wRepeatCount = 1;
rec.Event.KeyEvent.wVirtualKeyCode = upper;
rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
rec.Event.KeyEvent.uChar.AsciiChar = *sz;
rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
WriteConsoleInput(
hStdin,
&rec,
1,
&dwWritten);
rec.Event.KeyEvent.bKeyDown = FALSE;
WriteConsoleInput(
hStdin,
&rec,
1,
&dwWritten);
sz++;
}
return TRUE;
}
int CharToCode (char c)
{
char upper;
upper = toupper(c);
switch (c)
{
case 13:
return 28;
default:
break;
}
if (isalpha(c))
return (30 + upper - 65);
if (isdigit(c))
return (1 + upper - 47);
return c;
}
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
{
CONSOLE_SCREEN_BUFFER_INFO info;
COORD coordMax;
coordMax = GetLargestConsoleWindowSize(hStdout);
if (cy > coordMax.Y)
cy = coordMax.Y;
if (cx > coordMax.X)
cx = coordMax.X;
if (!GetConsoleScreenBufferInfo(hStdout, &info))
return FALSE;
// height
info.srWindow.Left = 0;
info.srWindow.Right = info.dwSize.X - 1;
info.srWindow.Top = 0;
info.srWindow.Bottom = cy - 1;
if (cy < info.dwSize.Y)
{
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
return FALSE;
info.dwSize.Y = cy;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return FALSE;
}
else if (cy > info.dwSize.Y)
{
info.dwSize.Y = cy;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return FALSE;
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
return FALSE;
}
if (!GetConsoleScreenBufferInfo(hStdout, &info))
return FALSE;
// width
info.srWindow.Left = 0;
info.srWindow.Right = cx - 1;
info.srWindow.Top = 0;
info.srWindow.Bottom = info.dwSize.Y - 1;
if (cx < info.dwSize.X)
{
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
return FALSE;
info.dwSize.X = cx;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return FALSE;
}
else if (cx > info.dwSize.X)
{
info.dwSize.X = cx;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return FALSE;
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
return FALSE;
}
return TRUE;
}

View file

@ -1,37 +0,0 @@
/*
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.
*/
// conproc.h
#define CCOM_WRITE_TEXT 0x2
// Param1 : Text
#define CCOM_GET_TEXT 0x3
// Param1 : Begin line
// Param2 : End line
#define CCOM_GET_SCR_LINES 0x4
// No params
#define CCOM_SET_SCR_LINES 0x5
// Param1 : Number of lines
void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild);
void DeinitConProc (void);

View file

@ -1,331 +0,0 @@
/*
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.
*/
// d_edge.c
#include "quakedef.h"
#include "d_local.h"
static int miplevel;
float scale_for_mip;
int screenwidth;
int ubasestep, errorterm, erroradjustup, erroradjustdown;
int vstartscan;
// FIXME: should go away
extern void R_RotateBmodel (void);
extern void R_TransformFrustum (void);
vec3_t transformed_modelorg;
/*
==============
D_DrawPoly
==============
*/
void D_DrawPoly (void)
{
// this driver takes spans, not polygons
}
/*
=============
D_MipLevelForScale
=============
*/
int D_MipLevelForScale (float scale)
{
int lmiplevel;
if (scale >= d_scalemip[0] )
lmiplevel = 0;
else if (scale >= d_scalemip[1] )
lmiplevel = 1;
else if (scale >= d_scalemip[2] )
lmiplevel = 2;
else
lmiplevel = 3;
if (lmiplevel < d_minmip)
lmiplevel = d_minmip;
return lmiplevel;
}
/*
==============
D_DrawSolidSurface
==============
*/
// FIXME: clean this up
void D_DrawSolidSurface (surf_t *surf, int color)
{
espan_t *span;
byte *pdest;
int u, u2, pix;
pix = (color<<24) | (color<<16) | (color<<8) | color;
for (span=surf->spans ; span ; span=span->pnext)
{
pdest = (byte *)d_viewbuffer + screenwidth*span->v;
u = span->u;
u2 = span->u + span->count - 1;
((byte *)pdest)[u] = pix;
if (u2 - u < 8)
{
for (u++ ; u <= u2 ; u++)
((byte *)pdest)[u] = pix;
}
else
{
for (u++ ; u & 3 ; u++)
((byte *)pdest)[u] = pix;
u2 -= 4;
for ( ; u <= u2 ; u+=4)
*(int *)((byte *)pdest + u) = pix;
u2 += 4;
for ( ; u <= u2 ; u++)
((byte *)pdest)[u] = pix;
}
}
}
/*
==============
D_CalcGradients
==============
*/
void D_CalcGradients (msurface_t *pface)
{
mplane_t *pplane;
float mipscale;
vec3_t p_temp1;
vec3_t p_saxis, p_taxis;
float t;
pplane = pface->plane;
mipscale = 1.0 / (float)(1 << miplevel);
TransformVector (pface->texinfo->vecs[0], p_saxis);
TransformVector (pface->texinfo->vecs[1], p_taxis);
t = xscaleinv * mipscale;
d_sdivzstepu = p_saxis[0] * t;
d_tdivzstepu = p_taxis[0] * t;
t = yscaleinv * mipscale;
d_sdivzstepv = -p_saxis[1] * t;
d_tdivzstepv = -p_taxis[1] * t;
d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
VectorScale (transformed_modelorg, mipscale, p_temp1);
t = 0x10000*mipscale;
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs[0][3]*t;
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs[1][3]*t;
//
// -1 (-epsilon) so we never wander off the edge of the texture
//
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
/*
==============
D_DrawSurfaces
==============
*/
void D_DrawSurfaces (void)
{
surf_t *s;
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
currententity = &cl_entities[0];
TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
// TODO: could preset a lot of this at mode set time
if (r_drawflat.value)
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
D_DrawSolidSurface (s, (int)s->data & 0xFF);
D_DrawZSpans (s->spans);
}
}
else
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
r_drawnpolycount++;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
if (s->flags & SURF_DRAWSKY)
{
if (!r_skymade)
{
R_MakeSky ();
}
D_DrawSkyScans8 (s->spans);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWBACKGROUND)
{
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = -0.9;
D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWTURB)
{
pface = s->data;
miplevel = 0;
cacheblock = (pixel_t *)
((byte *)pface->texinfo->texture +
pface->texinfo->texture->offsets[0]);
cachewidth = 64;
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
D_CalcGradients (pface);
Turbulent8 (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
else
{
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin, local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
pface = s->data;
miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
* pface->texinfo->mipadjust);
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = D_CacheSurface (pface, miplevel);
cacheblock = (pixel_t *)pcurrentcache->data;
cachewidth = pcurrentcache->width;
D_CalcGradients (pface);
(*d_drawspans) (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
}
}
}

View file

@ -1,88 +0,0 @@
/*
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.
*/
// d_clear: clears a specified rectangle to the specified color
#include "quakedef.h"
/*
================
D_FillRect
================
*/
void D_FillRect (vrect_t *rect, int color)
{
int rx, ry, rwidth, rheight;
unsigned char *dest;
unsigned *ldest;
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
if (rx < 0)
{
rwidth += rx;
rx = 0;
}
if (ry < 0)
{
rheight += ry;
ry = 0;
}
if (rx+rwidth > vid.width)
rwidth = vid.width - rx;
if (ry+rheight > vid.height)
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx);
if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0))
{
// faster aligned dword clear
ldest = (unsigned *)dest;
color += color << 16;
rwidth >>= 2;
color += color << 8;
for (ry=0 ; ry<rheight ; ry++)
{
for (rx=0 ; rx<rwidth ; rx++)
ldest[rx] = color;
ldest = (unsigned *)((byte*)ldest + vid.rowbytes);
}
}
else
{
// slower byte-by-byte clear for unaligned cases
for (ry=0 ; ry<rheight ; ry++)
{
for (rx=0 ; rx<rwidth ; rx++)
dest[rx] = color;
dest += vid.rowbytes;
}
}
}

View file

@ -1,229 +0,0 @@
/*
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.
*/
// d_iface.h: interface header file for rasterization driver modules
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
#define MAX_LBM_HEIGHT 480
typedef struct
{
float u, v;
float s, t;
float zi;
} emitpoint_t;
typedef enum {
pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
} ptype_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct particle_s
{
// driver-usable fields
vec3_t org;
float color;
// drivers never touch the following fields
struct particle_s *next;
vec3_t vel;
float ramp;
float die;
ptype_t type;
} particle_t;
#define PARTICLE_Z_CLIP 8.0
typedef struct polyvert_s {
float u, v, zi, s, t;
} polyvert_t;
typedef struct polydesc_s {
int numverts;
float nearzi;
msurface_t *pcurrentface;
polyvert_t *pverts;
} polydesc_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct finalvert_s {
int v[6]; // u, v, s, t, l, 1/z
int flags;
float reserved;
} finalvert_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct
{
void *pskin;
maliasskindesc_t *pskindesc;
int skinwidth;
int skinheight;
mtriangle_t *ptriangles;
finalvert_t *pfinalverts;
int numtriangles;
int drawtype;
int seamfixupX16;
} affinetridesc_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct {
float u, v, zi, color;
} screenpart_t;
typedef struct
{
int nump;
emitpoint_t *pverts; // there's room for an extra element at [nump],
// if the driver wants to duplicate element [0] at
// element [nump] to avoid dealing with wrapping
mspriteframe_t *pspriteframe;
vec3_t vup, vright, vpn; // in worldspace
float nearzi;
} spritedesc_t;
typedef struct
{
int u, v;
float zi;
int color;
} zpointdesc_t;
extern cvar_t r_drawflat;
extern int d_spanpixcount;
extern int r_framecount; // sequence # of current frame since Quake
// started
extern qboolean r_drawpolys; // 1 if driver wants clipped polygons
// rather than a span list
extern qboolean r_drawculledpolys; // 1 if driver wants clipped polygons that
// have been culled by the edge list
extern qboolean r_worldpolysbacktofront; // 1 if driver wants polygons
// delivered back to front rather
// than front to back
extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use
// recursive triangular subdivison
// and vertex drawing via
// D_PolysetDrawFinalVerts() past
// a certain distance (normally
// only used by the software
// driver)
extern float r_aliasuvscale; // scale-up factor for screen u and v
// on Alias vertices passed to driver
extern int r_pixbytes;
extern qboolean r_dowarp;
extern affinetridesc_t r_affinetridesc;
extern spritedesc_t r_spritedesc;
extern zpointdesc_t r_zpointdesc;
extern polydesc_t r_polydesc;
extern int d_con_indirect; // if 0, Quake will draw console directly
// to vid.buffer; if 1, Quake will
// draw console via D_DrawRect. Must be
// defined by driver
extern vec3_t r_pright, r_pup, r_ppn;
void D_Aff8Patch (void *pcolormap);
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height);
void D_DisableBackBufferAccess (void);
void D_EndDirectRect (int x, int y, int width, int height);
void D_PolysetDraw (void);
void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
void D_DrawParticle (particle_t *pparticle);
void D_DrawPoly (void);
void D_DrawSprite (void);
void D_DrawSurfaces (void);
void D_DrawZPoint (void);
void D_EnableBackBufferAccess (void);
void D_EndParticles (void);
void D_Init (void);
void D_ViewChanged (void);
void D_SetupFrame (void);
void D_StartParticles (void);
void D_TurnZOn (void);
void D_WarpScreen (void);
void D_FillRect (vrect_t *vrect, int color);
void D_DrawRect (void);
void D_UpdateRects (vrect_t *prect);
// currently for internal use only, and should be a do-nothing function in
// hardware drivers
// FIXME: this should go away
void D_PolysetUpdateTables (void);
// these are currently for internal use only, and should not be used by drivers
extern int r_skydirect;
extern byte *r_skysource;
// transparency types for D_DrawRect ()
#define DR_SOLID 0
#define DR_TRANSPARENT 1
// !!! must be kept the same as in quakeasm.h !!!
#define TRANSPARENT_COLOR 0xFF
extern void *acolormap; // FIXME: should go away
//=======================================================================//
// callbacks to Quake
typedef struct
{
pixel_t *surfdat; // destination for generated surface
int rowbytes; // destination logical width in bytes
msurface_t *surf; // description for surface to generate
fixed8_t lightadj[MAXLIGHTMAPS];
// adjust for lightmap levels for dynamic lighting
texture_t *texture; // corrected for animating textures
int surfmip; // mipmapped ratio of surface texels / world pixels
int surfwidth; // in mipmapped texels
int surfheight; // in mipmapped texels
} drawsurf_t;
extern drawsurf_t r_drawsurf;
void R_DrawSurface (void);
void R_GenTile (msurface_t *psurf, void *pdest);
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define CYCLE 128 // turbulent cycle size
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
#define SKYSHIFT 7
#define SKYSIZE (1 << SKYSHIFT)
#define SKYMASK (SKYSIZE - 1)
extern float skyspeed, skyspeed2;
extern float skytime;
extern int c_surf;
extern vrect_t scr_vrect;
extern byte *r_warpbuffer;

View file

@ -1,98 +0,0 @@
/*
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.
*/
//
// d_ifacea.h
//
// Include file for asm driver interface.
//
//
// !!! note that this file must match the corresponding C structures in
// d_iface.h at all times !!!
//
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define ALIAS_ONSEAM 0x0020
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define CYCLE 128
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define MAXHEIGHT 1024
// !!! if this is changed, it must be changed in quakedef.h too !!!
#define CACHE_SIZE 32 // used to align key data structures
// particle_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
// driver-usable fields
#define pt_org 0
#define pt_color 12
// drivers never touch the following fields
#define pt_next 16
#define pt_vel 20
#define pt_ramp 32
#define pt_die 36
#define pt_type 40
#define pt_size 44
#define PARTICLE_Z_CLIP 8.0
// finalvert_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define fv_v 0 // !!! if this is moved, cases where the !!!
// !!! address of this field is pushed in !!!
// !!! d_polysa.s must be changed !!!
#define fv_flags 24
#define fv_reserved 28
#define fv_size 32
#define fv_shift 5
// stvert_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define stv_onseam 0
#define stv_s 4
#define stv_t 8
#define stv_size 12
// trivertx_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define tv_v 0
#define tv_lightnormalindex 3
#define tv_size 4
// affinetridesc_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define atd_pskin 0
#define atd_pskindesc 4
#define atd_skinwidth 8
#define atd_skinheight 12
#define atd_ptriangles 16
#define atd_pfinalverts 20
#define atd_numtriangles 24
#define atd_drawtype 28
#define atd_seamfixupX16 32
#define atd_size 36

View file

@ -1,173 +0,0 @@
/*
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.
*/
// d_init.c: rasterization driver initialization
#include "quakedef.h"
#include "d_local.h"
#define NUM_MIPS 4
cvar_t d_subdiv16 = {"d_subdiv16", "1"};
cvar_t d_mipcap = {"d_mipcap", "0"};
cvar_t d_mipscale = {"d_mipscale", "1"};
surfcache_t *d_initial_rover;
qboolean d_roverwrapped;
int d_minmip;
float d_scalemip[NUM_MIPS-1];
static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
extern int d_aflatcolor;
void (*d_drawspans) (espan_t *pspan);
/*
===============
D_Init
===============
*/
void D_Init (void)
{
r_skydirect = 1;
Cvar_RegisterVariable (&d_subdiv16);
Cvar_RegisterVariable (&d_mipcap);
Cvar_RegisterVariable (&d_mipscale);
r_drawpolys = false;
r_worldpolysbacktofront = false;
r_recursiveaffinetriangles = true;
r_pixbytes = 1;
r_aliasuvscale = 1.0;
}
/*
===============
D_CopyRects
===============
*/
void D_CopyRects (vrect_t *prects, int transparent)
{
// this function is only required if the CPU doesn't have direct access to the
// back buffer, and there's some driver interface function that the driver
// doesn't support and requires Quake to do in software (such as drawing the
// console); Quake will then draw into wherever the driver points vid.buffer
// and will call this function before swapping buffers
UNUSED(prects);
UNUSED(transparent);
}
/*
===============
D_EnableBackBufferAccess
===============
*/
void D_EnableBackBufferAccess (void)
{
VID_LockBuffer ();
}
/*
===============
D_TurnZOn
===============
*/
void D_TurnZOn (void)
{
// not needed for software version
}
/*
===============
D_DisableBackBufferAccess
===============
*/
void D_DisableBackBufferAccess (void)
{
VID_UnlockBuffer ();
}
/*
===============
D_SetupFrame
===============
*/
void D_SetupFrame (void)
{
int i;
if (r_dowarp)
d_viewbuffer = r_warpbuffer;
else
d_viewbuffer = (void *)(byte *)vid.buffer;
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
d_roverwrapped = false;
d_initial_rover = sc_rover;
d_minmip = d_mipcap.value;
if (d_minmip > 3)
d_minmip = 3;
else if (d_minmip < 0)
d_minmip = 0;
for (i=0 ; i<(NUM_MIPS-1) ; i++)
d_scalemip[i] = basemip[i] * d_mipscale.value;
#if id386
if (d_subdiv16.value)
d_drawspans = D_DrawSpans16;
else
d_drawspans = D_DrawSpans8;
#else
d_drawspans = D_DrawSpans8;
#endif
d_aflatcolor = 0;
}
/*
===============
D_UpdateRects
===============
*/
void D_UpdateRects (vrect_t *prect)
{
// the software driver draws these directly to the vid buffer
UNUSED(prect);
}

View file

@ -1,111 +0,0 @@
/*
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.
*/
// d_local.h: private rasterization driver defs
#include "r_shared.h"
//
// TODO: fine-tune this; it's based on providing some overage even if there
// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each
//
#define SCANBUFFERPAD 0x1000
#define R_SKY_SMASK 0x007F0000
#define R_SKY_TMASK 0x007F0000
#define DS_SPAN_LIST_END -128
#define SURFCACHE_SIZE_AT_320X200 600*1024
typedef struct surfcache_s
{
struct surfcache_s *next;
struct surfcache_s **owner; // NULL is an empty chunk of memory
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
int dlight;
int size; // including header
unsigned width;
unsigned height; // DEBUG only needed for debug
float mipscale;
struct texture_s *texture; // checked for animating textures
byte data[4]; // width*height elements
} surfcache_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct sspan_s
{
int u, v, count;
} sspan_t;
extern cvar_t d_subdiv16;
extern float scale_for_mip;
extern qboolean d_roverwrapped;
extern surfcache_t *sc_rover;
extern surfcache_t *d_initial_rover;
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
fixed16_t sadjust, tadjust;
fixed16_t bbextents, bbextentt;
void D_DrawSpans8 (espan_t *pspans);
void D_DrawSpans16 (espan_t *pspans);
void D_DrawZSpans (espan_t *pspans);
void Turbulent8 (espan_t *pspan);
void D_SpriteDrawSpans (sspan_t *pspan);
void D_DrawSkyScans8 (espan_t *pspan);
void D_DrawSkyScans16 (espan_t *pspan);
void R_ShowSubDiv (void);
void (*prealspandrawer)(void);
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
extern int D_MipLevelForScale (float scale);
#if id386
extern void D_PolysetAff8Start (void);
extern void D_PolysetAff8End (void);
#endif
extern short *d_pzbuffer;
extern unsigned int d_zrowbytes, d_zwidth;
extern int *d_pscantable;
extern int d_scantable[MAXHEIGHT];
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
extern pixel_t *d_viewbuffer;
extern short *zspantable[MAXHEIGHT];
extern int d_minmip;
extern float d_scalemip[3];
extern void (*d_drawspans) (espan_t *pspan);

View file

@ -1,107 +0,0 @@
/*
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.
*/
// d_modech.c: called when mode has just changed
#include "quakedef.h"
#include "d_local.h"
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
int d_scantable[MAXHEIGHT];
short *zspantable[MAXHEIGHT];
/*
================
D_Patch
================
*/
void D_Patch (void)
{
#if id386
static qboolean protectset8 = false;
if (!protectset8)
{
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
(int)D_PolysetAff8End - (int)D_PolysetAff8Start);
protectset8 = true;
}
#endif // id386
}
/*
================
D_ViewChanged
================
*/
void D_ViewChanged (void)
{
int rowbytes;
if (r_dowarp)
rowbytes = WARP_WIDTH;
else
rowbytes = vid.rowbytes;
scale_for_mip = xscale;
if (yscale > xscale)
scale_for_mip = yscale;
d_zrowbytes = vid.width * 2;
d_zwidth = vid.width;
d_pix_min = r_refdef.vrect.width / 320;
if (d_pix_min < 1)
d_pix_min = 1;
d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
if (d_pix_max < 1)
d_pix_max = 1;
if (pixelAspect > 1.4)
d_y_aspect_shift = 1;
else
d_y_aspect_shift = 0;
d_vrectx = r_refdef.vrect.x;
d_vrecty = r_refdef.vrect.y;
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
d_vrectbottom_particle =
r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
{
int i;
for (i=0 ; i<vid.height; i++)
{
d_scantable[i] = i*rowbytes;
zspantable[i] = d_pzbuffer + i*d_zwidth;
}
}
D_Patch ();
}

View file

@ -1,207 +0,0 @@
/*
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.
*/
// d_part.c: software driver module for drawing particles
#include "quakedef.h"
#include "d_local.h"
/*
==============
D_EndParticles
==============
*/
void D_EndParticles (void)
{
// not used by software driver
}
/*
==============
D_StartParticles
==============
*/
void D_StartParticles (void)
{
// not used by software driver
}
#if !id386
/*
==============
D_DrawParticle
==============
*/
void D_DrawParticle (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
byte *pdest;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtract (pparticle->org, r_origin, local);
transformed[0] = DotProduct(local, r_pright);
transformed[1] = DotProduct(local, r_pup);
transformed[2] = DotProduct(local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
// project the point
// FIXME: preadjust xcenter and ycenter
zi = 1.0 / transformed[2];
u = (int)(xcenter + zi * transformed[0] + 0.5);
v = (int)(ycenter - zi * transformed[1] + 0.5);
if ((v > d_vrectbottom_particle) ||
(u > d_vrectright_particle) ||
(v < d_vrecty) ||
(u < d_vrectx))
{
return;
}
pz = d_pzbuffer + (d_zwidth * v) + u;
pdest = d_viewbuffer + d_scantable[v] + u;
izi = (int)(zi * 0x8000);
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
switch (pix)
{
case 1:
count = 1 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
}
break;
case 2:
count = 2 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
}
break;
case 3:
count = 3 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = pparticle->color;
}
}
break;
case 4:
count = 4 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = pparticle->color;
}
if (pz[3] <= izi)
{
pz[3] = izi;
pdest[3] = pparticle->color;
}
}
break;
default:
count = pix << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = pparticle->color;
}
}
}
break;
}
}
#endif // !id386

File diff suppressed because it is too large Load diff

View file

@ -1,449 +0,0 @@
/*
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.
*/
// d_scan.c
//
// Portable C scan-level rasterization code, all pixel depths.
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
unsigned char *r_turb_pbase, *r_turb_pdest;
fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
int *r_turb_turb;
int r_turb_spancount;
void D_DrawTurbulent8Span (void);
/*
=============
D_WarpScreen
// this performs a slight compression of the screen at the same time as
// the sine warp, to keep the edges from wrapping
=============
*/
void D_WarpScreen (void)
{
int w, h;
int u,v;
byte *dest;
int *turb;
int *col;
byte **row;
byte *rowptr[MAXHEIGHT+(AMP2*2)];
int column[MAXWIDTH+(AMP2*2)];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float)scr_vrect.width;
hratio = h / (float)scr_vrect.height;
for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
{
rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
(screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
}
for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
{
column[u] = r_refdef.vrect.x +
(int)((float)u * wratio * w / (w + AMP2 * 2));
}
turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
{
col = &column[turb[v]];
row = &rowptr[v];
for (u=0 ; u<scr_vrect.width ; u+=4)
{
dest[u+0] = row[turb[u+0]][col[u+0]];
dest[u+1] = row[turb[u+1]][col[u+1]];
dest[u+2] = row[turb[u+2]][col[u+2]];
dest[u+3] = row[turb[u+3]][col[u+3]];
}
}
}
#if !id386
/*
=============
D_DrawTurbulent8Span
=============
*/
void D_DrawTurbulent8Span (void)
{
int sturb, tturb;
do
{
sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
}
#endif // !id386
/*
=============
Turbulent8
=============
*/
void Turbulent8 (espan_t *pspan)
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz16stepu, tdivz16stepu, zi16stepu;
r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
r_turb_sstep = 0; // keep compiler happy
r_turb_tstep = 0; // ditto
r_turb_pbase = (unsigned char *)cacheblock;
sdivz16stepu = d_sdivzstepu * 16;
tdivz16stepu = d_tdivzstepu * 16;
zi16stepu = d_zistepu * 16;
do
{
r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
r_turb_s = (int)(sdivz * z) + sadjust;
if (r_turb_s > bbextents)
r_turb_s = bbextents;
else if (r_turb_s < 0)
r_turb_s = 0;
r_turb_t = (int)(tdivz * z) + tadjust;
if (r_turb_t > bbextentt)
r_turb_t = bbextentt;
else if (r_turb_t < 0)
r_turb_t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 16)
r_turb_spancount = 16;
else
r_turb_spancount = count;
count -= r_turb_spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz16stepu;
tdivz += tdivz16stepu;
zi += zi16stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on <0 steps
r_turb_sstep = (snext - r_turb_s) >> 4;
r_turb_tstep = (tnext - r_turb_t) >> 4;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(r_turb_spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on <0 steps
if (r_turb_spancount > 1)
{
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
}
}
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
D_DrawTurbulent8Span ();
r_turb_s = snext;
r_turb_t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#if !id386
/*
=============
D_DrawSpans8
=============
*/
void D_DrawSpans8 (espan_t *pspan)
{
int count, spancount;
unsigned char *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (unsigned char *)cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do
{
*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#endif
#if !id386
/*
=============
D_DrawZSpans
=============
*/
void D_DrawZSpans (espan_t *pspan)
{
int count, doublecount, izistep;
int izi;
short *pdest;
unsigned ltemp;
double zi;
float du, dv;
// FIXME: check for clamping/range problems
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial 1/z
du = (float)pspan->u;
dv = (float)pspan->v;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
if ((long)pdest & 0x02)
{
*pdest++ = (short)(izi >> 16);
izi += izistep;
count--;
}
if ((doublecount = count >> 1) > 0)
{
do
{
ltemp = izi >> 16;
izi += izistep;
ltemp |= izi & 0xFFFF0000;
izi += izistep;
*(int *)pdest = ltemp;
pdest += 2;
} while (--doublecount > 0);
}
if (count & 1)
*pdest = (short)(izi >> 16);
} while ((pspan = pspan->pnext) != NULL);
}
#endif

View file

@ -1,138 +0,0 @@
/*
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.
*/
// d_sky.c
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
#define SKY_SPAN_SHIFT 5
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
/*
=================
D_Sky_uv_To_st
=================
*/
void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
{
float wu, wv, temp;
vec3_t end;
if (r_refdef.vrect.width >= r_refdef.vrect.height)
temp = (float)r_refdef.vrect.width;
else
temp = (float)r_refdef.vrect.height;
wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp;
wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp;
end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
end[2] *= 3;
VectorNormalize (end);
temp = skytime*skyspeed; // TODO: add D_SetupFrame & set this there
*s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
*t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
}
/*
=================
D_DrawSkyScans8
=================
*/
void D_DrawSkyScans8 (espan_t *pspan)
{
int count, spancount, u, v;
unsigned char *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do
{
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count)
{
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
}
else
{
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float)(spancount - 1);
if (spancountminus1 > 0)
{
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do
{
*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}

View file

@ -1,442 +0,0 @@
/*
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.
*/
// d_sprite.c: software top-level rasterization driver module for drawing
// sprites
#include "quakedef.h"
#include "d_local.h"
static int sprite_height;
static int minindex, maxindex;
static sspan_t *sprite_spans;
#if !id386
/*
=====================
D_SpriteDrawSpans
=====================
*/
void D_SpriteDrawSpans (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do
{
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (btemp != 255)
{
if (*pz <= (izi >> 16))
{
*pz = izi >> 16;
*pdest = btemp;
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
#endif
/*
=====================
D_SpriteScanLeftEdge
=====================
*/
void D_SpriteScanLeftEdge (void)
{
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
if (i == 0)
i = r_spritedesc.nump;
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = r_spritedesc.nump;
vtop = ceil (r_spritedesc.pverts[i].v);
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert - 1;
vbottom = ceil (pnext->v);
if (vtop < vbottom)
{
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
vtop = vbottom;
i--;
if (i == 0)
i = r_spritedesc.nump;
} while (i != lmaxindex);
}
/*
=====================
D_SpriteScanRightEdge
=====================
*/
void D_SpriteScanRightEdge (void)
{
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
vvert = r_spritedesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
vtop = ceil (vvert);
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert + 1;
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
vbottom = ceil (vnext);
if (vtop < vbottom)
{
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
vtop = vbottom;
vvert = vnext;
i++;
if (i == r_spritedesc.nump)
i = 0;
} while (i != maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
/*
=====================
D_SpriteCalculateGradients
=====================
*/
void D_SpriteCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
float distinv;
TransformVector (r_spritedesc.vpn, p_normal);
TransformVector (r_spritedesc.vright, p_saxis);
TransformVector (r_spritedesc.vup, p_taxis);
VectorInverse (p_taxis);
distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
ycenter * d_zistepv;
TransformVector (modelorg, p_temp1);
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(cachewidth >> 1) << 16);
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (cachewidth << 16) - 1;
bbextentt = (sprite_height << 16) - 1;
}
/*
=====================
D_DrawSprite
=====================
*/
void D_DrawSprite (void)
{
int i, nump;
float ymin, ymax;
emitpoint_t *pverts;
sspan_t spans[MAXHEIGHT+1];
sprite_spans = spans;
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin = 999999.9;
ymax = -999999.9;
pverts = r_spritedesc.pverts;
for (i=0 ; i<r_spritedesc.nump ; i++)
{
if (pverts->v < ymin)
{
ymin = pverts->v;
minindex = i;
}
if (pverts->v > ymax)
{
ymax = pverts->v;
maxindex = i;
}
pverts++;
}
ymin = ceil (ymin);
ymax = ceil (ymax);
if (ymin >= ymax)
return; // doesn't cross any scans at all
cachewidth = r_spritedesc.pspriteframe->width;
sprite_height = r_spritedesc.pspriteframe->height;
cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0];
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_spritedesc.nump;
pverts = r_spritedesc.pverts;
pverts[nump] = pverts[0];
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
D_SpriteDrawSpans (sprite_spans);
}

View file

@ -1,335 +0,0 @@
/*
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.
*/
// d_surf.c: rasterization driver surface heap manager
#include "quakedef.h"
#include "d_local.h"
#include "r_local.h"
float surfscale;
qboolean r_cache_thrash; // set if surface cache is thrashing
int sc_size;
surfcache_t *sc_rover, *sc_base;
#define GUARDSIZE 4
int D_SurfaceCacheForRes (int width, int height)
{
int size, pix;
if (COM_CheckParm ("-surfcachesize"))
{
size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
return size;
}
size = SURFCACHE_SIZE_AT_320X200;
pix = width*height;
if (pix > 64000)
size += (pix-64000)*3;
return size;
}
void D_CheckCacheGuard (void)
{
byte *s;
int i;
s = (byte *)sc_base + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
if (s[i] != (byte)i)
Sys_Error ("D_CheckCacheGuard: failed");
}
void D_ClearCacheGuard (void)
{
byte *s;
int i;
s = (byte *)sc_base + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
s[i] = (byte)i;
}
/*
================
D_InitCaches
================
*/
void D_InitCaches (void *buffer, int size)
{
if (!msg_suppress_1)
Con_Printf ("%ik surface cache\n", size/1024);
sc_size = size - GUARDSIZE;
sc_base = (surfcache_t *)buffer;
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
D_ClearCacheGuard ();
}
/*
==================
D_FlushCaches
==================
*/
void D_FlushCaches (void)
{
surfcache_t *c;
if (!sc_base)
return;
for (c = sc_base ; c ; c = c->next)
{
if (c->owner)
*c->owner = NULL;
}
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
}
/*
=================
D_SCAlloc
=================
*/
surfcache_t *D_SCAlloc (int width, int size)
{
surfcache_t *new;
qboolean wrapped_this_time;
if ((width < 0) || (width > 256))
Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
if ((size <= 0) || (size > 0x10000))
Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
size = (int)&((surfcache_t *)0)->data[size];
size = (size + 3) & ~3;
if (size > sc_size)
Sys_Error ("D_SCAlloc: %i > cache size",size);
// if there is not size bytes after the rover, reset to the start
wrapped_this_time = false;
if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
{
if (sc_rover)
{
wrapped_this_time = true;
}
sc_rover = sc_base;
}
// colect and free surfcache_t blocks until the rover block is large enough
new = sc_rover;
if (sc_rover->owner)
*sc_rover->owner = NULL;
while (new->size < size)
{
// free another
sc_rover = sc_rover->next;
if (!sc_rover)
Sys_Error ("D_SCAlloc: hit the end of memory");
if (sc_rover->owner)
*sc_rover->owner = NULL;
new->size += sc_rover->size;
new->next = sc_rover->next;
}
// create a fragment out of any leftovers
if (new->size - size > 256)
{
sc_rover = (surfcache_t *)( (byte *)new + size);
sc_rover->size = new->size - size;
sc_rover->next = new->next;
sc_rover->width = 0;
sc_rover->owner = NULL;
new->next = sc_rover;
new->size = size;
}
else
sc_rover = new->next;
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
new->owner = NULL; // should be set properly after return
if (d_roverwrapped)
{
if (wrapped_this_time || (sc_rover >= d_initial_rover))
r_cache_thrash = true;
}
else if (wrapped_this_time)
{
d_roverwrapped = true;
}
D_CheckCacheGuard (); // DEBUG
return new;
}
/*
=================
D_SCDump
=================
*/
void D_SCDump (void)
{
surfcache_t *test;
for (test = sc_base ; test ; test = test->next)
{
if (test == sc_rover)
Sys_Printf ("ROVER:\n");
printf ("%p : %i bytes %i width\n",test, test->size, test->width);
}
}
//=============================================================================
// if the num is not a power of 2, assume it will not repeat
int MaskForNum (int num)
{
if (num==128)
return 127;
if (num==64)
return 63;
if (num==32)
return 31;
if (num==16)
return 15;
return 255;
}
int D_log2 (int num)
{
int c;
c = 0;
while (num>>=1)
c++;
return c;
}
//=============================================================================
/*
================
D_CacheSurface
================
*/
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
{
surfcache_t *cache;
//
// if the surface is animating or flashing, flush the cache
//
r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
//
// see if the cache holds apropriate data
//
cache = surface->cachespots[miplevel];
if (cache && !cache->dlight && surface->dlightframe != r_framecount
&& cache->texture == r_drawsurf.texture
&& cache->lightadj[0] == r_drawsurf.lightadj[0]
&& cache->lightadj[1] == r_drawsurf.lightadj[1]
&& cache->lightadj[2] == r_drawsurf.lightadj[2]
&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
return cache;
//
// determine shape of surface
//
surfscale = 1.0 / (1<<miplevel);
r_drawsurf.surfmip = miplevel;
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
//
// allocate memory if needed
//
if (!cache) // if a texture just animated, don't reallocate it
{
cache = D_SCAlloc (r_drawsurf.surfwidth,
r_drawsurf.surfwidth * r_drawsurf.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscale;
}
if (surface->dlightframe == r_framecount)
cache->dlight = 1;
else
cache->dlight = 0;
r_drawsurf.surfdat = (pixel_t *)cache->data;
cache->texture = r_drawsurf.texture;
cache->lightadj[0] = r_drawsurf.lightadj[0];
cache->lightadj[1] = r_drawsurf.lightadj[1];
cache->lightadj[2] = r_drawsurf.lightadj[2];
cache->lightadj[3] = r_drawsurf.lightadj[3];
//
// draw and light the surface texture
//
r_drawsurf.surf = surface;
c_surf++;
R_DrawSurface ();
return surface->cachespots[miplevel];
}

View file

@ -1,50 +0,0 @@
/*
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.
*/
// r_vars.c: global refresh variables
#if !id386
#include "quakedef.h"
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
float d_sdivzstepu, d_tdivzstepu, d_zistepu;
float d_sdivzstepv, d_tdivzstepv, d_zistepv;
float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
fixed16_t sadjust, tadjust, bbextents, bbextentt;
pixel_t *cacheblock;
int cachewidth;
pixel_t *d_viewbuffer;
short *d_pzbuffer;
unsigned int d_zrowbytes;
unsigned int d_zwidth;
#endif // !id386

View file

@ -1,47 +0,0 @@
/*
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.
*/
// d_zpoint.c: software driver module for drawing z-buffered points
#include "quakedef.h"
#include "d_local.h"
/*
=====================
D_DrawZPoint
=====================
*/
void D_DrawZPoint (void)
{
byte *pdest;
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
izi = (int)(r_zpointdesc.zi * 0x8000);
if (*pz <= izi)
{
*pz = izi;
*pdest = r_zpointdesc.color;
}
}

View file

@ -1,257 +0,0 @@
/*
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.
*/
#include <sys/segments.h>
#include <go32.h>
#include <unistd.h>
#include <sys/nearptr.h>
#include <dos.h>
#include <string.h>
#include <dpmi.h>
// #include <osfcn.h>
#include <bios.h>
#include "dosisms.h"
_go32_dpmi_registers hmm;
// globals
regs_t regs;
void (*dos_error_func)(char *msg, ...);
static unsigned conventional_memory = -1;
__dpmi_regs callback_regs;
void map_in_conventional_memory(void)
{
if (conventional_memory == -1)
{
if (__djgpp_nearptr_enable())
{
conventional_memory = __djgpp_conventional_base;
}
}
}
unsigned int ptr2real(void *ptr)
{
map_in_conventional_memory();
return (int)ptr - conventional_memory;
}
void *real2ptr(unsigned int real)
{
map_in_conventional_memory();
return (void *) (real + conventional_memory);
}
void *far2ptr(unsigned int farptr)
{
return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff));
}
unsigned int ptr2far(void *ptr)
{
return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf);
}
int dos_inportb(int port)
{
return inportb(port);
}
int dos_inportw(int port)
{
return inportw(port);
}
void dos_outportb(int port, int val)
{
outportb(port, val);
}
void dos_outportw(int port, int val)
{
outportw(port, val);
}
void dos_irqenable(void)
{
enable();
}
void dos_irqdisable(void)
{
disable();
}
//
// Returns 0 on success
//
int dos_int86(int vec)
{
int rc;
regs.x.ss = regs.x.sp = 0;
rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) &regs);
return rc || (regs.x.flags & 1);
}
int dos_int386(int vec, regs_t *inregs, regs_t *outregs)
{
int rc;
memcpy(outregs, inregs, sizeof(regs_t));
outregs->x.ss = outregs->x.sp = 0;
rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs);
return rc || (outregs->x.flags & 1);
}
//
// Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep
// the seginfo structure around for when you free the mem.
//
static _go32_dpmi_seginfo seginfo[10];
void *dos_getmemory(int size)
{
int rc;
_go32_dpmi_seginfo info;
static int firsttime=1;
int i;
if (firsttime)
{
memset(seginfo, 0, sizeof(seginfo));
firsttime = 0;
}
info.size = (size+15) / 16;
rc = _go32_dpmi_allocate_dos_memory(&info);
if (rc)
return 0;
for (i=0;i<10;i++)
if (!seginfo[i].rm_segment) break;
seginfo[i] = info;
return real2ptr((int) info.rm_segment << 4);
}
void dos_freememory(void *ptr)
{
int i;
int segment;
segment = ptr2real(ptr) >> 4;
for (i=0 ; i<10 ; i++)
if (seginfo[i].rm_segment == segment)
{
_go32_dpmi_free_dos_memory(&seginfo[i]);
seginfo[i].rm_segment = 0;
break;
}
}
static struct handlerhistory_s
{
int intr;
_go32_dpmi_seginfo pm_oldvec;
} handlerhistory[4];
static int handlercount=0;
void dos_registerintr(int intr, void (*handler)(void))
{
_go32_dpmi_seginfo info;
struct handlerhistory_s *oldstuff;
oldstuff = &handlerhistory[handlercount];
// remember old handler
_go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec);
oldstuff->intr = intr;
info.pm_offset = (int) handler;
_go32_dpmi_allocate_iret_wrapper(&info);
// set new protected mode handler
_go32_dpmi_set_protected_mode_interrupt_vector(intr, &info);
handlercount++;
}
void dos_restoreintr(int intr)
{
int i;
struct handlerhistory_s *oldstuff;
// find and reinstall previous interrupt
for (i=0 ; i<handlercount ; i++)
{
oldstuff = &handlerhistory[i];
if (oldstuff->intr == intr)
{
_go32_dpmi_set_protected_mode_interrupt_vector(intr,
&oldstuff->pm_oldvec);
oldstuff->intr = -1;
break;
}
}
}
void dos_usleep(int usecs)
{
usleep(usecs);
}
int dos_getheapsize(void)
{
return _go32_dpmi_remaining_physical_memory();
}
int dos_lockmem(void *addr, int size)
{
__dpmi_meminfo info;
info.address = (long) addr + __djgpp_base_address;
info.size = size;
if (__dpmi_lock_linear_region(&info))
return __dpmi_error;
else
return 0;
}
int dos_unlockmem(void *addr, int size)
{
__dpmi_meminfo info;
info.address = (long) addr + __djgpp_base_address;
info.size = size;
if (__dpmi_unlock_linear_region(&info))
return __dpmi_error;
else
return 0;
}

View file

@ -62,7 +62,6 @@ BRUSH MODELS
//
// in memory representation
//
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vec3_t position;
@ -74,7 +73,6 @@ typedef struct
// plane_t structure
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct mplane_s
{
vec3_t normal;
@ -109,7 +107,6 @@ typedef struct texture_s
#define TEXFLAG_NODRAW 256
#define TEXFLAG_LIGHT 512
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
unsigned short v[2];
@ -208,7 +205,6 @@ typedef struct mleaf_s
byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t;
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
dclipnode_t *clipnodes;
@ -296,7 +292,6 @@ typedef struct
maliasgroupframedesc_t frames[1];
} maliasgroup_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct mtriangle_s {
int facesfront;
int vertindex[3];

View file

@ -1,211 +0,0 @@
/*
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.
*/
// disable data conversion warnings
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4136) // X86
#pragma warning(disable : 4051) // ALPHA
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
void GL_BeginRendering (int *x, int *y, int *width, int *height);
void GL_EndRendering (void);
// Function prototypes for the Texture Object Extension routines
typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *,
const GLboolean *);
typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint);
typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *);
typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *);
typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint);
typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
const GLclampf *);
typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *);
extern BINDTEXFUNCPTR bindTexFunc;
extern DELTEXFUNCPTR delTexFunc;
extern TEXSUBIMAGEPTR TexSubImage2DFunc;
extern int texture_extension_number;
extern int texture_mode;
extern float gldepthmin, gldepthmax;
void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate);
void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate);
int GL_LoadTexture (char *identifier, int width, int height, byte *data, int mipmap, int alpha, int modulate);
int GL_FindTexture (char *identifier);
typedef struct
{
float x, y, z;
float s, t;
float r, g, b;
} glvert_t;
extern glvert_t glv;
extern int glx, gly, glwidth, glheight;
extern PROC glArrayElementEXT;
extern PROC glColorPointerEXT;
extern PROC glTexturePointerEXT;
extern PROC glVertexPointerEXT;
// r_local.h -- private refresh defs
#define MAXALIASVERTS 2000 // TODO: tune this
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
// normalizing factor so player model works out to about
// 1 pixel per triangle
#define MAX_LBM_HEIGHT 480
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
#define SKYSHIFT 7
#define SKYSIZE (1 << SKYSHIFT)
#define SKYMASK (SKYSIZE - 1)
#define BACKFACE_EPSILON 0.01
void R_TimeRefresh_f (void);
void R_ReadPointFile_f (void);
texture_t *R_TextureAnimation (texture_t *base);
typedef struct surfcache_s
{
struct surfcache_s *next;
struct surfcache_s **owner; // NULL is an empty chunk of memory
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
int dlight;
int size; // including header
unsigned width;
unsigned height; // DEBUG only needed for debug
float mipscale;
struct texture_s *texture; // checked for animating textures
byte data[4]; // width*height elements
} surfcache_t;
typedef struct
{
pixel_t *surfdat; // destination for generated surface
int rowbytes; // destination logical width in bytes
msurface_t *surf; // description for surface to generate
fixed8_t lightadj[MAXLIGHTMAPS];
// adjust for lightmap levels for dynamic lighting
texture_t *texture; // corrected for animating textures
int surfmip; // mipmapped ratio of surface texels / world pixels
int surfwidth; // in mipmapped texels
int surfheight; // in mipmapped texels
} drawsurf_t;
typedef enum {
pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
} ptype_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct particle_s
{
// driver-usable fields
vec3_t org;
float color;
// drivers never touch the following fields
struct particle_s *next;
vec3_t vel;
float ramp;
float die;
ptype_t type;
} particle_t;
//====================================================
extern entity_t r_worldentity;
extern qboolean r_cache_thrash; // compatability
extern vec3_t modelorg, r_entorigin;
extern entity_t *currententity;
extern int r_visframecount; // ??? what difs?
extern int r_framecount;
extern mplane_t frustum[4];
extern int c_brush_polys, c_alias_polys;
//
// view origin
//
extern vec3_t vup;
extern vec3_t vpn;
extern vec3_t vright;
extern vec3_t r_origin;
//
// screen size info
//
extern refdef_t r_refdef;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern texture_t *r_notexture_mip;
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value
extern qboolean envmap;
extern int currenttexture;
extern int particletexture;
extern int playertextures;
extern int skytexturenum; // index in cl.loadmodel, not gl texture object
extern cvar_t r_drawentities;
extern cvar_t r_drawworld;
extern cvar_t r_drawviewmodel;
extern cvar_t r_speeds;
extern cvar_t r_waterwarp;
extern cvar_t r_fullbright;
extern cvar_t r_lightmap;
extern cvar_t r_shadows;
extern cvar_t r_dynamic;
extern cvar_t r_lerpmodels;
extern cvar_t r_lerpmove;
extern cvar_t gl_clear;
extern cvar_t gl_cull;
extern cvar_t gl_poly;
extern cvar_t gl_texsort;
extern cvar_t gl_smoothmodels;
extern cvar_t gl_affinemodels;
extern cvar_t gl_fogblend;
extern cvar_t gl_polyblend;
extern cvar_t gl_keeptjunctions;
extern cvar_t gl_reporttjunctions;
extern int gl_lightmap_format;
extern int gl_solid_format;
extern int gl_alpha_format;
void R_TranslatePlayerSkin (int playernum);
void GL_Bind (int texnum);

View file

@ -20,10 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include <sys/dirent.h>
#ifdef _WIN32
#include "winquake.h"
#endif
extern cvar_t r_wateralpha;
extern cvar_t r_vsync;
extern cvar_t in_disable_analog;

View file

@ -43,7 +43,6 @@ BRUSH MODELS
//
// in memory representation
//
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vec3_t position;
@ -55,7 +54,6 @@ typedef struct
// plane_t structure
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct mplane_s
{
vec3_t normal;
@ -84,7 +82,6 @@ typedef struct texture_s
#define SURF_DRAWTILED 0x20
#define SURF_DRAWBACKGROUND 0x40
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
unsigned short v[2];
@ -165,7 +162,6 @@ typedef struct mleaf_s
byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t;
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
dclipnode_t *clipnodes;
@ -266,7 +262,6 @@ typedef struct
maliasskindesc_t skindescs[1];
} maliasskingroup_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct mtriangle_s {
int facesfront;
int vertindex[3];

View file

@ -1,797 +0,0 @@
/* WINSOCK.H--definitions to be used with the WINSOCK.DLL
* Copyright (c) 1993-1995, Microsoft Corp. All rights reserved.
*
* This header file corresponds to version 1.1 of the Windows Sockets specification.
*
* This file includes parts which are Copyright (c) 1982-1986 Regents
* of the University of California. All rights reserved. The
* Berkeley Software License Agreement specifies the terms and
* conditions for redistribution.
*
*/
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_
#define FAR
#define PASCAL
/*
* Basic system type definitions, taken from the BSD file sys/types.h.
*/
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
/*
* The new type to be used in all
* instances which refer to sockets.
*/
typedef u_int SOCKET;
// FIXME
#if 0
/*
* Select uses arrays of SOCKETs. These macros manipulate such
* arrays. FD_SETSIZE may be defined by the user before including
* this file, but the default here should be >= 64.
*
* CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE
* INCLUDED IN WINSOCK.H EXACTLY AS SHOWN HERE.
*/
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */
typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;
#ifdef __cplusplus
extern "C" {
#endif
extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *);
#ifdef __cplusplus
}
#endif
#define FD_CLR(fd, set) do { \
u_int __i; \
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == fd) { \
while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
((fd_set FAR *)(set))->fd_array[__i] = \
((fd_set FAR *)(set))->fd_array[__i+1]; \
__i++; \
} \
((fd_set FAR *)(set))->fd_count--; \
break; \
} \
} \
} while(0)
#define FD_SET(fd, set) do { \
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) \
((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\
} while(0)
#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0)
#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set))
/*
* Structure used in select() call, taken from the BSD file sys/time.h.
*/
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
/*
* Operations on timevals.
*
* NB: timercmp does not work for >= or <=.
*/
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timercmp(tvp, uvp, cmp) \
((tvp)->tv_sec cmp (uvp)->tv_sec || \
(tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
#endif
/*
* Commands for ioctlsocket(), taken from the BSD file fcntl.h.
*
*
* Ioctl's have the command encoded in the lower word,
* and the size of any in or out parameters in the upper
* word. The high 2 bits of the upper word are used
* to encode the in/out status of the parameter; for now
* we restrict parameters to at most 128 bytes.
*/
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out parameters */
#define IOC_IN 0x80000000 /* copy in parameters */
#define IOC_INOUT (IOC_IN|IOC_OUT)
/* 0x20000000 distinguishes new &
old ioctl's */
#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
#define FIONREAD _IOR('f', 127, u_long) /* get # bytes to read */
#define FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i/o */
#define FIOASYNC _IOW('f', 125, u_long) /* set/clear async i/o */
/* Socket I/O Controls */
#define SIOCSHIWAT _IOW('s', 0, u_long) /* set high watermark */
#define SIOCGHIWAT _IOR('s', 1, u_long) /* get high watermark */
#define SIOCSLOWAT _IOW('s', 2, u_long) /* set low watermark */
#define SIOCGLOWAT _IOR('s', 3, u_long) /* get low watermark */
#define SIOCATMARK _IOR('s', 7, u_long) /* at oob mark? */
/*
* Structures returned by network data base library, taken from the
* BSD file netdb.h. All addresses are supplied in host order, and
* returned in network order (suitable for use in system calls).
*/
struct hostent {
char FAR * h_name; /* official name of host */
char FAR * FAR * h_aliases; /* alias list */
short h_addrtype; /* host address type */
short h_length; /* length of address */
char FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr h_addr_list[0] /* address, for backward compat */
};
/*
* It is assumed here that a network number
* fits in 32 bits.
*/
struct netent {
char FAR * n_name; /* official name of net */
char FAR * FAR * n_aliases; /* alias list */
short n_addrtype; /* net address type */
u_long n_net; /* network # */
};
struct servent {
char FAR * s_name; /* official service name */
char FAR * FAR * s_aliases; /* alias list */
short s_port; /* port # */
char FAR * s_proto; /* protocol to use */
};
struct protoent {
char FAR * p_name; /* official protocol name */
char FAR * FAR * p_aliases; /* alias list */
short p_proto; /* protocol # */
};
/*
* Constants and structures defined by the internet system,
* Per RFC 790, September 1981, taken from the BSD file netinet/in.h.
*/
/*
* Protocols
*/
#define IPPROTO_IP 0 /* dummy for IP */
#define IPPROTO_ICMP 1 /* control message protocol */
#define IPPROTO_GGP 2 /* gateway^2 (deprecated) */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_PUP 12 /* pup */
#define IPPROTO_UDP 17 /* user datagram protocol */
#define IPPROTO_IDP 22 /* xns idp */
#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
#define IPPROTO_RAW 255 /* raw IP packet */
#define IPPROTO_MAX 256
/*
* Port/socket numbers: network standard functions
*/
#define IPPORT_ECHO 7
#define IPPORT_DISCARD 9
#define IPPORT_SYSTAT 11
#define IPPORT_DAYTIME 13
#define IPPORT_NETSTAT 15
#define IPPORT_FTP 21
#define IPPORT_TELNET 23
#define IPPORT_SMTP 25
#define IPPORT_TIMESERVER 37
#define IPPORT_NAMESERVER 42
#define IPPORT_WHOIS 43
#define IPPORT_MTP 57
/*
* Port/socket numbers: host specific functions
*/
#define IPPORT_TFTP 69
#define IPPORT_RJE 77
#define IPPORT_FINGER 79
#define IPPORT_TTYLINK 87
#define IPPORT_SUPDUP 95
/*
* UNIX TCP sockets
*/
#define IPPORT_EXECSERVER 512
#define IPPORT_LOGINSERVER 513
#define IPPORT_CMDSERVER 514
#define IPPORT_EFSSERVER 520
/*
* UNIX UDP sockets
*/
#define IPPORT_BIFFUDP 512
#define IPPORT_WHOSERVER 513
#define IPPORT_ROUTESERVER 520
/* 520+1 also used */
/*
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root).
*/
#define IPPORT_RESERVED 1024
/*
* Link numbers
*/
#define IMPLINK_IP 155
#define IMPLINK_LOWEXPER 156
#define IMPLINK_HIGHEXPER 158
/*
* Internet address (old style... should be updated)
*/
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
/* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2
/* host on imp */
#define s_net S_un.S_un_b.s_b1
/* network */
#define s_imp S_un.S_un_w.s_w2
/* imp */
#define s_impno S_un.S_un_b.s_b4
/* imp # */
#define s_lh S_un.S_un_b.s_b3
/* logical host */
};
/*
* Definitions of bits in internet address integers.
* On subnets, the decomposition of addresses to host and net parts
* is done according to subnet mask, not the masks here.
*/
#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST 0x00ffffff
#define IN_CLASSA_MAX 128
#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST 0x0000ffff
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST 0x000000ff
#define INADDR_ANY (u_long)0x00000000
#define INADDR_LOOPBACK 0x7f000001
#define INADDR_BROADCAST (u_long)0xffffffff
#define INADDR_NONE 0xffffffff
/*
* Socket address, internet style.
*/
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
#define WSADESCRIPTION_LEN 256
#define WSASYS_STATUS_LEN 128
/*
* Options for use with [gs]etsockopt at the IP level.
*/
#define IP_OPTIONS 1 /* set/get IP per-packet options */
#define IP_MULTICAST_IF 2 /* set/get IP multicast interface */
#define IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */
#define IP_MULTICAST_LOOP 4 /* set/get IP multicast loopback */
#define IP_ADD_MEMBERSHIP 5 /* add an IP group membership */
#define IP_DROP_MEMBERSHIP 6 /* drop an IP group membership */
#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */
/*
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
*/
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
/*
* Definitions related to sockets: types, address families, options,
* taken from the BSD file sys/socket.h.
*/
/*
* This is used instead of -1, since the
* SOCKET type is unsigned.
*/
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
/*
* Types
*/
#define SOCK_STREAM 1 /* stream socket */
#define SOCK_DGRAM 2 /* datagram socket */
#define SOCK_RAW 3 /* raw-protocol interface */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequenced packet stream */
/*
* Option flags per-socket.
*/
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_DONTLINGER (u_int)(~SO_LINGER)
/*
* Additional options.
*/
#define SO_SNDBUF 0x1001 /* send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
/*
* Options for connect and disconnect data and options. Used only by
* non-TCP/IP transports such as DECNet, OSI TP4, etc.
*/
#define SO_CONNDATA 0x7000
#define SO_CONNOPT 0x7001
#define SO_DISCDATA 0x7002
#define SO_DISCOPT 0x7003
#define SO_CONNDATALEN 0x7004
#define SO_CONNOPTLEN 0x7005
#define SO_DISCDATALEN 0x7006
#define SO_DISCOPTLEN 0x7007
/*
* Option for opening sockets for synchronous access.
*/
#define SO_OPENTYPE 0x7008
#define SO_SYNCHRONOUS_ALERT 0x10
#define SO_SYNCHRONOUS_NONALERT 0x20
/*
* Other NT-specific options.
*/
#define SO_MAXDG 0x7009
#define SO_MAXPATHDG 0x700A
/*
* TCP options.
*/
#define TCP_NODELAY 0x0001
#define TCP_BSDURGENT 0x7000
/*
* Address families.
*/
#define AF_UNSPEC 0 /* unspecified */
#define AF_UNIX 1 /* local to host (pipes, portals) */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_IPX 6 /* IPX and SPX */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style addresses */
#define AF_VOICEVIEW 18 /* VoiceView */
#define AF_MAX 19
/*
* Structure used by kernel to store most
* addresses.
*/
struct sockaddr {
u_short sa_family; /* address family */
char sa_data[14]; /* up to 14 bytes of direct address */
};
/*
* Structure used by kernel to pass protocol
* information in raw sockets.
*/
struct sockproto {
u_short sp_family; /* address family */
u_short sp_protocol; /* protocol */
};
/*
* Protocol families, same as address families for now.
*/
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_IMPLINK AF_IMPLINK
#define PF_PUP AF_PUP
#define PF_CHAOS AF_CHAOS
#define PF_NS AF_NS
#define PF_IPX AF_IPX
#define PF_ISO AF_ISO
#define PF_OSI AF_OSI
#define PF_ECMA AF_ECMA
#define PF_DATAKIT AF_DATAKIT
#define PF_CCITT AF_CCITT
#define PF_SNA AF_SNA
#define PF_DECnet AF_DECnet
#define PF_DLI AF_DLI
#define PF_LAT AF_LAT
#define PF_HYLINK AF_HYLINK
#define PF_APPLETALK AF_APPLETALK
#define PF_VOICEVIEW AF_VOICEVIEW
#define PF_MAX AF_MAX
/*
* Structure used for manipulating linger option.
*/
struct linger {
u_short l_onoff; /* option on/off */
u_short l_linger; /* linger time */
};
/*
* Level number for (get/set)sockopt() to apply to socket itself.
*/
#define SOL_SOCKET 0xffff /* options for socket level */
/*
* Maximum queue length specifiable by listen.
*/
#define SOMAXCONN 5
#define MSG_OOB 0x1 /* process out-of-band data */
#define MSG_PEEK 0x2 /* peek at incoming message */
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
#define MSG_MAXIOVLEN 16
#define MSG_PARTIAL 0x8000 /* partial send or recv for message xport */
/*
* Define constant based on rfc883, used by gethostbyxxxx() calls.
*/
#define MAXGETHOSTSTRUCT 1024
/*
* Define flags to be used with the WSAAsyncSelect() call.
*/
#define FD_READ 0x01
#define FD_WRITE 0x02
#define FD_OOB 0x04
#define FD_ACCEPT 0x08
#define FD_CONNECT 0x10
#define FD_CLOSE 0x20
/*
* All Windows Sockets error constants are biased by WSABASEERR from
* the "normal"
*/
#define WSABASEERR 10000
/*
* Windows Sockets definitions of regular Microsoft C error constants
*/
#define WSAEINTR (WSABASEERR+4)
#define WSAEBADF (WSABASEERR+9)
#define WSAEACCES (WSABASEERR+13)
#define WSAEFAULT (WSABASEERR+14)
#define WSAEINVAL (WSABASEERR+22)
#define WSAEMFILE (WSABASEERR+24)
/*
* Windows Sockets definitions of regular Berkeley error constants
*/
#define WSAEWOULDBLOCK (WSABASEERR+35)
#define WSAEINPROGRESS (WSABASEERR+36)
#define WSAEALREADY (WSABASEERR+37)
#define WSAENOTSOCK (WSABASEERR+38)
#define WSAEDESTADDRREQ (WSABASEERR+39)
#define WSAEMSGSIZE (WSABASEERR+40)
#define WSAEPROTOTYPE (WSABASEERR+41)
#define WSAENOPROTOOPT (WSABASEERR+42)
#define WSAEPROTONOSUPPORT (WSABASEERR+43)
#define WSAESOCKTNOSUPPORT (WSABASEERR+44)
#define WSAEOPNOTSUPP (WSABASEERR+45)
#define WSAEPFNOSUPPORT (WSABASEERR+46)
#define WSAEAFNOSUPPORT (WSABASEERR+47)
#define WSAEADDRINUSE (WSABASEERR+48)
#define WSAEADDRNOTAVAIL (WSABASEERR+49)
#define WSAENETDOWN (WSABASEERR+50)
#define WSAENETUNREACH (WSABASEERR+51)
#define WSAENETRESET (WSABASEERR+52)
#define WSAECONNABORTED (WSABASEERR+53)
#define WSAECONNRESET (WSABASEERR+54)
#define WSAENOBUFS (WSABASEERR+55)
#define WSAEISCONN (WSABASEERR+56)
#define WSAENOTCONN (WSABASEERR+57)
#define WSAESHUTDOWN (WSABASEERR+58)
#define WSAETOOMANYREFS (WSABASEERR+59)
#define WSAETIMEDOUT (WSABASEERR+60)
#define WSAECONNREFUSED (WSABASEERR+61)
#define WSAELOOP (WSABASEERR+62)
#define WSAENAMETOOLONG (WSABASEERR+63)
#define WSAEHOSTDOWN (WSABASEERR+64)
#define WSAEHOSTUNREACH (WSABASEERR+65)
#define WSAENOTEMPTY (WSABASEERR+66)
#define WSAEPROCLIM (WSABASEERR+67)
#define WSAEUSERS (WSABASEERR+68)
#define WSAEDQUOT (WSABASEERR+69)
#define WSAESTALE (WSABASEERR+70)
#define WSAEREMOTE (WSABASEERR+71)
#define WSAEDISCON (WSABASEERR+101)
/*
* Extended Windows Sockets error constant definitions
*/
#define WSASYSNOTREADY (WSABASEERR+91)
#define WSAVERNOTSUPPORTED (WSABASEERR+92)
#define WSANOTINITIALISED (WSABASEERR+93)
/*
* Error return codes from gethostbyname() and gethostbyaddr()
* (when using the resolver). Note that these errors are
* retrieved via WSAGetLastError() and must therefore follow
* the rules for avoiding clashes with error numbers from
* specific implementations or language run-time systems.
* For this reason the codes are based at WSABASEERR+1001.
* Note also that [WSA]NO_ADDRESS is defined only for
* compatibility purposes.
*/
#define h_errno WSAGetLastError()
/* Authoritative Answer: Host not found */
#define WSAHOST_NOT_FOUND (WSABASEERR+1001)
#define HOST_NOT_FOUND WSAHOST_NOT_FOUND
/* Non-Authoritative: Host not found, or SERVERFAIL */
#define WSATRY_AGAIN (WSABASEERR+1002)
#define TRY_AGAIN WSATRY_AGAIN
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
#define WSANO_RECOVERY (WSABASEERR+1003)
#define NO_RECOVERY WSANO_RECOVERY
/* Valid name, no data record of requested type */
#define WSANO_DATA (WSABASEERR+1004)
#define NO_DATA WSANO_DATA
/* no address, look for MX record */
#define WSANO_ADDRESS WSANO_DATA
#define NO_ADDRESS WSANO_ADDRESS
/*
* Windows Sockets errors redefined as regular Berkeley error constants.
* These are commented out in Windows NT to avoid conflicts with errno.h.
* Use the WSA constants instead.
*/
#if 0
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define ENOTSOCK WSAENOTSOCK
#define EDESTADDRREQ WSAEDESTADDRREQ
#define EMSGSIZE WSAEMSGSIZE
#define EPROTOTYPE WSAEPROTOTYPE
#define ENOPROTOOPT WSAENOPROTOOPT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENETDOWN WSAENETDOWN
#define ENETUNREACH WSAENETUNREACH
#define ENETRESET WSAENETRESET
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOBUFS WSAENOBUFS
#define EISCONN WSAEISCONN
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
#define ENAMETOOLONG WSAENAMETOOLONG
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#define ENOTEMPTY WSAENOTEMPTY
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
#endif
/* Socket function prototypes */
#ifdef __cplusplus
extern "C" {
#endif
SOCKET PASCAL FAR accept (SOCKET s, struct sockaddr FAR *addr,
int FAR *addrlen);
int PASCAL FAR bind (SOCKET s, const struct sockaddr FAR *addr, int namelen);
int PASCAL FAR closesocket (SOCKET s);
int PASCAL FAR connect (SOCKET s, const struct sockaddr FAR *name, int namelen);
int PASCAL FAR ioctlsocket (SOCKET s, long cmd, u_long FAR *argp);
int PASCAL FAR getpeername (SOCKET s, struct sockaddr FAR *name,
int FAR * namelen);
int PASCAL FAR getsockname (SOCKET s, struct sockaddr FAR *name,
int FAR * namelen);
int PASCAL FAR getsockopt (SOCKET s, int level, int optname,
char FAR * optval, int FAR *optlen);
u_long PASCAL FAR htonl (u_long hostlong);
u_short PASCAL FAR htons (u_short hostshort);
unsigned long PASCAL FAR inet_addr (const char FAR * cp);
char FAR * PASCAL FAR inet_ntoa (struct in_addr in);
int PASCAL FAR listen (SOCKET s, int backlog);
u_long PASCAL FAR ntohl (u_long netlong);
u_short PASCAL FAR ntohs (u_short netshort);
int PASCAL FAR recv (SOCKET s, char FAR * buf, int len, int flags);
int PASCAL FAR recvfrom (SOCKET s, char FAR * buf, int len, int flags,
struct sockaddr FAR *from, int FAR * fromlen);
#if 0
int PASCAL FAR select (int nfds, fd_set FAR *readfds, fd_set FAR *writefds,
fd_set FAR *exceptfds, const struct timeval FAR *timeout);
#endif
int PASCAL FAR send (SOCKET s, const char FAR * buf, int len, int flags);
int PASCAL FAR sendto (SOCKET s, const char FAR * buf, int len, int flags,
const struct sockaddr FAR *to, int tolen);
int PASCAL FAR setsockopt (SOCKET s, int level, int optname,
const char FAR * optval, int optlen);
int PASCAL FAR shutdown (SOCKET s, int how);
SOCKET PASCAL FAR socket (int af, int type, int protocol);
/* Database function prototypes */
struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * addr,
int len, int type);
struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name);
int PASCAL FAR gethostname (char FAR * name, int namelen);
struct servent FAR * PASCAL FAR getservbyport(int port, const char FAR * proto);
struct servent FAR * PASCAL FAR getservbyname(const char FAR * name,
const char FAR * proto);
struct protoent FAR * PASCAL FAR getprotobynumber(int proto);
struct protoent FAR * PASCAL FAR getprotobyname(const char FAR * name);
#ifdef __cplusplus
}
#endif
/* Microsoft Windows Extended data types */
typedef struct sockaddr SOCKADDR;
typedef struct sockaddr *PSOCKADDR;
typedef struct sockaddr FAR *LPSOCKADDR;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr_in *PSOCKADDR_IN;
typedef struct sockaddr_in FAR *LPSOCKADDR_IN;
typedef struct linger LINGER;
typedef struct linger *PLINGER;
typedef struct linger FAR *LPLINGER;
typedef struct in_addr IN_ADDR;
typedef struct in_addr *PIN_ADDR;
typedef struct in_addr FAR *LPIN_ADDR;
typedef struct fd_set FD_SET;
typedef struct fd_set *PFD_SET;
typedef struct fd_set FAR *LPFD_SET;
typedef struct hostent HOSTENT;
typedef struct hostent *PHOSTENT;
typedef struct hostent FAR *LPHOSTENT;
typedef struct servent SERVENT;
typedef struct servent *PSERVENT;
typedef struct servent FAR *LPSERVENT;
typedef struct protoent PROTOENT;
typedef struct protoent *PPROTOENT;
typedef struct protoent FAR *LPPROTOENT;
typedef struct timeval TIMEVAL;
typedef struct timeval *PTIMEVAL;
typedef struct timeval FAR *LPTIMEVAL;
#endif /* _WINSOCKAPI_ */

View file

@ -1,222 +0,0 @@
/*
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.
*/
#include <dpmi.h>
//#include "types.h"
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
//#include "mgenord.h"
#define MGENVXD_REGISTER_ORD 1
#define MGENVXD_GETMEM_ORD 2
#define MGENVXD_DEREGISTER_ORD 3
#define MGENVXD_WAKEUP_ORD 4
#define MGENVXD_MAKEDQS_ORD 5
// Virtual 8086 API Ordinals
#define V86API_GETSELECTOR16_ORD (1)
#define V86API_GETSELECTOR32_ORD (2)
#define V86API_GETFLAT32_ORD (3)
#define V86API_MOVERP_ORD (6)
#define V86API_MOVEPR_ORD (7)
#define V86API_POST_ORD (8)
#define V86API_INIT_ORD (9)
#define V86API_UNINIT_ORD (10)
#define V86API_INSERTKEY_ORD (11)
#define V86API_REMOVEHOTKEY_ORD (12)
#define V86API_INSTALLHOTKEY_ORD (13)
#define V86API_HOOKINT48_ORD (14)
#define V86API_WAKEUPDLL_ORD (15)
#define DPMIAPI_GETFLAT32_ORD (1)
#define DPMIAPI_POST_WINDOWS_ORD (2)
// these are DPMI functions. Make sure they don't clash with the
// other MGENVXD_XXXX functions above, or the DPMI functions!
#define MGENVXD_GETQUEUECTR_ORD 6
#define MGENVXD_MOVENODE_ORD 7
#define MGENVXD_GETNODE_ORD 8
#define MGENVXD_FLUSHNODE_ORD 9
#define MGENVXD_MCOUNT_ORD 10
#define MGENVXD_MASTERNODE_ORD 11
#define MGENVXD_SANITYCHECK_ORD 12
#define MGENVXD_WAKEUPDLL_ORD 13
#define MGENVXD_WAIT_ORD 14
//
#define HWND_OFFSET (0)
#define UMSG_OFFSET (1)
#define SIZEREQUEST_OFFSET (2)
#define HVXD_OFFSET (3)
#define DATUM_OFFSET (4)
#define SLOT_OFFSET (5)
#define SIZEGIVEN_OFFSET (6)
#define SELECTOR32_OFFSET (7)
#define SELECTOR16_OFFSET (8)
//#include "magic.h"
#define MGENVXD_DEVICE_ID 0x18AA
//#include "rtq.h"
#define RTQ_NODE struct rtq_node
RTQ_NODE
{
RTQ_NODE *self; // Ring zero address of this node
RTQ_NODE *left; // Ring zero address of preceding node
RTQ_NODE *right; // Ring zero address of succeding node
BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface)
BYTE * rtqInsert; // Ring 3 insertion position
WORD rtqLen; // Length of buffer, excluding preface
WORD rtqUpCtr; // Up Counter of bytes used so far
WORD rtqQCtr; // number of nodes attached
WORD padding; // DWORD alignment
};
#define RTQ_PARAM_MOVENODE struct rtq_param_movenode
RTQ_PARAM_MOVENODE
{
WORD rtqFromDQ;
WORD rtqToDQ;
};
RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From
int _int86(int vector, __dpmi_regs *iregs, __dpmi_regs *oregs);
#define CHUNNEL_INT 0x48
#define int386 _int86
#define REGISTERS __dpmi_regs
void
Yield(void)
{
__dpmi_yield();
}
void
PostWindowsMessage(void)
{
REGISTERS regs;
regs.d.eax = DPMIAPI_POST_WINDOWS_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = 0;
regs.d.ecx = 0;
int386(CHUNNEL_INT, &regs, &regs);
}
int
MGenWait(void)
{
REGISTERS regs;
regs.d.eax = MGENVXD_WAIT_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
return regs.d.eax;
}
int MGenGetQueueCtr(int qNo)
{
REGISTERS regs;
regs.d.eax = MGENVXD_GETQUEUECTR_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = qNo;
int386(CHUNNEL_INT, &regs, &regs);
return regs.d.eax;
}
RTQ_NODE *MGenMoveTo(int qFrom, int qTo)
{
REGISTERS regs;
regs.d.eax = MGENVXD_MOVENODE_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = qFrom;
regs.d.ecx = qTo;
int386(CHUNNEL_INT, &regs, &regs);
return (RTQ_NODE *) regs.d.eax;
}
RTQ_NODE *MGenGetNode(int q)
{
REGISTERS regs;
regs.d.eax = MGENVXD_GETNODE_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = q;
int386(CHUNNEL_INT, &regs, &regs);
return (RTQ_NODE *) regs.d.eax;
}
RTQ_NODE *MGenGetMasterNode(unsigned *size)
{
REGISTERS regs;
regs.d.eax = MGENVXD_MASTERNODE_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
*size = regs.d.ecx;
return (RTQ_NODE *) regs.d.eax;
}
RTQ_NODE *MGenFlushNodes(int qFrom, int qTo)
{
REGISTERS regs;
regs.d.eax = MGENVXD_FLUSHNODE_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = qFrom;
regs.d.ecx = qTo;
int386(CHUNNEL_INT, &regs, &regs);
return (RTQ_NODE *) regs.d.eax;
}
int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits)
{
REGISTERS regs;
regs.d.eax = MGENVXD_MCOUNT_ORD << 16 | MGENVXD_DEVICE_ID;
regs.d.ebx = lowerOrderBits;
regs.d.ecx = upperOrderBits;
int386(CHUNNEL_INT, &regs, &regs);
return regs.d.eax;
}
int MGenSanityCheck(void)
{
REGISTERS regs;
regs.d.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
return regs.d.eax;
}
void MGenWakeupDll(void)
{
REGISTERS regs;
regs.d.eax = MGENVXD_WAKEUPDLL_ORD << 16 | MGENVXD_DEVICE_ID;
int386(CHUNNEL_INT, &regs, &regs);
}

File diff suppressed because it is too large Load diff

View file

@ -1,763 +0,0 @@
/*
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.
*/
// net_bw.c
#include <stdio.h>
#include <stdlib.h>
#include <dpmi.h>
#include "quakedef.h"
#include "dosisms.h"
// this section is general Unix stuff that we need
#define EIO 5 /* I/O error */
#define EBADS 9
#define EWOULDBLOCK 35 /* function would block */
#define EMSGSIZE 40 /* message to big for buffers */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
#define EPFNOSUPPORT 46 /* Protocol family not supported */
#define EAFNOSUPPORT 47 /* Address family not supported */
#define ECONNABORTED 53 /* User requested hangup */
#define ENOBUFS 55 /* No buffers available */
#define EISCONN 56 /* Socket has closed */
#define ENOTCONN 57 /* Socket is not connected */
#define ESHUTDOWN 58 /* Socket is closed */
#define ETOOMANYREFS 59 /* Too many sockets open */
#define ETIMEDOUT 60 /* Connection timed out */
#define ECONNREFUSED 61 /* Connection refused */
#define AF_INET 2 /* internet */
#define PF_INET AF_INET
#define SOCK_STREAM 1 /* stream */
#define SOCK_DGRAM 2 /* datagram */
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define INADDR_ANY 0
#define SIOCDONE 0x7300
#define FIONREAD 0x667f
#define FIONBIO 0x667e
#define FIONWIN 0x1000
#define FIONTIN 0x2000
#define BRDINIT 0
#define BRDADDR 10
#define MAXHOSTNAMELEN 256
#define SOL_SOCKET 0xffff /* options for socket level */
/*
* Option flags per-socket.
*/
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_USEPRIV 0x4000 /* allocate from privileged port area */
#define SO_CANTSIG 0x8000 /* prevent SIGPIPE on SS_CANTSENDMORE */
/*
* Additional options, not kept in so_options.
*/
#define SO_SNDBUF 0x1001 /* send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
struct in_addr
{
union
{
struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { unsigned short s_w1,s_w2; } S_un_w;
unsigned long S_addr;
} S_un;
};
#define s_addr S_un.S_addr /* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2 /* host on imp */
#define s_net S_un.S_un_b.s_b1 /* network */
#define s_imp S_un.S_un_w.s_w2 /* imp */
#define s_impno S_un.S_un_b.s_b4 /* imp # */
#define s_lh S_un.S_un_b.s_b3 /* logical host */
struct sockaddr_in
{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
#define h_addr h_addr_list[0] /* address, for backward compatiblity */
};
char *inet_ntoa(struct in_addr in);
// this section is B&W specific constants & structures
#define BW_IOCTL_BIND 0
#define BW_IOCTL_CLEAROPTIONS 5
#define BW_IOCTL_SETOPTIONS 6
#define BW_IOCTL_PEEK 7
#define BW_IOCTL_SETWINMASK 8
#define BW_OPTION_BLOCKING 0x01
#define BW_OPTION_REUSEBUFFERS 0x80
#define BW_ERR_USR_HANGUP 50
#define BW_ERR_HANGUP 51
#define BW_ERR_NET_ERR 52
#define BW_ERR_IS_CLOSED 53
#define BW_ERR_TIME_OUT 54
#define BW_ERR_RESET 55
#define BW_ERR_FULL 56
#define BW_ERR_BLOCK 57
#define BW_ERR_SHUTDOWN 58
#pragma pack(1)
typedef struct
{
char state; // always 1
short localPort;
struct in_addr localAddr;
char reason; // always 0
char options;
short dataAvailable;
} BW_UDPinfo_t;
typedef struct
{
char reserved1 [6];
unsigned short info2Offset;
char reserved2 [18];
struct in_addr remoteAddr;
} BW_UDPreadInfo1_t;
typedef struct
{
short remotePort;
char reserved1 [2];
unsigned short dataLenPlus8;
char reserved2 [2];
char data[1]; // actual size is <dataLenPlus8> - 8
} BW_UDPreadInfo2_t;
typedef struct
{
char reserved1 [2];
short remotePort;
unsigned short dataLen;
struct in_addr remoteAddr;
char reserved2 [42];
char data[1]; // actual size is <datalen>
} BW_writeInfo_t;
typedef struct
{
short ioport;
byte dma;
byte vector;
byte irq;
short bufferSize;
short maxWindow;
short timeZone;
byte myType;
int inetAddr;
short value;
byte subnetMask;
short etherPointer;
short logserverPointer;
short nameserverPointer;
short printserverPointer;
short timeserverPointer;
short gatewayPointer;
short driverSegment;
byte transferSize;
char cardName [9];
} BW_ethdevinfo_t;
#pragma pack()
#define LOWMEM_SIZE 4096
static unsigned char *lowmem_buffer;
static int lowmem_bufseg;
static int lowmem_bufoff;
static BW_ethdevinfo_t ethdevinfo;
static int netmask;
static struct in_addr bcastaddr;
extern regs_t regs;
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket = 0;
#include "net_bw.h"
//=============================================================================
static int BW_ioctl(int s, char *msg, int msglen)
{
Q_memcpy(lowmem_buffer, msg, msglen);
regs.x.ax = 0x4403;
regs.x.bx = s;
regs.x.cx = msglen;
regs.x.dx = lowmem_bufoff;
regs.x.ds = lowmem_bufseg;
if (dos_int86(0x21))
return regs.x.ax;
return 0;
}
//=============================================================================
static int BW_TranslateError(int error)
{
switch(error)
{
case BW_ERR_USR_HANGUP: return ECONNABORTED;
case BW_ERR_HANGUP: return EISCONN;
case BW_ERR_NET_ERR: return ENOTCONN;
case BW_ERR_IS_CLOSED: return ENOTCONN;
case BW_ERR_TIME_OUT: return ETIMEDOUT;
case BW_ERR_RESET: return ECONNREFUSED;
case BW_ERR_FULL: return ETOOMANYREFS;
case BW_ERR_BLOCK: return EWOULDBLOCK;
case BW_ERR_SHUTDOWN: return ESHUTDOWN;
}
return EIO;
}
//=============================================================================
static int GetEthdevinfo(void)
{
int fd;
Q_strcpy((char *)lowmem_buffer, "ETHDEV27");
regs.x.ax = 0x3d42;
regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
return -1;
fd = regs.x.ax;
regs.x.ax = 0x4401;
regs.x.bx = fd;
regs.x.dx = 0x60;
dos_int86(0x21);
regs.h.ah = 0x3f;
regs.x.cx = sizeof(ethdevinfo);
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
regs.x.bx = fd;
if (dos_int86(0x21))
return -1;
Q_memcpy(&ethdevinfo, lowmem_buffer, regs.x.ax);
regs.h.ah = 0x3e;
regs.x.bx = fd;
dos_int86(0x21);
return 0;
}
//=============================================================================
int BW_Init(void)
{
struct qsockaddr addr;
char *colon;
if (COM_CheckParm ("-noudp"))
return -1;
lowmem_buffer = dos_getmemory(LOWMEM_SIZE);
if (!lowmem_buffer)
Sys_Error("not enough low memory\n");
lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
if (GetEthdevinfo())
{
Con_DPrintf("Beame & Whiteside TCP/IP not detected\n");
dos_freememory(lowmem_buffer);
return -1;
}
netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask);
bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask);
if ((net_controlsocket = BW_OpenSocket (0)) == -1)
{
dos_freememory(lowmem_buffer);
Con_DPrintf ("BW_Init unable to open control socket; disabled\n");
return -1;
}
BW_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, BW_AddrToString (&addr));
colon = Q_strrchr (my_tcpip_address, ':');
if (colon)
*colon = 0;
Con_Printf("BW_Init: UDP initialized\n");
tcpipAvailable = true;
return net_controlsocket;
}
//=============================================================================
void BW_Shutdown(void)
{
BW_Listen (false);
BW_CloseSocket (net_controlsocket);
dos_freememory(lowmem_buffer);
}
//=============================================================================
void BW_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1)
Sys_Error ("BW_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
BW_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
/*
OpenSocket returns a handle to a network socket that has been opened,
set to nonblocking, and bound to <port>. Additional socket options
should be set here if they are needed. -1 is returned on failure.
*/
int BW_OpenSocket(int port)
{
int s;
int ret;
int deadman = 3 * 1024;
static int dynamic = 1024;
static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS};
static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0};
static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING};
// allocate a UDP socket
Q_strcpy((char *)lowmem_buffer, "UDP-IP10");
regs.x.ax = 0x3d42;
regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
{
Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
s = regs.x.ax;
// set file descriptor to raw mode
regs.x.ax = 0x4401;
regs.x.bx = s;
regs.x.dx = 0x60;
dos_int86(0x21);
if (BW_ioctl(s, reuse_msg, 2))
{
Con_Printf("BW_OpenSocket ioctl(reuse) failed\n");
return -1;
}
if (BW_ioctl(s, nonblock_msg, 2))
{
Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n");
return -1;
}
// if a socket was specified, bind to it and return
if (port)
{
*(short *)&bind_msg[1] = port;
if (BW_ioctl(s, bind_msg, 3))
{
BW_CloseSocket(s);
return -1;
}
return s;
}
// B&W does NOT do dynamic allocation, so if port == 0 we must fake it
do
{
port = dynamic++;
if (dynamic == 4096)
dynamic = 1024;
deadman--;
*(short *)&bind_msg[1] = port;
ret = BW_ioctl(s, bind_msg, 3);
}
while (ret && deadman);
if (ret)
return -1;
return s;
}
//=============================================================================
int BW_CloseSocket(int socket)
{
regs.h.ah = 0x3e;
regs.x.bx = socket;
if(dos_int86(0x21))
{
Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax));
return -1;
}
return 0;
}
//=============================================================================
int BW_Connect (int socket, struct qsockaddr *hostaddr)
{
return 0;
}
//=============================================================================
int BW_CheckNewConnections(void)
{
if (net_acceptsocket == 0)
return -1;
// see if there's anything waiting
regs.x.ax = 0x4406;
regs.x.bx = net_acceptsocket;
dos_int86(0x21);
if (regs.x.ax == 0)
return -1;
return net_acceptsocket;
}
//=============================================================================
int BW_Read(int s, byte *buf, int len, struct qsockaddr *from)
{
BW_UDPreadInfo1_t *info1;
BW_UDPreadInfo2_t *info2;
// ask if there's anything waiting
regs.x.ax = 0x4406;
regs.x.bx = s;
dos_int86(0x21);
if (regs.x.ax == 0)
return 0;
// there was, so let's get it
regs.h.ah = 0x3f;
regs.x.cx = /* len + 53 */ LOWMEM_SIZE;
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
regs.x.bx = s;
if (dos_int86(0x21))
{
Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
info1 = (BW_UDPreadInfo1_t *)lowmem_buffer;
info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset);
if (from)
{
from->sa_family = AF_INET;
((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr;
((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort);
}
len = info2->dataLenPlus8 - 8;
if (len > NET_DATAGRAMSIZE)
{
Con_Printf("BW UDP read packet too large: %u\n", len);
return -1;
}
Q_memcpy(buf, info2->data, len);
return len;
}
//=============================================================================
int BW_Broadcast(int s, byte *msg, int len)
{
BW_writeInfo_t *writeInfo;
// ask if we're clear to send
regs.x.ax = 0x4407;
regs.x.bx = s;
dos_int86(0x21);
if (regs.x.ax == 0)
return 0;
// yes, let's do it
writeInfo = (BW_writeInfo_t *)lowmem_buffer;
writeInfo->remoteAddr = bcastaddr;
writeInfo->remotePort = net_hostport;
writeInfo->dataLen = len;
if (len > NET_DATAGRAMSIZE)
Sys_Error("BW UDP write packet too large: %u\n", len);
Q_memcpy(writeInfo->data, msg, len);
writeInfo->data[len] = 0;
regs.h.ah = 0x40;
regs.x.bx = s;
regs.x.cx = len + sizeof(BW_writeInfo_t);
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
{
Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
return len;
}
//=============================================================================
int BW_Write(int s, byte *msg, int len, struct qsockaddr *to)
{
BW_writeInfo_t *writeInfo;
// ask if we're clear to send
regs.x.ax = 0x4407;
regs.x.bx = s;
dos_int86(0x21);
if (regs.x.ax == 0)
return 0;
// yes, let's do it
writeInfo = (BW_writeInfo_t *)lowmem_buffer;
writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr;
writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port);
writeInfo->dataLen = len;
if (len > NET_DATAGRAMSIZE)
Sys_Error("BW UDP write packet too large: %u\n", len);
Q_memcpy(writeInfo->data, msg, len);
writeInfo->data[len] = 0;
regs.h.ah = 0x40;
regs.x.bx = s;
regs.x.cx = len + sizeof(BW_writeInfo_t);
regs.x.es = regs.x.ds = lowmem_bufseg;
regs.x.dx = lowmem_bufoff;
if (dos_int86(0x21))
{
Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax));
return -1;
}
return len;
}
//=============================================================================
char *BW_AddrToString (struct qsockaddr *addr)
{
static char buffer[22];
sprintf(buffer, "%d.%d.%d.%d:%d",
((struct sockaddr_in *)addr)->sin_addr.s_net,
((struct sockaddr_in *)addr)->sin_addr.s_host,
((struct sockaddr_in *)addr)->sin_addr.s_lh,
((struct sockaddr_in *)addr)->sin_addr.s_impno,
ntohs(((struct sockaddr_in *)addr)->sin_port)
);
return buffer;
}
//=============================================================================
int BW_StringToAddr (char *string, struct qsockaddr *addr)
{
int ha1, ha2, ha3, ha4, hp;
int ipaddr;
sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
((struct sockaddr_in *)addr)->sin_port = htons((short)hp);
return 0;
}
//=============================================================================
int BW_GetSocketAddr (int socket, struct qsockaddr *addr)
{
regs.x.ax = 0x4402;
regs.x.bx = socket;
regs.x.cx = sizeof(BW_UDPinfo_t);
regs.x.dx = lowmem_bufoff;
regs.x.ds = lowmem_bufseg;
dos_int86(0x21);
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr;
((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort);
return 0;
}
//=============================================================================
int BW_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
Q_strcpy(name, BW_AddrToString(addr));
return 0;
}
///=============================================================================
int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr)
{
char buff[MAXHOSTNAMELEN];
char *b;
int addr;
int num;
int mask;
int run;
int port;
if (name[0] < '0' || name[0] > '9')
return -1;
buff[0] = '.';
b = buff;
Q_strcpy(buff+1, name);
if (buff[1] == '.')
b++;
addr = 0;
mask = -1;
while (*b == '.')
{
b++;
num = 0;
run = 0;
while (!( *b < '0' || *b > '9'))
{
num = num*10 + *b++ - '0';
if (++run > 3)
return -1;
}
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
return -1;
if (num < 0 || num > 255)
return -1;
mask<<=8;
addr = (addr<<8) + num;
}
addr = htonl(addr);
mask = htonl(mask);
if (*b++ == ':')
port = Q_atoi(b);
else
port = net_hostport;
hostaddr->sa_family = AF_INET;
((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
((struct sockaddr_in *)hostaddr)->sin_addr.s_addr =
((ethdevinfo.inetAddr & mask) | addr);
return 0;
}
//=============================================================================
int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
return -1;
if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
return 1;
return 0;
}
//=============================================================================
int BW_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
int BW_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
//=============================================================================

View file

@ -1,39 +0,0 @@
/*
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.
*/
// net_bw.h
int BW_Init (void);
void BW_Shutdown (void);
void BW_Listen (qboolean state);
int BW_OpenSocket (int port);
int BW_CloseSocket (int socket);
int BW_Connect (int socket, struct qsockaddr *addr);
int BW_CheckNewConnections (void);
int BW_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int BW_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int BW_Broadcast (int socket, byte *buf, int len);
char *BW_AddrToString (struct qsockaddr *addr);
int BW_StringToAddr (char *string, struct qsockaddr *addr);
int BW_GetSocketAddr (int socket, struct qsockaddr *addr);
int BW_GetNameFromAddr (struct qsockaddr *addr, char *name);
int BW_GetAddrFromName (char *name, struct qsockaddr *addr);
int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int BW_GetSocketPort (struct qsockaddr *addr);
int BW_SetSocketPort (struct qsockaddr *addr, int port);

File diff suppressed because it is too large Load diff

View file

@ -1,162 +0,0 @@
/*
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.
*/
#include "quakedef.h"
#include "net_loop.h"
#include "net_dgrm.h"
#include "net_ser.h"
net_driver_t net_drivers[MAX_NET_DRIVERS] =
{
{
"Loopback",
false,
Loop_Init,
Loop_Listen,
Loop_SearchForHosts,
Loop_Connect,
Loop_CheckNewConnections,
Loop_GetMessage,
Loop_SendMessage,
Loop_SendUnreliableMessage,
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
Loop_Shutdown
}
,
{
"Datagram",
false,
Datagram_Init,
Datagram_Listen,
Datagram_SearchForHosts,
Datagram_Connect,
Datagram_CheckNewConnections,
Datagram_GetMessage,
Datagram_SendMessage,
Datagram_SendUnreliableMessage,
Datagram_CanSendMessage,
Datagram_CanSendUnreliableMessage,
Datagram_Close,
Datagram_Shutdown
}
,
{
"Serial",
false,
Serial_Init,
Serial_Listen,
Serial_SearchForHosts,
Serial_Connect,
Serial_CheckNewConnections,
Serial_GetMessage,
Serial_SendMessage,
Serial_SendUnreliableMessage,
Serial_CanSendMessage,
Serial_CanSendUnreliableMessage,
Serial_Close,
Serial_Shutdown
}
};
int net_numdrivers = 3;
#include "net_bw.h"
#include "net_ipx.h"
#include "net_mp.h"
net_landriver_t net_landrivers[MAX_NET_DRIVERS] =
{
{
"Beame & Whiteside TCP/IP",
false,
0,
BW_Init,
BW_Shutdown,
BW_Listen,
BW_OpenSocket,
BW_CloseSocket,
BW_Connect,
BW_CheckNewConnections,
BW_Read,
BW_Write,
BW_Broadcast,
BW_AddrToString,
BW_StringToAddr,
BW_GetSocketAddr,
BW_GetNameFromAddr,
BW_GetAddrFromName,
BW_AddrCompare,
BW_GetSocketPort,
BW_SetSocketPort
}
,
{
"IPX",
false,
0,
IPX_Init,
IPX_Shutdown,
IPX_Listen,
IPX_OpenSocket,
IPX_CloseSocket,
IPX_Connect,
IPX_CheckNewConnections,
IPX_Read,
IPX_Write,
IPX_Broadcast,
IPX_AddrToString,
IPX_StringToAddr,
IPX_GetSocketAddr,
IPX_GetNameFromAddr,
IPX_GetAddrFromName,
IPX_AddrCompare,
IPX_GetSocketPort,
IPX_SetSocketPort
}
,
{
"Win95 TCP/IP",
false,
0,
MPATH_Init,
MPATH_Shutdown,
MPATH_Listen,
MPATH_OpenSocket,
MPATH_CloseSocket,
MPATH_Connect,
MPATH_CheckNewConnections,
MPATH_Read,
MPATH_Write,
MPATH_Broadcast,
MPATH_AddrToString,
MPATH_StringToAddr,
MPATH_GetSocketAddr,
MPATH_GetNameFromAddr,
MPATH_GetAddrFromName,
MPATH_AddrCompare,
MPATH_GetSocketPort,
MPATH_SetSocketPort
}
};
int net_numlandrivers = 3;

View file

@ -1,706 +0,0 @@
/*
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.
*/
// net_ipx.c
#include <stdio.h>
#include <stdlib.h>
#include <dpmi.h>
#include "quakedef.h"
#include "dosisms.h"
#include "net_ipx.h"
#define EIO 5 /* I/O error */
#define AF_NETWARE 64
#define IPX_OPEN 0
#define IPX_CLOSE 1
#define IPX_GETROUTE 2
#define IPX_SEND 3
#define IPX_LISTEN 4
#define IPX_SCHEDULEEVENT 5
#define IPX_CANCEL 6
#define IPX_SCHEDULESPECIALEVENT 7
#define IPX_GETINTERVALMARKER 8
#define IPX_GETADDRESS 9
#define IPX_RELINQUISH 10
#define PTYPE_UNKNOWN 0
#define PTYPE_RIP 1
#define PTYPE_ECHO 2
#define PTYPE_ERROR 3
#define PTYPE_IPX 4
#define PTYPE_SPX 5
#pragma pack(1)
typedef struct
{
byte network[4];
byte node[6];
short socket;
} IPXaddr;
struct sockaddr_ipx
{
short sipx_family;
IPXaddr sipx_addr;
char sipx_zero[2];
};
#define sipx_port sipx_addr.socket
typedef struct
{
short checkSum;
short length;
byte transportControl;
byte type;
IPXaddr destination;
IPXaddr source;
} IPXheader;
typedef struct ECBStructure
{
struct ECBStructure *link;
unsigned short ESR_off;
unsigned short ESR_seg;
byte inUse;
byte completionCode;
short socket;
byte IPXWorkspace[4];
byte driverWorkspace[12];
byte immediateAddress[6];
short fragCount;
short fragOff;
short fragSeg;
short fragSize;
} ECB;
#pragma pack()
typedef struct
{
ECB ecb;
IPXheader header;
int sequence;
char data[NET_DATAGRAMSIZE];
} ipx_lowmem_buffer_t;
#define LOWMEMSIZE (100 * 1024)
#define LOWMEMSAVE 256
#define IPXBUFFERS ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t))
#define IPXSOCKBUFFERS 5
#define IPXSOCKETS (IPXBUFFERS / IPXSOCKBUFFERS)
// each socket's socketbuffer 0 is used for sending, the others for listening
typedef struct
{
char reserved[LOWMEMSAVE];
ipx_lowmem_buffer_t socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS];
} ipx_lowmem_area_t;
static int ipxsocket[IPXSOCKETS];
static ECB *readlist[IPXSOCKETS];
static int sequence[IPXSOCKETS];
static int handlesInUse;
static ipx_lowmem_area_t *lma;
static char *lowmem_buffer;
static int lowmem_bufseg;
static int lowmem_bufoff;
static unsigned short ipx_cs;
static unsigned short ipx_ip;
static int net_acceptsocket = -1;
static int net_controlsocket;
static void IPX_PollProcedure(void);
static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure};
//=============================================================================
static void IPX_GetLocalAddress(IPXaddr *addr)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_GETADDRESS;
regs.x.es = lowmem_bufseg;
regs.x.si = lowmem_bufoff;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
Q_memcpy(addr, lowmem_buffer, 10);
}
//=============================================================================
static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_GETROUTE;
regs.x.es = lowmem_bufseg;
regs.x.si = lowmem_bufoff;
regs.x.di = lowmem_bufoff + sizeof(IPXaddr);
Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr));
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
if (regs.h.al)
return -1;
Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6);
return 0;
}
//=============================================================================
static void IPX_ListenForPacket(ECB *ecb)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_LISTEN;
regs.x.es = ptr2real(ecb) >> 4;
regs.x.si = ptr2real(ecb) & 0xf;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
}
//=============================================================================
static void IPX_RelinquishControl(void)
{
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_RELINQUISH;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
}
void IPX_PollProcedure(void)
{
IPX_RelinquishControl();
SchedulePollProcedure(&pollProcedure, 0.01);
}
//=============================================================================
static void ProcessReadyList(int s)
{
int n;
ECB *ecb;
ECB *prev;
for (n = 1; n < IPXSOCKBUFFERS; n++)
{
if (lma->socketbuffer[s][n].ecb.inUse == 0)
{
for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link)
{
if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence)
break;
prev = ecb;
}
if (ecb)
lma->socketbuffer[s][n].ecb.link = ecb;
else
lma->socketbuffer[s][n].ecb.link = NULL;
if (prev)
prev->link = &lma->socketbuffer[s][n].ecb;
else
readlist[s] = &lma->socketbuffer[s][n].ecb;
lma->socketbuffer[s][n].ecb.inUse = 0xff;
}
}
}
//=============================================================================
int IPX_Init(void)
{
int s;
int n;
struct qsockaddr addr;
char *colon;
if (COM_CheckParm ("-noipx"))
return -1;
// find the IPX far call entry point
regs.x.ax = 0x7a00;
__dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)&regs);
if (regs.h.al != 0xff)
{
Con_Printf("IPX not detected\n");
return -1;
}
ipx_cs = regs.x.es;
ipx_ip = regs.x.di;
// grab a chunk of memory down in DOS land
lowmem_buffer = dos_getmemory(LOWMEMSIZE);
if (!lowmem_buffer)
{
Con_Printf("IPX_Init: Not enough low memory\n");
return -1;
}
lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
// init socket handles & buffers
handlesInUse = 0;
lma = (ipx_lowmem_area_t *)lowmem_buffer;
for (s = 0; s < IPXSOCKETS; s++)
{
ipxsocket[s] = 0;
for (n = 0; n < IPXSOCKBUFFERS; n++)
{
lma->socketbuffer[s][n].ecb.link = NULL;
lma->socketbuffer[s][n].ecb.ESR_off = 0;
lma->socketbuffer[s][n].ecb.ESR_seg = 0;
lma->socketbuffer[s][n].ecb.socket = 0;
lma->socketbuffer[s][n].ecb.inUse = 0xff;
lma->socketbuffer[s][n].ecb.completionCode = 0;
lma->socketbuffer[s][n].ecb.fragCount = 1;
lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf;
lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4;
lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
}
}
if ((net_controlsocket = IPX_OpenSocket (0)) == -1)
{
dos_freememory(lowmem_buffer);
Con_DPrintf ("IPX_Init: Unable to open control socket\n");
return -1;
}
SchedulePollProcedure(&pollProcedure, 0.01);
IPX_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_ipx_address, IPX_AddrToString (&addr));
colon = Q_strrchr (my_ipx_address, ':');
if (colon)
*colon = 0;
Con_Printf("IPX initialized\n");
ipxAvailable = true;
return net_controlsocket;
}
//=============================================================================
void IPX_Shutdown(void)
{
IPX_Listen (false);
IPX_CloseSocket (net_controlsocket);
dos_freememory(lowmem_buffer);
}
//=============================================================================
void IPX_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1)
Sys_Error ("IPX_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
IPX_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
int IPX_OpenSocket(int port)
{
int handle;
int n;
unsigned short socket;
if (handlesInUse == IPXSOCKETS)
return -1;
// open the IPX socket
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_OPEN;
regs.h.al = 0;
regs.x.dx = htons(port);
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
if (regs.h.al == 0xfe)
{
Con_DPrintf("IPX_OpenSocket: all sockets in use\n");
return -1;
}
if (regs.h.al == 0xff)
{
Con_DPrintf("IPX_OpenSocket: socket already open\n");
return -1;
}
if (regs.h.al != 0)
{
Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al);
return -1;
}
socket = regs.x.dx;
// grab a handle; fill in the ECBs, and get them listening
for (handle = 0; handle < IPXSOCKETS; handle++)
{
if (ipxsocket[handle] == 0)
{
ipxsocket[handle] = socket;
readlist[handle] = NULL;
sequence[handle] = 0;
for (n = 0; n < IPXSOCKBUFFERS; n ++)
{
lma->socketbuffer[handle][n].ecb.socket = socket;
lma->socketbuffer[handle][n].ecb.inUse = 0;
if (n)
IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb);
}
handlesInUse++;
return handle;
}
}
// "this will NEVER happen"
Sys_Error("IPX_OpenSocket: handle allocation failed\n");
return -1;
}
//=============================================================================
int IPX_CloseSocket(int handle)
{
// if there's a send in progress, give it one last chance
if (lma->socketbuffer[handle][0].ecb.inUse != 0)
IPX_RelinquishControl();
// close the socket (all pending sends/received are cancelled)
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_CLOSE;
regs.x.dx = ipxsocket[handle];
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
ipxsocket[handle] = 0;
handlesInUse--;
return 0;
}
//=============================================================================
int IPX_Connect (int handle, struct qsockaddr *addr)
{
IPXaddr ipxaddr;
Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
{
Con_Printf("Get Local Target failed\n");
return -1;
}
return 0;
}
//=============================================================================
int IPX_CheckNewConnections (void)
{
int n;
if (net_acceptsocket == -1)
return -1;
for (n = 1; n < IPXSOCKBUFFERS; n ++)
if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0)
return net_acceptsocket;
return -1;
}
//=============================================================================
int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
{
ECB *ecb;
ipx_lowmem_buffer_t *rcvbuf;
int copylen;
ProcessReadyList(handle);
tryagain:
if (readlist[handle] == NULL)
return 0;
ecb = readlist[handle];
readlist[handle] = ecb->link;
if (ecb->completionCode != 0)
{
Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode);
ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
IPX_ListenForPacket(ecb);
goto tryagain;
}
rcvbuf = (ipx_lowmem_buffer_t *)ecb;
// copy the data up to the buffer
copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader));
if (len < copylen)
Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen);
Q_memcpy(buf, rcvbuf->data, copylen);
// fill in the addr if they want it
if (addr)
{
((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE;
Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr));
((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0;
((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0;
}
// update the send ecb's immediate address
Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6);
// get this ecb listening again
rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
IPX_ListenForPacket(&rcvbuf->ecb);
return copylen;
}
//=============================================================================
int IPX_Broadcast (int handle, byte *buf, int len)
{
struct sockaddr_ipx addr;
int ret;
Q_memset(addr.sipx_addr.network, 0x00, 4);
Q_memset(addr.sipx_addr.node, 0xff, 6);
addr.sipx_port = htons(net_hostport);
Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6);
ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr);
return ret;
}
//=============================================================================
int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
{
// has the previous send completed?
while (lma->socketbuffer[handle][0].ecb.inUse != 0)
IPX_RelinquishControl();
switch (lma->socketbuffer[handle][0].ecb.completionCode)
{
case 0x00: // success
case 0xfc: // request cancelled
break;
case 0xfd: // malformed packet
default:
Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode);
break;
case 0xfe: // packet undeliverable
case 0xff: // unable to send packet
Con_Printf("IPX lost route, trying to re-establish\n");
// look for a new route
if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
return -1;
// re-send the one that failed
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_SEND;
regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
// report that we did not send the current one
return 0;
}
// ecb : length
lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len;
// ipx header : type
lma->socketbuffer[handle][0].header.type = PTYPE_IPX;
// ipx header : destination
Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
// sequence number
lma->socketbuffer[handle][0].sequence = sequence[handle];
sequence[handle]++;
// copy down the data
Q_memcpy(lma->socketbuffer[handle][0].data, buf, len);
regs.x.cs = ipx_cs;
regs.x.ip = ipx_ip;
regs.x.bx = IPX_SEND;
regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
return len;
}
//=============================================================================
char *IPX_AddrToString (struct qsockaddr *addr)
{
static char buf[28];
sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
((struct sockaddr_ipx *)addr)->sipx_addr.network[0],
((struct sockaddr_ipx *)addr)->sipx_addr.network[1],
((struct sockaddr_ipx *)addr)->sipx_addr.network[2],
((struct sockaddr_ipx *)addr)->sipx_addr.network[3],
((struct sockaddr_ipx *)addr)->sipx_addr.node[0],
((struct sockaddr_ipx *)addr)->sipx_addr.node[1],
((struct sockaddr_ipx *)addr)->sipx_addr.node[2],
((struct sockaddr_ipx *)addr)->sipx_addr.node[3],
((struct sockaddr_ipx *)addr)->sipx_addr.node[4],
((struct sockaddr_ipx *)addr)->sipx_addr.node[5],
ntohs(((struct sockaddr_ipx *)addr)->sipx_port)
);
return buf;
}
//=============================================================================
int IPX_StringToAddr (char *string, struct qsockaddr *addr)
{
int val;
char buf[3];
buf[2] = 0;
Q_memset(addr, 0, sizeof(struct qsockaddr));
addr->sa_family = AF_NETWARE;
#define DO(src,dest) \
buf[0] = string[src]; \
buf[1] = string[src + 1]; \
if (sscanf (buf, "%x", &val) != 1) \
return -1; \
((struct sockaddr_ipx *)addr)->sipx_addr.dest = val
DO(0, network[0]);
DO(2, network[1]);
DO(4, network[2]);
DO(6, network[3]);
DO(9, node[0]);
DO(11, node[1]);
DO(13, node[2]);
DO(15, node[3]);
DO(17, node[4]);
DO(19, node[5]);
#undef DO
sscanf (&string[22], "%u", &val);
((struct sockaddr_ipx *)addr)->sipx_port = htons(val);
return 0;
}
//=============================================================================
int IPX_GetSocketAddr (int handle, struct qsockaddr *addr)
{
Q_memset(addr, 0, sizeof(struct qsockaddr));
addr->sa_family = AF_NETWARE;
IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr);
((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle];
return 0;
}
//=============================================================================
int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
Q_strcpy(name, IPX_AddrToString(addr));
return 0;
}
//=============================================================================
int IPX_GetAddrFromName (char *name, struct qsockaddr *addr)
{
int n;
char buf[32];
n = Q_strlen(name);
if (n == 12)
{
sprintf(buf, "00000000:%s:%u", name, net_hostport);
return IPX_StringToAddr (buf, addr);
}
if (n == 21)
{
sprintf(buf, "%s:%u", name, net_hostport);
return IPX_StringToAddr (buf, addr);
}
if (n > 21 && n <= 27)
return IPX_StringToAddr (name, addr);
return -1;
}
//=============================================================================
int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10))
return -1;
if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port)
return 1;
return 0;
}
//=============================================================================
int IPX_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_ipx *)addr)->sipx_port);
}
int IPX_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_ipx *)addr)->sipx_port = htons(port);
return 0;
}
//=============================================================================

View file

@ -1,39 +0,0 @@
/*
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.
*/
// net_ipx.h
int IPX_Init (void);
void IPX_Shutdown (void);
void IPX_Listen (qboolean state);
int IPX_OpenSocket (int port);
int IPX_CloseSocket (int socket);
int IPX_Connect (int socket, struct qsockaddr *addr);
int IPX_CheckNewConnections (void);
int IPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int IPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int IPX_Broadcast (int socket, byte *buf, int len);
char *IPX_AddrToString (struct qsockaddr *addr);
int IPX_StringToAddr (char *string, struct qsockaddr *addr);
int IPX_GetSocketAddr (int socket, struct qsockaddr *addr);
int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name);
int IPX_GetAddrFromName (char *name, struct qsockaddr *addr);
int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int IPX_GetSocketPort (struct qsockaddr *addr);
int IPX_SetSocketPort (struct qsockaddr *addr, int port);

View file

@ -1,443 +0,0 @@
/*
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.
*/
// net_mpath.c
#include <dpmi.h>
#include "quakedef.h"
#include "mpdosock.h"
short flat_selector;
int WSAGetLastError(void);
void sockets_flush(void);
extern cvar_t hostname;
#define MAXHOSTNAMELEN 256
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket;
static int net_broadcastsocket = 0;
//static qboolean ifbcastinit = false;
static struct qsockaddr broadcastaddr;
static unsigned long myAddr;
#include "net_mp.h"
//=============================================================================
int MPATH_Init (void)
{
int i;
struct hostent *local = NULL;
char buff[MAXHOSTNAMELEN];
struct qsockaddr addr;
char *p;
if (COM_CheckParm ("-mpath") == 0)
return -1;
flat_selector = __dpmi_allocate_ldt_descriptors(1);
if (flat_selector == -1) {
Con_Printf("MPATH_Init: Can't get flat selector\n");
return -1;
}
if (__dpmi_set_segment_base_address(flat_selector, 0) == -1) {
Con_Printf("MPATH_Init: Can't seg flat base!\n");
return -1;
}
if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1) {
Con_Printf("MPATH_Init: Can't set segment limit\n");
return -1;
}
// determine my name & address
if (gethostname(buff, MAXHOSTNAMELEN) == 0)
local = gethostbyname(buff);
if (local)
{
myAddr = *(int *)local->h_addr_list[0];
// if the quake hostname isn't set, set it to the machine name
if (strcmp(hostname.string, "UNNAMED") == 0)
{
// see if it's a text IP address (well, close enough)
for (p = buff; *p; p++)
if ((*p < '0' || *p > '9') && *p != '.')
break;
// if it is a real name, strip off the domain; we only want the host
if (*p)
{
for (i = 0; i < 15; i++)
if (buff[i] == '.')
break;
buff[i] = 0;
}
Cvar_Set ("hostname", buff);
}
}
if ((net_controlsocket = MPATH_OpenSocket (0)) == -1)
Sys_Error("MPATH_Init: Unable to open control socket\n");
((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
MPATH_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, MPATH_AddrToString (&addr));
p = Q_strrchr (my_tcpip_address, ':');
if (p)
*p = 0;
Con_Printf("MPath Initialized\n");
tcpipAvailable = true;
return net_controlsocket;
}
//=============================================================================
void MPATH_Shutdown (void)
{
MPATH_Listen (false);
MPATH_CloseSocket (net_controlsocket);
}
//=============================================================================
void MPATH_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1)
Sys_Error ("MPATH_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
MPATH_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
int MPATH_OpenSocket (int port)
{
int newsocket;
struct sockaddr_in address;
u_long _true = 1;
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
goto ErrorReturn;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
goto ErrorReturn;
return newsocket;
ErrorReturn:
closesocket (newsocket);
return -1;
}
//=============================================================================
int MPATH_CloseSocket (int socket)
{
if (socket == net_broadcastsocket)
net_broadcastsocket = 0;
return closesocket (socket);
}
//=============================================================================
/*
============
PartialIPAddress
this lets you type only as much of the net address as required, using
the local network components to fill in the rest
============
*/
static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
{
char buff[256];
char *b;
int addr;
int num;
int mask;
int run;
int port;
buff[0] = '.';
b = buff;
strcpy(buff+1, in);
if (buff[1] == '.')
b++;
addr = 0;
mask=-1;
while (*b == '.')
{
b++;
num = 0;
run = 0;
while (!( *b < '0' || *b > '9'))
{
num = num*10 + *b++ - '0';
if (++run > 3)
return -1;
}
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
return -1;
if (num < 0 || num > 255)
return -1;
mask<<=8;
addr = (addr<<8) + num;
}
if (*b++ == ':')
port = Q_atoi(b);
else
port = net_hostport;
hostaddr->sa_family = AF_INET;
((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
return 0;
}
//=============================================================================
int MPATH_Connect (int socket, struct qsockaddr *addr)
{
return 0;
}
//=============================================================================
int MPATH_CheckNewConnections (void)
{
char buf[4];
if (net_acceptsocket == -1)
return -1;
if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
return net_acceptsocket;
return -1;
}
//=============================================================================
int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int ret;
ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1)
{
int errno = WSAGetLastError();
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
return 0;
}
return ret;
}
//=============================================================================
int MPATH_MakeSocketBroadcastCapable (int socket)
{
int i = 1;
// make this socket broadcast capable
if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
return -1;
net_broadcastsocket = socket;
return 0;
}
//=============================================================================
int MPATH_Broadcast (int socket, byte *buf, int len)
{
int ret;
if (socket != net_broadcastsocket)
{
if (net_broadcastsocket != 0)
Sys_Error("Attempted to use multiple broadcasts sockets\n");
ret = MPATH_MakeSocketBroadcastCapable (socket);
if (ret == -1)
{
Con_Printf("Unable to make socket broadcast capable\n");
return ret;
}
}
return MPATH_Write (socket, buf, len, &broadcastaddr);
}
//=============================================================================
int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int ret;
ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1)
if (WSAGetLastError() == WSAEWOULDBLOCK)
return 0;
sockets_flush();
return ret;
}
//=============================================================================
char *MPATH_AddrToString (struct qsockaddr *addr)
{
static char buffer[22];
int haddr;
haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
return buffer;
}
//=============================================================================
int MPATH_StringToAddr (char *string, struct qsockaddr *addr)
{
int ha1, ha2, ha3, ha4, hp;
int ipaddr;
sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
((struct sockaddr_in *)addr)->sin_port = htons(hp);
return 0;
}
//=============================================================================
int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr)
{
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
Q_memset(addr, 0, sizeof(struct qsockaddr));
getsockname(socket, (struct sockaddr *)addr, &addrlen);
a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
if (a == 0 || a == inet_addr("127.0.0.1"))
((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
return 0;
}
//=============================================================================
int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
struct hostent *hostentry;
hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
if (hostentry)
{
Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
return 0;
}
Q_strcpy (name, MPATH_AddrToString (addr));
return 0;
}
//=============================================================================
int MPATH_GetAddrFromName(char *name, struct qsockaddr *addr)
{
struct hostent *hostentry;
if (name[0] >= '0' && name[0] <= '9')
return PartialIPAddress (name, addr);
hostentry = gethostbyname (name);
if (!hostentry)
return -1;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
return 0;
}
//=============================================================================
int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
return -1;
if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
return 1;
return 0;
}
//=============================================================================
int MPATH_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
int MPATH_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
//=============================================================================

View file

@ -1,39 +0,0 @@
/*
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.
*/
// net_mpath.h
int MPATH_Init (void);
void MPATH_Shutdown (void);
void MPATH_Listen (qboolean state);
int MPATH_OpenSocket (int port);
int MPATH_CloseSocket (int socket);
int MPATH_Connect (int socket, struct qsockaddr *addr);
int MPATH_CheckNewConnections (void);
int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int MPATH_Broadcast (int socket, byte *buf, int len);
char *MPATH_AddrToString (struct qsockaddr *addr);
int MPATH_StringToAddr (char *string, struct qsockaddr *addr);
int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr);
int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name);
int MPATH_GetAddrFromName (char *name, struct qsockaddr *addr);
int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int MPATH_GetSocketPort (struct qsockaddr *addr);
int MPATH_SetSocketPort (struct qsockaddr *addr, int port);

View file

@ -1,46 +0,0 @@
/*
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.
*/
#include "quakedef.h"
#include "net_loop.h"
net_driver_t net_drivers[MAX_NET_DRIVERS] =
{
{
"Loopback",
false,
Loop_Init,
Loop_Listen,
Loop_SearchForHosts,
Loop_Connect,
Loop_CheckNewConnections,
Loop_GetMessage,
Loop_SendMessage,
Loop_SendUnreliableMessage,
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
Loop_Shutdown
}
};
int net_numdrivers = 1;
net_landriver_t net_landrivers[MAX_NET_DRIVERS];
int net_numlandrivers = 0;

View file

@ -1,951 +0,0 @@
/*
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.
*/
// net_ser.c
#include "quakedef.h"
#include "net_ser.h"
#include "dosisms.h"
#include "crc.h"
#include "net_comx.c"
// serial protocol
#define SERIAL_PROTOCOL_VERSION 3
// The serial protocol is message oriented. The high level message format is
// a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All
// multi-byte fields are sent in network byte order. There are currently 4
// MTYPEs defined. Their formats are as follows:
//
// MTYPE_RELIABLE sequence data_length data checksum eom
// MTYPE_UNRELIABLE sequence data_length data checksum eom
// MTYPE_ACK sequence checksum eom
// MTYPE_CONTROL data_length data checksum eom
//
// sequence is an 8-bit unsigned value starting from 0
// data_length is a 16-bit unsigned value; it is the length of the data only
// the checksum is a 16-bit value. the CRC formula used is defined in crc.h.
// the checksum covers the entire messages, excluding itself
// eom is a special 2 byte sequence used to mark the End Of Message. This is
// needed for error recovery.
//
// A lot of behavior is based on knowledge of the upper level Quake network
// layer. For example, only one reliable message can be outstanding (pending
// reception of an MTYPE_ACK) at a time.
//
// The low level routines used to communicate with the modem are not part of
// this protocol.
//
// The CONTROL messages are only used for session establishment. They are
// not reliable or sequenced.
#define MTYPE_RELIABLE 0x01
#define MTYPE_UNRELIABLE 0x02
#define MTYPE_CONTROL 0x03
#define MTYPE_ACK 0x04
#define MTYPE_CLIENT 0x80
#define ESCAPE_COMMAND 0xe0
#define ESCAPE_EOM 0x19
static qboolean listening = false;
typedef struct SerialLine_s
{
struct SerialLine_s *next;
qsocket_t *sock;
int lengthStated;
int lengthFound;
int tty;
qboolean connected;
qboolean connecting;
qboolean client;
double connect_time;
unsigned short crcStated;
unsigned short crcValue;
byte currState;
byte prevState;
byte mtype;
byte sequence;
} SerialLine;
#define STATE_READY 0
#define STATE_SEQUENCE 1
#define STATE_LENGTH1 2
#define STATE_LENGTH2 3
#define STATE_DATA 4
#define STATE_CRC1 5
#define STATE_CRC2 6
#define STATE_EOM 7
#define STATE_ESCAPE 8
#define STATE_ABORT 9
SerialLine serialLine[NUM_COM_PORTS];
int myDriverLevel;
static void Serial_SendACK (SerialLine *p, byte sequence);
static void ResetSerialLineProtocol (SerialLine *p)
{
p->connected = false;
p->connecting = false;
p->currState = STATE_READY;
p->prevState = STATE_READY;
p->lengthFound = 0;
}
static int ProcessInQueue(SerialLine *p)
{
int b;
while (1)
{
b = TTY_ReadByte(p->tty);
if (b == ERR_TTY_NODATA)
break;
if (b == ERR_TTY_LINE_STATUS)
{
p->currState = STATE_ABORT;
continue;
}
if (b == ERR_TTY_MODEM_STATUS)
{
p->currState = STATE_ABORT;
return -1;
}
if (b == ESCAPE_COMMAND)
if (p->currState != STATE_ESCAPE)
{
p->prevState = p->currState;
p->currState = STATE_ESCAPE;
continue;
}
if (p->currState == STATE_ESCAPE)
{
if (b == ESCAPE_EOM)
{
if (p->prevState == STATE_ABORT)
{
p->currState = STATE_READY;
p->lengthFound = 0;
continue;
}
if (p->prevState != STATE_EOM)
{
p->currState = STATE_READY;
p->lengthFound = 0;
Con_DPrintf("Serial: premature EOM\n");
continue;
}
switch (p->mtype)
{
case MTYPE_RELIABLE:
Con_DPrintf("Serial: sending ack %u\n", p->sequence);
Serial_SendACK (p, p->sequence);
if (p->sequence == p->sock->receiveSequence)
{
p->sock->receiveSequence = (p->sequence + 1) & 0xff;
p->sock->receiveMessageLength += p->lengthFound;
}
else
Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence);
break;
case MTYPE_UNRELIABLE:
p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff;
p->sock->receiveMessageLength += p->lengthFound;
break;
case MTYPE_ACK:
Con_DPrintf("Serial: got ack %u\n", p->sequence);
if (p->sequence == p->sock->sendSequence)
{
p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff;
p->sock->canSend = true;
}
else
Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence);
break;
case MTYPE_CONTROL:
p->sock->receiveMessageLength += p->lengthFound;
break;
}
p->currState = STATE_READY;
p->lengthFound = 0;
continue;
}
if (b != ESCAPE_COMMAND)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: Bad escape sequence\n");
continue;
}
// b == ESCAPE_COMMAND
p->currState = p->prevState;
}
p->prevState = p->currState;
//DEBUG
if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE)
{
Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound);
p->currState = STATE_ABORT;
}
if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE)
{
Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound);
p->currState = STATE_ABORT;
}
//end DEBUG
switch (p->currState)
{
case STATE_READY:
CRC_Init(&p->crcValue);
CRC_ProcessByte(&p->crcValue, b);
if (p->client)
{
if ((b & MTYPE_CLIENT) != 0)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: client got own message\n");
break;
}
}
else
{
if ((b & MTYPE_CLIENT) == 0)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: server got own message\n");
break;
}
b &= 0x7f;
}
p->mtype = b;
if (b != MTYPE_CONTROL)
p->currState = STATE_SEQUENCE;
else
p->currState = STATE_LENGTH1;
if (p->mtype < MTYPE_ACK)
{
p->sock->receiveMessage[p->sock->receiveMessageLength] = b;
p->lengthFound++;
}
break;
case STATE_SEQUENCE:
p->sequence = b;
CRC_ProcessByte(&p->crcValue, b);
if (p->mtype != MTYPE_ACK)
p->currState = STATE_LENGTH1;
else
p->currState = STATE_CRC1;
break;
case STATE_LENGTH1:
p->lengthStated = b * 256;
CRC_ProcessByte(&p->crcValue, b);
p->currState = STATE_LENGTH2;
break;
case STATE_LENGTH2:
p->lengthStated += b;
CRC_ProcessByte(&p->crcValue, b);
if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated);
}
else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM)
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated);
}
else
{
p->currState = STATE_DATA;
if (p->mtype < MTYPE_ACK)
{
*(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated;
p->lengthFound += 2;
}
}
break;
case STATE_DATA:
p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b;
p->lengthFound++;
CRC_ProcessByte(&p->crcValue, b);
if (p->lengthFound == p->lengthStated + 3)
p->currState = STATE_CRC1;
break;
case STATE_CRC1:
p->crcStated = b * 256;
p->currState = STATE_CRC2;
break;
case STATE_CRC2:
p->crcStated += b;
if (p->crcStated == CRC_Value(p->crcValue))
{
p->currState = STATE_EOM;
}
else
{
p->currState = STATE_ABORT;
Con_DPrintf("Serial: Bad crc\n");
}
break;
case STATE_EOM:
p->currState = STATE_ABORT;
Con_DPrintf("Serial: Bad message format\n");
break;
case STATE_ABORT:
break;
}
}
return 0;
}
int Serial_Init (void)
{
int n;
// LATER do Win32 serial support
#ifdef _WIN32
return -1;
#endif
if (COM_CheckParm("-nolan"))
return -1;
if (COM_CheckParm ("-noserial"))
return -1;
myDriverLevel = net_driverlevel;
if (TTY_Init())
return -1;
for (n = 0; n < NUM_COM_PORTS; n++)
{
serialLine[n].tty = TTY_Open(n);
ResetSerialLineProtocol (&serialLine[n]);
}
Con_Printf("Serial driver initialized\n");
serialAvailable = true;
return 0;
}
void Serial_Shutdown (void)
{
int n;
for (n = 0; n < NUM_COM_PORTS; n++)
{
if (serialLine[n].connected)
Serial_Close(serialLine[n].sock);
}
TTY_Shutdown();
}
void Serial_Listen (qboolean state)
{
listening = state;
}
qboolean Serial_CanSendMessage (qsocket_t *sock)
{
return sock->canSend;
}
qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock)
{
return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty);
}
int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message)
{
SerialLine *p;
int n;
unsigned short crc;
byte b;
p = (SerialLine *)sock->driverdata;
CRC_Init (&crc);
// message type
b = MTYPE_RELIABLE;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// sequence
b = p->sock->sendSequence;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// data length
b = message->cursize >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
b = message->cursize & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// data
for (n = 0; n < message->cursize; n++)
{
b = message->data[n];
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
}
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
TTY_Flush(p->tty);
// mark sock as busy and save the message for possible retransmit
sock->canSend = false;
Q_memcpy(sock->sendMessage, message->data, message->cursize);
sock->sendMessageLength = message->cursize;
sock->lastSendTime = net_time;
return 1;
}
static void ReSendMessage (qsocket_t *sock)
{
sizebuf_t temp;
Con_DPrintf("Serial: re-sending reliable\n");
temp.data = sock->sendMessage;
temp.maxsize = sock->sendMessageLength;
temp.cursize = sock->sendMessageLength;
Serial_SendMessage (sock, &temp);
}
int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message)
{
SerialLine *p;
int n;
unsigned short crc;
byte b;
p = (SerialLine *)sock->driverdata;
if (!TTY_OutputQueueIsEmpty(p->tty))
{
TTY_Flush(p->tty);
return 1;
}
CRC_Init (&crc);
// message type
b = MTYPE_UNRELIABLE;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// sequence
b = p->sock->unreliableSendSequence;
p->sock->unreliableSendSequence = (b + 1) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// data length
b = message->cursize >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
b = message->cursize & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// data
for (n = 0; n < message->cursize; n++)
{
b = message->data[n];
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
}
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
TTY_Flush(p->tty);
return 1;
}
static void Serial_SendACK (SerialLine *p, byte sequence)
{
unsigned short crc;
byte b;
CRC_Init (&crc);
// message type
b = MTYPE_ACK;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// sequence
b = sequence;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
TTY_Flush(p->tty);
}
static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message)
{
unsigned short crc;
int n;
byte b;
CRC_Init (&crc);
// message type
b = MTYPE_CONTROL;
if (p->client)
b |= MTYPE_CLIENT;
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// data length
b = message->cursize >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
b = message->cursize & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
// data
for (n = 0; n < message->cursize; n++)
{
b = message->data[n];
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
CRC_ProcessByte (&crc, b);
}
// checksum
b = CRC_Value (crc) >> 8;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
b = CRC_Value (crc) & 0xff;
TTY_WriteByte(p->tty, b);
if (b == ESCAPE_COMMAND)
TTY_WriteByte(p->tty, b);
// end of message
TTY_WriteByte(p->tty, ESCAPE_COMMAND);
TTY_WriteByte(p->tty, ESCAPE_EOM);
TTY_Flush(p->tty);
}
static int _Serial_GetMessage (SerialLine *p)
{
byte ret;
short length;
if (ProcessInQueue(p))
return -1;
if (p->sock->receiveMessageLength == 0)
return 0;
ret = p->sock->receiveMessage[0];
length = *(short *)&p->sock->receiveMessage[1];
if (ret == MTYPE_CONTROL)
ret = 1;
SZ_Clear (&net_message);
SZ_Write (&net_message, &p->sock->receiveMessage[3], length);
length += 3;
p->sock->receiveMessageLength -= length;
if (p->sock->receiveMessageLength + p->lengthFound)
Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound);
return ret;
}
int Serial_GetMessage (qsocket_t *sock)
{
SerialLine *p;
int ret;
p = (SerialLine *)sock->driverdata;
ret = _Serial_GetMessage (p);
if (ret == 1)
messagesReceived++;
if (!sock->canSend)
if ((net_time - sock->lastSendTime) > 1.0)
{
ReSendMessage (sock);
sock->lastSendTime = net_time;
}
return ret;
}
void Serial_Close (qsocket_t *sock)
{
SerialLine *p = (SerialLine *)sock->driverdata;
TTY_Close(p->tty);
ResetSerialLineProtocol (p);
}
char *com_types[] = {"direct", "modem"};
unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600};
void Serial_SearchForHosts (qboolean xmit)
{
int n;
SerialLine *p;
if (sv.active)
return;
if (hostCacheCount == HOSTCACHESIZE)
return;
// see if we've already answered
for (n = 0; n < hostCacheCount; n++)
if (strcmp (hostcache[n].cname, "#") == 0)
return;
for (n = 0; n < NUM_COM_PORTS; n++)
if (TTY_IsEnabled(n))
break;
if (n == NUM_COM_PORTS)
return;
p = &serialLine[n];
if (TTY_IsModem(p->tty))
return;
sprintf(hostcache[hostCacheCount].name, "COM%u", n+1);
Q_strcpy(hostcache[hostCacheCount].map, "");
hostcache[hostCacheCount].users = 0;
hostcache[hostCacheCount].maxusers = 0;
hostcache[hostCacheCount].driver = net_driverlevel;
Q_strcpy(hostcache[hostCacheCount].cname, "#");
hostCacheCount++;
return;
}
static qsocket_t *_Serial_Connect (char *host, SerialLine *p)
{
int ret;
double start_time;
double last_time;
p->client = true;
if (TTY_Connect(p->tty, host))
return NULL;
p->sock = NET_NewQSocket ();
p->sock->driver = myDriverLevel;
if (p->sock == NULL)
{
Con_Printf("No sockets available\n");
return NULL;
}
p->sock->driverdata = p;
// send the connection request
start_time = SetNetTime();
last_time = 0.0;
SZ_Clear(&net_message);
MSG_WriteByte(&net_message, CCREQ_CONNECT);
MSG_WriteString(&net_message, "QUAKE");
do
{
SetNetTime();
if ((net_time - last_time) >= 1.0)
{
Serial_SendControlMessage (p, &net_message);
last_time = net_time;
Con_Printf("trying...\n"); SCR_UpdateScreen ();
}
ret = _Serial_GetMessage (p);
}
while (ret == 0 && (net_time - start_time) < 5.0);
if (ret == 0)
{
Con_Printf("Unable to connect, no response\n");
goto ErrorReturn;
}
if (ret == -1)
{
Con_Printf("Connection request error\n");
goto ErrorReturn;
}
MSG_BeginReading ();
ret = MSG_ReadByte();
if (ret == CCREP_REJECT)
{
Con_Printf(MSG_ReadString());
goto ErrorReturn;
}
if (ret != CCREP_ACCEPT)
{
Con_Printf("Unknown connection response\n");
goto ErrorReturn;
}
p->connected = true;
p->sock->lastMessageTime = net_time;
Con_Printf ("Connection accepted\n");
return p->sock;
ErrorReturn:
TTY_Disconnect(p->tty);
return NULL;
}
qsocket_t *Serial_Connect (char *host)
{
int n;
qsocket_t *ret = NULL;
// see if this looks like a phone number
if (*host == '#')
host++;
for (n = 0; n < Q_strlen(host); n++)
if (host[n] == '.' || host[n] == ':')
return NULL;
for (n = 0; n < NUM_COM_PORTS; n++)
if (TTY_IsEnabled(n) && !serialLine[n].connected)
if ((ret = _Serial_Connect (host, &serialLine[n])))
break;
return ret;
}
static qsocket_t *_Serial_CheckNewConnections (SerialLine *p)
{
int command;
p->client = false;
if (!TTY_CheckForConnection(p->tty))
return NULL;
if (TTY_IsModem(p->tty))
{
if (!p->connecting)
{
p->connecting = true;
p->connect_time = net_time;
}
else if ((net_time - p->connect_time) > 15.0)
{
p->connecting = false;
TTY_Disconnect(p->tty);
return NULL;
}
}
p->sock = NET_NewQSocket ();
p->sock->driver = myDriverLevel;
if (p->sock == NULL)
{
Con_Printf("No sockets available\n");
return NULL;
}
p->sock->driverdata = p;
SZ_Clear(&net_message);
if (_Serial_GetMessage(p) != 1)
{
NET_FreeQSocket(p->sock);
return NULL;
}
MSG_BeginReading ();
command = MSG_ReadByte();
if (command == CCREQ_SERVER_INFO)
{
if (strcmp(MSG_ReadString(), "QUAKE") != 0)
return NULL;
if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION)
return NULL;
SZ_Clear(&net_message);
MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
MSG_WriteString(&net_message, hostname.string);
MSG_WriteString(&net_message, sv.name);
MSG_WriteByte(&net_message, net_activeconnections);
MSG_WriteByte(&net_message, svs.maxclients);
Serial_SendControlMessage (p, &net_message);
SZ_Clear(&net_message);
return NULL;
}
if (command != CCREQ_CONNECT)
return NULL;
if (strcmp(MSG_ReadString(), "QUAKE") != 0)
return NULL;
// send him back the info about the server connection he has been allocated
SZ_Clear(&net_message);
MSG_WriteByte(&net_message, CCREP_ACCEPT);
Serial_SendControlMessage (p, &net_message);
SZ_Clear(&net_message);
p->connected = true;
p->connecting = false;
p->sock->lastMessageTime = net_time;
sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1));
return p->sock;
}
qsocket_t *Serial_CheckNewConnections (void)
{
int n;
qsocket_t *ret = NULL;
for (n = 0; n < NUM_COM_PORTS; n++)
if (TTY_IsEnabled(n) && !serialLine[n].connected)
if ((ret = _Serial_CheckNewConnections (&serialLine[n])))
break;
return ret;
}

View file

@ -1,33 +0,0 @@
/*
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.
*/
// net_ser.h
int Serial_Init (void);
void Serial_Listen (qboolean state);
void Serial_SearchForHosts (qboolean xmit);
qsocket_t *Serial_Connect (char *host);
qsocket_t *Serial_CheckNewConnections (void);
int Serial_GetMessage (qsocket_t *sock);
int Serial_SendMessage (qsocket_t *sock, sizebuf_t *data);
int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Serial_CanSendMessage (qsocket_t *sock);
qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock);
void Serial_Close (qsocket_t *sock);
void Serial_Shutdown (void);

View file

@ -1,414 +0,0 @@
/*
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.
*/
// net_udp.c
#include "quakedef.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <errno.h>
#ifdef __sun__
#include <sys/filio.h>
#endif
#ifdef NeXT
#include <libc.h>
#endif
extern int gethostname (char *, int);
extern int close (int);
extern cvar_t hostname;
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket;
static int net_broadcastsocket = 0;
static struct qsockaddr broadcastaddr;
static unsigned long myAddr;
#include "net_udp.h"
//=============================================================================
int UDP_Init (void)
{
struct hostent *local;
char buff[MAXHOSTNAMELEN];
struct qsockaddr addr;
char *colon;
if (COM_CheckParm ("-noudp"))
return -1;
// determine my name & address
gethostname(buff, MAXHOSTNAMELEN);
local = gethostbyname(buff);
myAddr = *(int *)local->h_addr_list[0];
// if the quake hostname isn't set, set it to the machine name
if (strcmp(hostname.string, "UNNAMED") == 0)
{
buff[15] = 0;
Cvar_Set ("hostname", buff);
}
if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
Sys_Error("UDP_Init: Unable to open control socket\n");
((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
UDP_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, UDP_AddrToString (&addr));
colon = Q_strrchr (my_tcpip_address, ':');
if (colon)
*colon = 0;
Con_Printf("UDP Initialized\n");
tcpipAvailable = true;
return net_controlsocket;
}
//=============================================================================
void UDP_Shutdown (void)
{
UDP_Listen (false);
UDP_CloseSocket (net_controlsocket);
}
//=============================================================================
void UDP_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
Sys_Error ("UDP_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
UDP_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
int UDP_OpenSocket (int port)
{
int newsocket;
struct sockaddr_in address;
qboolean _true = true;
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
goto ErrorReturn;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
goto ErrorReturn;
return newsocket;
ErrorReturn:
close (newsocket);
return -1;
}
//=============================================================================
int UDP_CloseSocket (int socket)
{
if (socket == net_broadcastsocket)
net_broadcastsocket = 0;
return close (socket);
}
//=============================================================================
/*
============
PartialIPAddress
this lets you type only as much of the net address as required, using
the local network components to fill in the rest
============
*/
static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
{
char buff[256];
char *b;
int addr;
int num;
int mask;
int run;
int port;
buff[0] = '.';
b = buff;
strcpy(buff+1, in);
if (buff[1] == '.')
b++;
addr = 0;
mask=-1;
while (*b == '.')
{
b++;
num = 0;
run = 0;
while (!( *b < '0' || *b > '9'))
{
num = num*10 + *b++ - '0';
if (++run > 3)
return -1;
}
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
return -1;
if (num < 0 || num > 255)
return -1;
mask<<=8;
addr = (addr<<8) + num;
}
if (*b++ == ':')
port = Q_atoi(b);
else
port = net_hostport;
hostaddr->sa_family = AF_INET;
((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
return 0;
}
//=============================================================================
int UDP_Connect (int socket, struct qsockaddr *addr)
{
return 0;
}
//=============================================================================
int UDP_CheckNewConnections (void)
{
unsigned long available;
if (net_acceptsocket == -1)
return -1;
if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
if (available)
return net_acceptsocket;
return -1;
}
//=============================================================================
int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int ret;
ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
return 0;
return ret;
}
//=============================================================================
int UDP_MakeSocketBroadcastCapable (int socket)
{
int i = 1;
// make this socket broadcast capable
if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
return -1;
net_broadcastsocket = socket;
return 0;
}
//=============================================================================
int UDP_Broadcast (int socket, byte *buf, int len)
{
int ret;
if (socket != net_broadcastsocket)
{
if (net_broadcastsocket != 0)
Sys_Error("Attempted to use multiple broadcasts sockets\n");
ret = UDP_MakeSocketBroadcastCapable (socket);
if (ret == -1)
{
Con_Printf("Unable to make socket broadcast capable\n");
return ret;
}
}
return UDP_Write (socket, buf, len, &broadcastaddr);
}
//=============================================================================
int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int ret;
ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1 && errno == EWOULDBLOCK)
return 0;
return ret;
}
//=============================================================================
char *UDP_AddrToString (struct qsockaddr *addr)
{
static char buffer[22];
int haddr;
haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
return buffer;
}
//=============================================================================
int UDP_StringToAddr (char *string, struct qsockaddr *addr)
{
int ha1, ha2, ha3, ha4, hp;
int ipaddr;
sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
((struct sockaddr_in *)addr)->sin_port = htons(hp);
return 0;
}
//=============================================================================
int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
{
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
Q_memset(addr, 0, sizeof(struct qsockaddr));
getsockname(socket, (struct sockaddr *)addr, &addrlen);
a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
if (a == 0 || a == inet_addr("127.0.0.1"))
((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
return 0;
}
//=============================================================================
int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
struct hostent *hostentry;
hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
if (hostentry)
{
Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
return 0;
}
Q_strcpy (name, UDP_AddrToString (addr));
return 0;
}
//=============================================================================
int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
{
struct hostent *hostentry;
if (name[0] >= '0' && name[0] <= '9')
return PartialIPAddress (name, addr);
hostentry = gethostbyname (name);
if (!hostentry)
return -1;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
return 0;
}
//=============================================================================
int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
return -1;
if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
return 1;
return 0;
}
//=============================================================================
int UDP_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
int UDP_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
//=============================================================================

View file

@ -1,120 +0,0 @@
/*
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.
*/
#include "quakedef.h"
#include "net_loop.h"
#include "net_dgrm.h"
#include "net_ser.h"
net_driver_t net_drivers[MAX_NET_DRIVERS] =
{
{
"Loopback",
false,
Loop_Init,
Loop_Listen,
Loop_SearchForHosts,
Loop_Connect,
Loop_CheckNewConnections,
Loop_GetMessage,
Loop_SendMessage,
Loop_SendUnreliableMessage,
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
Loop_Shutdown
}
,
{
"Datagram",
false,
Datagram_Init,
Datagram_Listen,
Datagram_SearchForHosts,
Datagram_Connect,
Datagram_CheckNewConnections,
Datagram_GetMessage,
Datagram_SendMessage,
Datagram_SendUnreliableMessage,
Datagram_CanSendMessage,
Datagram_CanSendUnreliableMessage,
Datagram_Close,
Datagram_Shutdown
}
};
int net_numdrivers = 2;
#include "net_wins.h"
#include "net_wipx.h"
net_landriver_t net_landrivers[MAX_NET_DRIVERS] =
{
{
"Winsock TCPIP",
false,
0,
WINS_Init,
WINS_Shutdown,
WINS_Listen,
WINS_OpenSocket,
WINS_CloseSocket,
WINS_Connect,
WINS_CheckNewConnections,
WINS_Read,
WINS_Write,
WINS_Broadcast,
WINS_AddrToString,
WINS_StringToAddr,
WINS_GetSocketAddr,
WINS_GetNameFromAddr,
WINS_GetAddrFromName,
WINS_AddrCompare,
WINS_GetSocketPort,
WINS_SetSocketPort
},
{
"Winsock IPX",
false,
0,
WIPX_Init,
WIPX_Shutdown,
WIPX_Listen,
WIPX_OpenSocket,
WIPX_CloseSocket,
WIPX_Connect,
WIPX_CheckNewConnections,
WIPX_Read,
WIPX_Write,
WIPX_Broadcast,
WIPX_AddrToString,
WIPX_StringToAddr,
WIPX_GetSocketAddr,
WIPX_GetNameFromAddr,
WIPX_GetAddrFromName,
WIPX_AddrCompare,
WIPX_GetSocketPort,
WIPX_SetSocketPort
}
};
int net_numlandrivers = 2;

View file

@ -1,575 +0,0 @@
/*
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.
*/
// net_wins.c
#include "quakedef.h"
#include "winquake.h"
extern cvar_t hostname;
#define MAXHOSTNAMELEN 256
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket;
static int net_broadcastsocket = 0;
static struct qsockaddr broadcastaddr;
static unsigned long myAddr;
qboolean winsock_lib_initialized;
int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData);
int (PASCAL FAR *pWSACleanup)(void);
int (PASCAL FAR *pWSAGetLastError)(void);
SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol);
int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp);
int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname,
const char FAR * optval, int optlen);
int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags,
struct sockaddr FAR *from, int FAR * fromlen);
int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags,
const struct sockaddr FAR *to, int tolen);
int (PASCAL FAR *pclosesocket)(SOCKET s);
int (PASCAL FAR *pgethostname)(char FAR * name, int namelen);
struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name);
struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr,
int len, int type);
int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name,
int FAR * namelen);
#include "net_wins.h"
int winsock_initialized = 0;
WSADATA winsockdata;
//=============================================================================
static double blocktime;
BOOL PASCAL FAR BlockingHook(void)
{
MSG msg;
BOOL ret;
if ((Sys_FloatTime() - blocktime) > 2.0)
{
WSACancelBlockingCall();
return FALSE;
}
/* get the next message, if any */
ret = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
/* if we got one, process it */
if (ret) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/* TRUE if we got a message */
return ret;
}
void WINS_GetLocalAddress()
{
struct hostent *local = NULL;
char buff[MAXHOSTNAMELEN];
unsigned long addr;
if (myAddr != INADDR_ANY)
return;
if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR)
return;
blocktime = Sys_FloatTime();
WSASetBlockingHook(BlockingHook);
local = pgethostbyname(buff);
WSAUnhookBlockingHook();
if (local == NULL)
return;
myAddr = *(int *)local->h_addr_list[0];
addr = ntohl(myAddr);
sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
}
int WINS_Init (void)
{
int i;
char buff[MAXHOSTNAMELEN];
char *p;
int r;
WORD wVersionRequested;
HINSTANCE hInst;
// initialize the Winsock function vectors (we do this instead of statically linking
// so we can run on Win 3.1, where there isn't necessarily Winsock)
hInst = LoadLibrary("wsock32.dll");
if (hInst == NULL)
{
Con_SafePrintf ("Failed to load winsock.dll\n");
winsock_lib_initialized = false;
return -1;
}
winsock_lib_initialized = true;
pWSAStartup = (void *)GetProcAddress(hInst, "WSAStartup");
pWSACleanup = (void *)GetProcAddress(hInst, "WSACleanup");
pWSAGetLastError = (void *)GetProcAddress(hInst, "WSAGetLastError");
psocket = (void *)GetProcAddress(hInst, "socket");
pioctlsocket = (void *)GetProcAddress(hInst, "ioctlsocket");
psetsockopt = (void *)GetProcAddress(hInst, "setsockopt");
precvfrom = (void *)GetProcAddress(hInst, "recvfrom");
psendto = (void *)GetProcAddress(hInst, "sendto");
pclosesocket = (void *)GetProcAddress(hInst, "closesocket");
pgethostname = (void *)GetProcAddress(hInst, "gethostname");
pgethostbyname = (void *)GetProcAddress(hInst, "gethostbyname");
pgethostbyaddr = (void *)GetProcAddress(hInst, "gethostbyaddr");
pgetsockname = (void *)GetProcAddress(hInst, "getsockname");
if (!pWSAStartup || !pWSACleanup || !pWSAGetLastError ||
!psocket || !pioctlsocket || !psetsockopt ||
!precvfrom || !psendto || !pclosesocket ||
!pgethostname || !pgethostbyname || !pgethostbyaddr ||
!pgetsockname)
{
Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n");
return -1;
}
if (COM_CheckParm ("-noudp"))
return -1;
if (winsock_initialized == 0)
{
wVersionRequested = MAKEWORD(1, 1);
r = pWSAStartup (MAKEWORD(1, 1), &winsockdata);
if (r)
{
Con_SafePrintf ("Winsock initialization failed.\n");
return -1;
}
}
winsock_initialized++;
// determine my name
if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR)
{
Con_DPrintf ("Winsock TCP/IP Initialization failed.\n");
if (--winsock_initialized == 0)
pWSACleanup ();
return -1;
}
// if the quake hostname isn't set, set it to the machine name
if (strcmp(hostname.string, "UNNAMED") == 0)
{
// see if it's a text IP address (well, close enough)
for (p = buff; *p; p++)
if ((*p < '0' || *p > '9') && *p != '.')
break;
// if it is a real name, strip off the domain; we only want the host
if (*p)
{
for (i = 0; i < 15; i++)
if (buff[i] == '.')
break;
buff[i] = 0;
}
Cvar_Set ("hostname", buff);
}
i = COM_CheckParm ("-ip");
if (i)
{
if (i < com_argc-1)
{
myAddr = inet_addr(com_argv[i+1]);
if (myAddr == INADDR_NONE)
Sys_Error ("%s is not a valid IP address", com_argv[i+1]);
strcpy(my_tcpip_address, com_argv[i+1]);
}
else
{
Sys_Error ("NET_Init: you must specify an IP address after -ip");
}
}
else
{
myAddr = INADDR_ANY;
strcpy(my_tcpip_address, "INADDR_ANY");
}
if ((net_controlsocket = WINS_OpenSocket (0)) == -1)
{
Con_Printf("WINS_Init: Unable to open control socket\n");
if (--winsock_initialized == 0)
pWSACleanup ();
return -1;
}
((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport);
Con_Printf("Winsock TCP/IP Initialized\n");
tcpipAvailable = true;
return net_controlsocket;
}
//=============================================================================
void WINS_Shutdown (void)
{
WINS_Listen (false);
WINS_CloseSocket (net_controlsocket);
if (--winsock_initialized == 0)
pWSACleanup ();
}
//=============================================================================
void WINS_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
WINS_GetLocalAddress();
if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1)
Sys_Error ("WINS_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
WINS_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
int WINS_OpenSocket (int port)
{
int newsocket;
struct sockaddr_in address;
u_long _true = 1;
if ((newsocket = psocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if (pioctlsocket (newsocket, FIONBIO, &_true) == -1)
goto ErrorReturn;
address.sin_family = AF_INET;
address.sin_addr.s_addr = myAddr;
address.sin_port = htons((unsigned short)port);
if( bind (newsocket, (void *)&address, sizeof(address)) == 0)
return newsocket;
Sys_Error ("Unable to bind to %s", WINS_AddrToString((struct qsockaddr *)&address));
ErrorReturn:
pclosesocket (newsocket);
return -1;
}
//=============================================================================
int WINS_CloseSocket (int socket)
{
if (socket == net_broadcastsocket)
net_broadcastsocket = 0;
return pclosesocket (socket);
}
//=============================================================================
/*
============
PartialIPAddress
this lets you type only as much of the net address as required, using
the local network components to fill in the rest
============
*/
static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
{
char buff[256];
char *b;
int addr;
int num;
int mask;
int run;
int port;
buff[0] = '.';
b = buff;
strcpy(buff+1, in);
if (buff[1] == '.')
b++;
addr = 0;
mask=-1;
while (*b == '.')
{
b++;
num = 0;
run = 0;
while (!( *b < '0' || *b > '9'))
{
num = num*10 + *b++ - '0';
if (++run > 3)
return -1;
}
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
return -1;
if (num < 0 || num > 255)
return -1;
mask<<=8;
addr = (addr<<8) + num;
}
if (*b++ == ':')
port = Q_atoi(b);
else
port = net_hostport;
hostaddr->sa_family = AF_INET;
((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
return 0;
}
//=============================================================================
int WINS_Connect (int socket, struct qsockaddr *addr)
{
return 0;
}
//=============================================================================
int WINS_CheckNewConnections (void)
{
char buf[4096];
if (net_acceptsocket == -1)
return -1;
if (precvfrom (net_acceptsocket, buf, sizeof(buf), MSG_PEEK, NULL, NULL) > 0)
{
return net_acceptsocket;
}
return -1;
}
//=============================================================================
int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int ret;
ret = precvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1)
{
int errno = pWSAGetLastError();
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
return 0;
}
return ret;
}
//=============================================================================
int WINS_MakeSocketBroadcastCapable (int socket)
{
int i = 1;
// make this socket broadcast capable
if (psetsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
return -1;
net_broadcastsocket = socket;
return 0;
}
//=============================================================================
int WINS_Broadcast (int socket, byte *buf, int len)
{
int ret;
if (socket != net_broadcastsocket)
{
if (net_broadcastsocket != 0)
Sys_Error("Attempted to use multiple broadcasts sockets\n");
WINS_GetLocalAddress();
ret = WINS_MakeSocketBroadcastCapable (socket);
if (ret == -1)
{
Con_Printf("Unable to make socket broadcast capable\n");
return ret;
}
}
return WINS_Write (socket, buf, len, &broadcastaddr);
}
//=============================================================================
int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int ret;
ret = psendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1)
if (pWSAGetLastError() == WSAEWOULDBLOCK)
return 0;
return ret;
}
//=============================================================================
char *WINS_AddrToString (struct qsockaddr *addr)
{
static char buffer[22];
int haddr;
haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
return buffer;
}
//=============================================================================
int WINS_StringToAddr (char *string, struct qsockaddr *addr)
{
int ha1, ha2, ha3, ha4, hp;
int ipaddr;
sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)hp);
return 0;
}
//=============================================================================
int WINS_GetSocketAddr (int socket, struct qsockaddr *addr)
{
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
Q_memset(addr, 0, sizeof(struct qsockaddr));
pgetsockname(socket, (struct sockaddr *)addr, &addrlen);
a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
if (a == 0 || a == inet_addr("127.0.0.1"))
((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
return 0;
}
//=============================================================================
int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
struct hostent *hostentry;
hostentry = pgethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
if (hostentry)
{
Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
return 0;
}
Q_strcpy (name, WINS_AddrToString (addr));
return 0;
}
//=============================================================================
int WINS_GetAddrFromName(char *name, struct qsockaddr *addr)
{
struct hostent *hostentry;
if (name[0] >= '0' && name[0] <= '9')
return PartialIPAddress (name, addr);
hostentry = pgethostbyname (name);
if (!hostentry)
return -1;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)net_hostport);
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
return 0;
}
//=============================================================================
int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
return -1;
if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
return 1;
return 0;
}
//=============================================================================
int WINS_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
int WINS_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)port);
return 0;
}
//=============================================================================

View file

@ -1,39 +0,0 @@
/*
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.
*/
// net_wins.h
int WINS_Init (void);
void WINS_Shutdown (void);
void WINS_Listen (qboolean state);
int WINS_OpenSocket (int port);
int WINS_CloseSocket (int socket);
int WINS_Connect (int socket, struct qsockaddr *addr);
int WINS_CheckNewConnections (void);
int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int WINS_Broadcast (int socket, byte *buf, int len);
char *WINS_AddrToString (struct qsockaddr *addr);
int WINS_StringToAddr (char *string, struct qsockaddr *addr);
int WINS_GetSocketAddr (int socket, struct qsockaddr *addr);
int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name);
int WINS_GetAddrFromName (char *name, struct qsockaddr *addr);
int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int WINS_GetSocketPort (struct qsockaddr *addr);
int WINS_SetSocketPort (struct qsockaddr *addr, int port);

View file

@ -1,432 +0,0 @@
/*
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.
*/
// net_wipx.c
#include "quakedef.h"
#include "winquake.h"
#include <wsipx.h>
#include "net_wipx.h"
extern cvar_t hostname;
#define MAXHOSTNAMELEN 256
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket;
static struct qsockaddr broadcastaddr;
extern qboolean winsock_initialized;
extern WSADATA winsockdata;
#define IPXSOCKETS 18
static int ipxsocket[IPXSOCKETS];
static int sequence[IPXSOCKETS];
//=============================================================================
int WIPX_Init (void)
{
int i;
char buff[MAXHOSTNAMELEN];
struct qsockaddr addr;
char *p;
int r;
WORD wVersionRequested;
if (COM_CheckParm ("-noipx"))
return -1;
// make sure LoadLibrary has happened successfully
if (!winsock_lib_initialized)
return -1;
if (winsock_initialized == 0)
{
wVersionRequested = MAKEWORD(1, 1);
r = pWSAStartup (MAKEWORD(1, 1), &winsockdata);
if (r)
{
Con_Printf ("Winsock initialization failed.\n");
return -1;
}
}
winsock_initialized++;
for (i = 0; i < IPXSOCKETS; i++)
ipxsocket[i] = 0;
// determine my name & address
if (pgethostname(buff, MAXHOSTNAMELEN) == 0)
{
// if the quake hostname isn't set, set it to the machine name
if (strcmp(hostname.string, "UNNAMED") == 0)
{
// see if it's a text IP address (well, close enough)
for (p = buff; *p; p++)
if ((*p < '0' || *p > '9') && *p != '.')
break;
// if it is a real name, strip off the domain; we only want the host
if (*p)
{
for (i = 0; i < 15; i++)
if (buff[i] == '.')
break;
buff[i] = 0;
}
Cvar_Set ("hostname", buff);
}
}
if ((net_controlsocket = WIPX_OpenSocket (0)) == -1)
{
Con_Printf("WIPX_Init: Unable to open control socket\n");
if (--winsock_initialized == 0)
pWSACleanup ();
return -1;
}
((struct sockaddr_ipx *)&broadcastaddr)->sa_family = AF_IPX;
memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_netnum, 0, 4);
memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_nodenum, 0xff, 6);
((struct sockaddr_ipx *)&broadcastaddr)->sa_socket = htons((unsigned short)net_hostport);
WIPX_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_ipx_address, WIPX_AddrToString (&addr));
p = Q_strrchr (my_ipx_address, ':');
if (p)
*p = 0;
Con_Printf("Winsock IPX Initialized\n");
ipxAvailable = true;
return net_controlsocket;
}
//=============================================================================
void WIPX_Shutdown (void)
{
WIPX_Listen (false);
WIPX_CloseSocket (net_controlsocket);
if (--winsock_initialized == 0)
pWSACleanup ();
}
//=============================================================================
void WIPX_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = WIPX_OpenSocket (net_hostport)) == -1)
Sys_Error ("WIPX_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
WIPX_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
int WIPX_OpenSocket (int port)
{
int handle;
int newsocket;
struct sockaddr_ipx address;
u_long _true = 1;
for (handle = 0; handle < IPXSOCKETS; handle++)
if (ipxsocket[handle] == 0)
break;
if (handle == IPXSOCKETS)
return -1;
if ((newsocket = psocket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == INVALID_SOCKET)
return -1;
if (pioctlsocket (newsocket, FIONBIO, &_true) == -1)
goto ErrorReturn;
if (psetsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) < 0)
goto ErrorReturn;
address.sa_family = AF_IPX;
memset(address.sa_netnum, 0, 4);
memset(address.sa_nodenum, 0, 6);;
address.sa_socket = htons((unsigned short)port);
if( bind (newsocket, (void *)&address, sizeof(address)) == 0)
{
ipxsocket[handle] = newsocket;
sequence[handle] = 0;
return handle;
}
Sys_Error ("Winsock IPX bind failed\n");
ErrorReturn:
pclosesocket (newsocket);
return -1;
}
//=============================================================================
int WIPX_CloseSocket (int handle)
{
int socket = ipxsocket[handle];
int ret;
ret = pclosesocket (socket);
ipxsocket[handle] = 0;
return ret;
}
//=============================================================================
int WIPX_Connect (int handle, struct qsockaddr *addr)
{
return 0;
}
//=============================================================================
int WIPX_CheckNewConnections (void)
{
unsigned long available;
if (net_acceptsocket == -1)
return -1;
if (pioctlsocket (ipxsocket[net_acceptsocket], FIONREAD, &available) == -1)
Sys_Error ("WIPX: ioctlsocket (FIONREAD) failed\n");
if (available)
return net_acceptsocket;
return -1;
}
//=============================================================================
static byte packetBuffer[NET_DATAGRAMSIZE + 4];
int WIPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int socket = ipxsocket[handle];
int ret;
ret = precvfrom (socket, packetBuffer, len+4, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1)
{
int errno = pWSAGetLastError();
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
return 0;
}
if (ret < 4)
return 0;
// remove sequence number, it's only needed for DOS IPX
ret -= 4;
memcpy(buf, packetBuffer+4, ret);
return ret;
}
//=============================================================================
int WIPX_Broadcast (int handle, byte *buf, int len)
{
return WIPX_Write (handle, buf, len, &broadcastaddr);
}
//=============================================================================
int WIPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
{
int socket = ipxsocket[handle];
int ret;
// build packet with sequence number
*(int *)(&packetBuffer[0]) = sequence[handle];
sequence[handle]++;
memcpy(&packetBuffer[4], buf, len);
len += 4;
ret = psendto (socket, packetBuffer, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1)
if (pWSAGetLastError() == WSAEWOULDBLOCK)
return 0;
return ret;
}
//=============================================================================
char *WIPX_AddrToString (struct qsockaddr *addr)
{
static char buf[28];
sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
((struct sockaddr_ipx *)addr)->sa_netnum[0] & 0xff,
((struct sockaddr_ipx *)addr)->sa_netnum[1] & 0xff,
((struct sockaddr_ipx *)addr)->sa_netnum[2] & 0xff,
((struct sockaddr_ipx *)addr)->sa_netnum[3] & 0xff,
((struct sockaddr_ipx *)addr)->sa_nodenum[0] & 0xff,
((struct sockaddr_ipx *)addr)->sa_nodenum[1] & 0xff,
((struct sockaddr_ipx *)addr)->sa_nodenum[2] & 0xff,
((struct sockaddr_ipx *)addr)->sa_nodenum[3] & 0xff,
((struct sockaddr_ipx *)addr)->sa_nodenum[4] & 0xff,
((struct sockaddr_ipx *)addr)->sa_nodenum[5] & 0xff,
ntohs(((struct sockaddr_ipx *)addr)->sa_socket)
);
return buf;
}
//=============================================================================
int WIPX_StringToAddr (char *string, struct qsockaddr *addr)
{
int val;
char buf[3];
buf[2] = 0;
Q_memset(addr, 0, sizeof(struct qsockaddr));
addr->sa_family = AF_IPX;
#define DO(src,dest) \
buf[0] = string[src]; \
buf[1] = string[src + 1]; \
if (sscanf (buf, "%x", &val) != 1) \
return -1; \
((struct sockaddr_ipx *)addr)->dest = val
DO(0, sa_netnum[0]);
DO(2, sa_netnum[1]);
DO(4, sa_netnum[2]);
DO(6, sa_netnum[3]);
DO(9, sa_nodenum[0]);
DO(11, sa_nodenum[1]);
DO(13, sa_nodenum[2]);
DO(15, sa_nodenum[3]);
DO(17, sa_nodenum[4]);
DO(19, sa_nodenum[5]);
#undef DO
sscanf (&string[22], "%u", &val);
((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)val);
return 0;
}
//=============================================================================
int WIPX_GetSocketAddr (int handle, struct qsockaddr *addr)
{
int socket = ipxsocket[handle];
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
Q_memset(addr, 0, sizeof(struct qsockaddr));
if(pgetsockname(socket, (struct sockaddr *)addr, &addrlen) != 0)
{
int errno = pWSAGetLastError();
}
return 0;
}
//=============================================================================
int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
Q_strcpy(name, WIPX_AddrToString(addr));
return 0;
}
//=============================================================================
int WIPX_GetAddrFromName(char *name, struct qsockaddr *addr)
{
int n;
char buf[32];
n = Q_strlen(name);
if (n == 12)
{
sprintf(buf, "00000000:%s:%u", name, net_hostport);
return WIPX_StringToAddr (buf, addr);
}
if (n == 21)
{
sprintf(buf, "%s:%u", name, net_hostport);
return WIPX_StringToAddr (buf, addr);
}
if (n > 21 && n <= 27)
return WIPX_StringToAddr (name, addr);
return -1;
}
//=============================================================================
int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if (*((struct sockaddr_ipx *)addr1)->sa_netnum && *((struct sockaddr_ipx *)addr2)->sa_netnum)
if (memcmp(((struct sockaddr_ipx *)addr1)->sa_netnum, ((struct sockaddr_ipx *)addr2)->sa_netnum, 4) != 0)
return -1;
if (memcmp(((struct sockaddr_ipx *)addr1)->sa_nodenum, ((struct sockaddr_ipx *)addr2)->sa_nodenum, 6) != 0)
return -1;
if (((struct sockaddr_ipx *)addr1)->sa_socket != ((struct sockaddr_ipx *)addr2)->sa_socket)
return 1;
return 0;
}
//=============================================================================
int WIPX_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_ipx *)addr)->sa_socket);
}
int WIPX_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)port);
return 0;
}
//=============================================================================

View file

@ -1,39 +0,0 @@
/*
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.
*/
// net_wipx.h
int WIPX_Init (void);
void WIPX_Shutdown (void);
void WIPX_Listen (qboolean state);
int WIPX_OpenSocket (int port);
int WIPX_CloseSocket (int socket);
int WIPX_Connect (int socket, struct qsockaddr *addr);
int WIPX_CheckNewConnections (void);
int WIPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int WIPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int WIPX_Broadcast (int socket, byte *buf, int len);
char *WIPX_AddrToString (struct qsockaddr *addr);
int WIPX_StringToAddr (char *string, struct qsockaddr *addr);
int WIPX_GetSocketAddr (int socket, struct qsockaddr *addr);
int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name);
int WIPX_GetAddrFromName (char *name, struct qsockaddr *addr);
int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int WIPX_GetSocketPort (struct qsockaddr *addr);
int WIPX_SetSocketPort (struct qsockaddr *addr, int port);

View file

View file

@ -1,64 +0,0 @@
/*
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.
*/
//
// nonintel.c: code for non-Intel processors only
//
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
#if !id386
/*
================
R_Surf8Patch
================
*/
void R_Surf8Patch ()
{
// we only patch code on Intel
}
/*
================
R_Surf16Patch
================
*/
void R_Surf16Patch ()
{
// we only patch code on Intel
}
/*
================
R_SurfacePatch
================
*/
void R_SurfacePatch (void)
{
// we only patch code on Intel
}
#endif // !id386

View file

@ -1,280 +0,0 @@
/*
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.
*/
//
// quakeasm.h: general asm header file
//
//#define GLQUAKE 1
#if defined(_WIN32) && !defined(WINDED)
#if defined(_M_IX86)
#define __i386__ 1
#endif
#endif
#ifdef __i386__
#define id386 1
#else
#define id386 0
#endif
// !!! must be kept the same as in d_iface.h !!!
#define TRANSPARENT_COLOR 255
#ifndef NeXT
#ifndef GLQUAKE
.extern C(d_zistepu)
.extern C(d_pzbuffer)
.extern C(d_zistepv)
.extern C(d_zrowbytes)
.extern C(d_ziorigin)
.extern C(r_turb_s)
.extern C(r_turb_t)
.extern C(r_turb_pdest)
.extern C(r_turb_spancount)
.extern C(r_turb_turb)
.extern C(r_turb_pbase)
.extern C(r_turb_sstep)
.extern C(r_turb_tstep)
.extern C(r_bmodelactive)
.extern C(d_sdivzstepu)
.extern C(d_tdivzstepu)
.extern C(d_sdivzstepv)
.extern C(d_tdivzstepv)
.extern C(d_sdivzorigin)
.extern C(d_tdivzorigin)
.extern C(sadjust)
.extern C(tadjust)
.extern C(bbextents)
.extern C(bbextentt)
.extern C(cacheblock)
.extern C(d_viewbuffer)
.extern C(cachewidth)
.extern C(d_pzbuffer)
.extern C(d_zrowbytes)
.extern C(d_zwidth)
.extern C(d_scantable)
.extern C(r_lightptr)
.extern C(r_numvblocks)
.extern C(prowdestbase)
.extern C(pbasesource)
.extern C(r_lightwidth)
.extern C(lightright)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(lightdelta)
.extern C(lightright)
.extern C(lightdelta)
.extern C(sourcetstep)
.extern C(surfrowbytes)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(r_sourcemax)
.extern C(r_stepback)
.extern C(colormap)
.extern C(blocksize)
.extern C(sourcesstep)
.extern C(lightleft)
.extern C(blockdivshift)
.extern C(blockdivmask)
.extern C(lightleftstep)
.extern C(r_origin)
.extern C(r_ppn)
.extern C(r_pup)
.extern C(r_pright)
.extern C(ycenter)
.extern C(xcenter)
.extern C(d_vrectbottom_particle)
.extern C(d_vrectright_particle)
.extern C(d_vrecty)
.extern C(d_vrectx)
.extern C(d_pix_shift)
.extern C(d_pix_min)
.extern C(d_pix_max)
.extern C(d_y_aspect_shift)
.extern C(screenwidth)
.extern C(r_leftclipped)
.extern C(r_leftenter)
.extern C(r_rightclipped)
.extern C(r_rightenter)
.extern C(modelorg)
.extern C(xscale)
.extern C(r_refdef)
.extern C(yscale)
.extern C(r_leftexit)
.extern C(r_rightexit)
.extern C(r_lastvertvalid)
.extern C(cacheoffset)
.extern C(newedges)
.extern C(removeedges)
.extern C(r_pedge)
.extern C(r_framecount)
.extern C(r_u1)
.extern C(r_emitted)
.extern C(edge_p)
.extern C(surface_p)
.extern C(surfaces)
.extern C(r_lzi1)
.extern C(r_v1)
.extern C(r_ceilv1)
.extern C(r_nearzi)
.extern C(r_nearzionly)
.extern C(edge_aftertail)
.extern C(edge_tail)
.extern C(current_iv)
.extern C(edge_head_u_shift20)
.extern C(span_p)
.extern C(edge_head)
.extern C(fv)
.extern C(edge_tail_u_shift20)
.extern C(r_apverts)
.extern C(r_anumverts)
.extern C(aliastransform)
.extern C(r_avertexnormals)
.extern C(r_plightvec)
.extern C(r_ambientlight)
.extern C(r_shadelight)
.extern C(aliasxcenter)
.extern C(aliasycenter)
.extern C(a_sstepxfrac)
.extern C(r_affinetridesc)
.extern C(acolormap)
.extern C(d_pcolormap)
.extern C(r_affinetridesc)
.extern C(d_sfrac)
.extern C(d_ptex)
.extern C(d_pedgespanpackage)
.extern C(d_tfrac)
.extern C(d_light)
.extern C(d_zi)
.extern C(d_pdest)
.extern C(d_pz)
.extern C(d_aspancount)
.extern C(erroradjustup)
.extern C(errorterm)
.extern C(d_xdenom)
.extern C(r_p0)
.extern C(r_p1)
.extern C(r_p2)
.extern C(a_tstepxfrac)
.extern C(r_sstepx)
.extern C(r_tstepx)
.extern C(a_ststepxwhole)
.extern C(zspantable)
.extern C(skintable)
.extern C(r_zistepx)
.extern C(erroradjustdown)
.extern C(d_countextrastep)
.extern C(ubasestep)
.extern C(a_ststepxwhole)
.extern C(a_tstepxfrac)
.extern C(r_lstepx)
.extern C(a_spans)
.extern C(erroradjustdown)
.extern C(d_pdestextrastep)
.extern C(d_pzextrastep)
.extern C(d_sfracextrastep)
.extern C(d_ptexextrastep)
.extern C(d_countextrastep)
.extern C(d_tfracextrastep)
.extern C(d_lightextrastep)
.extern C(d_ziextrastep)
.extern C(d_pdestbasestep)
.extern C(d_pzbasestep)
.extern C(d_sfracbasestep)
.extern C(d_ptexbasestep)
.extern C(ubasestep)
.extern C(d_tfracbasestep)
.extern C(d_lightbasestep)
.extern C(d_zibasestep)
.extern C(zspantable)
.extern C(r_lstepy)
.extern C(r_sstepy)
.extern C(r_tstepy)
.extern C(r_zistepy)
.extern C(D_PolysetSetEdgeTable)
.extern C(D_RasterizeAliasPolySmooth)
.extern float_point5
.extern Float2ToThe31nd
.extern izistep
.extern izi
.extern FloatMinus2ToThe31nd
.extern float_1
.extern float_particle_z_clip
.extern float_minus_1
.extern float_0
.extern fp_16
.extern fp_64k
.extern fp_1m
.extern fp_1m_minus_1
.extern fp_8
.extern entryvec_table
.extern advancetable
.extern sstep
.extern tstep
.extern pspantemp
.extern counttemp
.extern jumptemp
.extern reciprocal_table
.extern DP_Count
.extern DP_u
.extern DP_v
.extern DP_32768
.extern DP_Color
.extern DP_Pix
.extern DP_EntryTable
.extern pbase
.extern s
.extern t
.extern sfracf
.extern tfracf
.extern snext
.extern tnext
.extern spancountminus1
.extern zi16stepu
.extern sdivz16stepu
.extern tdivz16stepu
.extern zi8stepu
.extern sdivz8stepu
.extern tdivz8stepu
.extern reciprocal_table_16
.extern entryvec_table_16
.extern ceil_cw
.extern single_cw
.extern fp_64kx64k
.extern pz
.extern spr8entryvec_table
#endif
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
.extern C(vright)
.extern C(vup)
.extern C(vpn)
.extern C(BOPS_Error)
#endif

View file

@ -85,7 +85,6 @@ extern cvar_t r_lerpmove;
#define DIST_NOT_SET 98765
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct clipplane_s
{
vec3_t normal;
@ -185,7 +184,6 @@ extern model_t *cl_worldmodel;
extern int *pfrustum_indexes[4];
// !!! if this is changed, it must be changed in asm_draw.h too !!!
#define NEAR_CLIP 0.01
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;

View file

@ -68,7 +68,6 @@ extern entity_t *currententity;
#define MINSURFACES NUMSTACKSURFACES
#define MAXSPANS 3000
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct espan_s
{
int u, v, count;
@ -140,7 +139,6 @@ extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
// must be kept in sync
#define ALIAS_XY_CLIP_MASK 0x000F
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct edge_s
{
fixed16_t u;

View file

@ -104,7 +104,6 @@ typedef struct entity_s
} entity_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vrect_t vrect; // subwindow in video for refresh

View file

@ -1,20 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by winquake.rc
//
#define IDS_STRING1 1
#define IDI_ICON2 1
#define IDD_DIALOG1 108
#define IDD_PROGRESS 109
#define IDC_PROGRESS 1000
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 111
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -21,10 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#ifdef _WIN32
#include "winquake.h"
#endif
void S_Play(void);
void S_PlayVol(void);
void S_SoundList(void);

View file

@ -1,653 +0,0 @@
/*
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.
*/
#include "quakedef.h"
#include "dosisms.h"
int BLASTER_GetDMAPos(void);
/*
===============================================================================
GUS SUPPORT
===============================================================================
*/
qboolean GUS_Init (void);
int GUS_GetDMAPos (void);
void GUS_Shutdown (void);
/*
===============================================================================
BLASTER SUPPORT
===============================================================================
*/
short *dma_buffer=0;
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;
int dsp_version;
int dsp_minor_version;
int timeconstant=-1;
void PrintBits (byte 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);
}
void SB_Info_f(void)
{
Con_Printf ("BLASTER=%s\n", getenv("BLASTER"));
Con_Printf("dsp version=%d.%d\n", dsp_version, dsp_minor_version);
Con_Printf("dma=%d\n", dma);
if (timeconstant != -1)
Con_Printf("timeconstant=%d\n", timeconstant);
Con_Printf("dma position:%i\n", BLASTER_GetDMAPos ());
}
// =======================================================================
// Interprets BLASTER variable
// =======================================================================
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.
// ==================================================================
int ResetDSP(void)
{
volatile int i;
dos_outportb(dsp_port + 6, 1);
for (i=65536 ; i ; i--) ;
dos_outportb(dsp_port + 6, 0);
for (i=65536 ; i ; i--)
{
if (!(dos_inportb(dsp_port + 0xe) & 0x80)) continue;
if (dos_inportb(dsp_port + 0xa) == 0xaa) break;
}
if (i) return 0;
else return 1;
}
int ReadDSP(void)
{
while (!(dos_inportb(dsp_port+0xe)&0x80)) ;
return dos_inportb(dsp_port+0xa);
}
void WriteDSP(int val)
{
while ((dos_inportb(dsp_port+0xc)&0x80)) ;
dos_outportb(dsp_port+0xc, val);
}
int ReadMixer(int addr)
{
dos_outportb(mixer_port+4, addr);
return dos_inportb(mixer_port+5);
}
void WriteMixer(int addr, int val)
{
dos_outportb(mixer_port+4, addr);
dos_outportb(mixer_port+5, val);
}
int oldmixervalue;
/*
================
StartSB
================
*/
void StartSB(void)
{
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(shm->speed>>8);
WriteDSP(shm->speed&0xff);
WriteDSP(0xb6); // 16-bit output
WriteDSP(0x30); // stereo
WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
WriteDSP((shm->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++)
dos_inportb(dsp_port+0xe); // ack the dsp
timeconstant = 65536-(256000000/(shm->channels*shm->speed));
WriteDSP(0x40);
WriteDSP(timeconstant>>8);
WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter
WriteDSP(0x48);
WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
WriteDSP((shm->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/(shm->channels*shm->speed));
WriteDSP(0x40);
WriteDSP(timeconstant>>8);
WriteDSP(0x48);
WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
WriteDSP((shm->samples-1) >> 8);
WriteDSP(0x1c); // normal speed 8 bit mono
}
}
static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };
static int mode_reg;
static int flipflop_reg;
static int disable_reg;
static int clear_reg;
/*
================
StartDMA
================
*/
void StartDMA(void)
{
int mode;
int realaddr;
realaddr = ptr2real(dma_buffer);
// 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;
}
dos_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 #
dos_outportb(mode_reg, mode);
// set address
// set page
dos_outportb(page_reg[dma], realaddr >> 16);
if (dma > 3)
{ // address is in words
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(addr_reg[dma], (realaddr>>1) & 0xff);
dos_outportb(addr_reg[dma], (realaddr>>9) & 0xff);
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff);
dos_outportb(count_reg[dma], ((dma_size>>1)-1) >> 8);
}
else
{ // address is in bytes
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(addr_reg[dma], realaddr & 0xff);
dos_outportb(addr_reg[dma], (realaddr>>8) & 0xff);
dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb(count_reg[dma], (dma_size-1) & 0xff);
dos_outportb(count_reg[dma], (dma_size-1) >> 8);
}
dos_outportb(clear_reg, 0); // clear write mask
dos_outportb(disable_reg, dma&~4);
}
/*
==================
BLASTER_Init
Returns false if nothing is found.
==================
*/
qboolean BLASTER_Init(void)
{
int size;
int realaddr;
int rc;
int p;
shm = 0;
rc = 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
shm = &sn;
shm->speed = 11025;
rc = COM_CheckParm("-sspeed");
if (rc)
shm->speed = Q_atoi(com_argv[rc+1]);
// version 4 cards (sb 16) do 16 bit stereo
if (dsp_version >= 4)
{
shm->channels = 2;
shm->samplebits = 16;
}
// version 3 cards (sb pro) do 8 bit stereo
else if (dsp_version == 3)
{
shm->channels = 2;
shm->samplebits = 8;
}
// v2 cards do 8 bit mono
else
{
shm->channels = 1;
shm->samplebits = 8;
}
Cmd_AddCommand("sbinfo", SB_Info_f);
size = 4096;
// allocate 8k and get a 4k-aligned buffer from it
dma_buffer = dos_getmemory(size*2);
if (!dma_buffer)
{
Con_Printf("Couldn't allocate sound dma buffer");
return false;
}
realaddr = ptr2real(dma_buffer);
realaddr = (realaddr + size) & ~(size-1);
dma_buffer = (short *) real2ptr(realaddr);
dma_size = size;
memset(dma_buffer, 0, dma_size);
shm->soundalive = true;
shm->splitbuffer = false;
shm->samples = size/(shm->samplebits/8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
shm->samples = size/(shm->samplebits/8);
StartDMA();
StartSB();
return true;
}
/*
==============
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.
===============
*/
int BLASTER_GetDMAPos(void)
{
int count;
// this function is called often. acknowledge the transfer completions
// all the time so that it loops
if (dsp_version >= 4)
dos_inportb(dsp_port+0xf); // 16 bit audio
else
dos_inportb(dsp_port+0xe); // 8 bit audio
// clear 16-bit reg flip-flop
// load the current dma count register
if (dma < 4)
{
dos_outportb(0xc, 0);
count = dos_inportb(dma*2+1);
count += dos_inportb(dma*2+1) << 8;
if (shm->samplebits == 16)
count /= 2;
count = shm->samples - (count+1);
}
else
{
dos_outportb(0xd8, 0);
count = dos_inportb(0xc0+(dma-4)*4+2);
count += dos_inportb(0xc0+(dma-4)*4+2) << 8;
if (shm->samplebits == 8)
count *= 2;
count = shm->samples - (count+1);
}
// Con_Printf("DMA pos = 0x%x\n", count);
shm->samplepos = count & (shm->samples-1);
return shm->samplepos;
}
/*
==============
BLASTER_Shutdown
Reset the sound device for exiting
===============
*/
void BLASTER_Shutdown(void)
{
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 ();
dos_outportb(disable_reg, dma|4); // disable dma channel
}
/*
===============================================================================
INTERFACE
===============================================================================
*/
typedef enum
{
dma_none,
dma_blaster,
dma_gus
} dmacard_t;
dmacard_t dmacard;
/*
==================
SNDDM_Init
Try to find a sound device to mix for.
Returns false if nothing is found.
Returns true and fills in the "shm" structure with information for the mixer.
==================
*/
qboolean SNDDMA_Init(void)
{
if (GUS_Init ())
{
dmacard = dma_gus;
return true;
}
if (BLASTER_Init ())
{
dmacard = dma_blaster;
return true;
}
dmacard = dma_none;
return false;
}
/*
==============
SNDDMA_GetDMAPos
return the current sample position (in mono samples, not stereo)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
===============
*/
int SNDDMA_GetDMAPos(void)
{
switch (dmacard)
{
case dma_blaster:
return BLASTER_GetDMAPos ();
case dma_gus:
return GUS_GetDMAPos ();
case dma_none:
break;
}
return 0;
}
/*
==============
SNDDMA_Shutdown
Reset the sound device for exiting
===============
*/
void SNDDMA_Shutdown(void)
{
switch (dmacard)
{
case dma_blaster:
BLASTER_Shutdown ();
break;
case dma_gus:
GUS_Shutdown ();
break;
case dma_none:
break;
}
dmacard = dma_none;
return;
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
}

File diff suppressed because it is too large Load diff

View file

@ -1,269 +0,0 @@
/*
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.
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <linux/soundcard.h>
#include <stdio.h>
#include "quakedef.h"
int audio_fd;
int snd_inited;
static int tryrates[] = { 11025, 22051, 44100, 8000 };
qboolean SNDDMA_Init(void)
{
int rc;
int fmt;
int tmp;
int i;
char *s;
struct audio_buf_info info;
int caps;
snd_inited = 0;
// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
audio_fd = open("/dev/dsp", O_RDWR);
if (audio_fd < 0)
{
perror("/dev/dsp");
Con_Printf("Could not open /dev/dsp\n");
return 0;
}
rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not reset /dev/dsp\n");
close(audio_fd);
return 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
{
perror("/dev/dsp");
Con_Printf("Sound driver too old\n");
close(audio_fd);
return 0;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
{
Con_Printf("Sorry but your soundcard can't do this\n");
close(audio_fd);
return 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
{
perror("GETOSPACE");
Con_Printf("Um, can't do GETOSPACE?\n");
close(audio_fd);
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
// set sample bits & speed
s = getenv("QUAKE_SOUND_SAMPLEBITS");
if (s) shm->samplebits = atoi(s);
else if ((i = COM_CheckParm("-sndbits")) != 0)
shm->samplebits = atoi(com_argv[i+1]);
if (shm->samplebits != 16 && shm->samplebits != 8)
{
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
if (fmt & AFMT_S16_LE) shm->samplebits = 16;
else if (fmt & AFMT_U8) shm->samplebits = 8;
}
s = getenv("QUAKE_SOUND_SPEED");
if (s) shm->speed = atoi(s);
else if ((i = COM_CheckParm("-sndspeed")) != 0)
shm->speed = atoi(com_argv[i+1]);
else
{
for (i=0 ; i<sizeof(tryrates)/4 ; i++)
if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
shm->speed = tryrates[i];
}
s = getenv("QUAKE_SOUND_CHANNELS");
if (s) shm->channels = atoi(s);
else if ((i = COM_CheckParm("-sndmono")) != 0)
shm->channels = 1;
else if ((i = COM_CheckParm("-sndstereo")) != 0)
shm->channels = 2;
else shm->channels = 2;
shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8);
shm->submission_chunk = 1;
// memory map the dma buffer
shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal
* info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
if (!shm->buffer || shm->buffer == (unsigned char *)-1)
{
perror("/dev/dsp");
Con_Printf("Could not mmap /dev/dsp\n");
close(audio_fd);
return 0;
}
tmp = 0;
if (shm->channels == 2)
tmp = 1;
rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not set /dev/dsp to stereo=%d", shm->channels);
close(audio_fd);
return 0;
}
if (tmp)
shm->channels = 2;
else
shm->channels = 1;
rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not set /dev/dsp speed to %d", shm->speed);
close(audio_fd);
return 0;
}
if (shm->samplebits == 16)
{
rc = AFMT_S16_LE;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not support 16-bit data. Try 8-bit.\n");
close(audio_fd);
return 0;
}
}
else if (shm->samplebits == 8)
{
rc = AFMT_U8;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not support 8-bit data.\n");
close(audio_fd);
return 0;
}
}
else
{
perror("/dev/dsp");
Con_Printf("%d-bit sound not supported.", shm->samplebits);
close(audio_fd);
return 0;
}
// toggle the trigger & start her up
tmp = 0;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not toggle.\n");
close(audio_fd);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0)
{
perror("/dev/dsp");
Con_Printf("Could not toggle.\n");
close(audio_fd);
return 0;
}
shm->samplepos = 0;
snd_inited = 1;
return 1;
}
int SNDDMA_GetDMAPos(void)
{
struct count_info count;
if (!snd_inited) return 0;
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
{
perror("/dev/dsp");
Con_Printf("Uh, sound dead.\n");
close(audio_fd);
snd_inited = 0;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
shm->samplepos = count.ptr / (shm->samplebits / 8);
return shm->samplepos;
}
void SNDDMA_Shutdown(void)
{
if (snd_inited)
{
close(audio_fd);
snd_inited = 0;
}
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
}

View file

@ -21,11 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#ifdef _WIN32
#include "winquake.h"
#else
#define DWORD unsigned long
#endif
#define PAINTBUFFER_SIZE 512
portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];

View file

@ -1,55 +0,0 @@
/*
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.
*/
#include "quakedef.h"
extern int desired_speed;
extern int desired_bits;
qboolean SNDDMA_Init(void)
{
int size;
size = 16384 + sizeof(dma_t);
shm = malloc (size);
memset((void*)shm, 0, size);
shm->buffer = (char*)shm + sizeof(dma_t);
shm->channels = 2;
shm->speed = desired_speed;
shm->samplebits = desired_bits;
shm->samples = 16384 / (desired_bits / 8);
shm->submission_chunk = 1;
return true;
}
// return the current sample position (in mono samples read)
// inside the recirculating dma buffer
int SNDDMA_GetDMAPos(void)
{
shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1);
return shm->samplepos;
}
void SNDDMA_Shutdown(void)
{
}

View file

@ -1,97 +0,0 @@
/*
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.
*/
// snd_null.c -- include this instead of all the other snd_* files to have
// no sound code whatsoever
#include "quakedef.h"
cvar_t bgmvolume = {"bgmvolume", "1", true};
cvar_t volume = {"volume", "0.7", true};
void S_Init (void)
{
}
void S_AmbientOff (void)
{
}
void S_AmbientOn (void)
{
}
void S_Shutdown (void)
{
}
void S_TouchSound (char *sample)
{
}
void S_ClearBuffer (void)
{
}
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
}
void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
{
}
void S_StopSound (int entnum, int entchannel)
{
}
sfx_t *S_PrecacheSound (char *sample)
{
return NULL;
}
void S_ClearPrecache (void)
{
}
void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
{
}
void S_StopAllSounds (qboolean clear)
{
}
void S_BeginPrecaching (void)
{
}
void S_EndPrecaching (void)
{
}
void S_ExtraUpdate (void)
{
}
void S_LocalSound (char *s)
{
}

View file

@ -1,218 +0,0 @@
/*
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.
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/audioio.h>
#include <errno.h>
#include "quakedef.h"
int audio_fd;
int snd_inited;
static int bufpos;
static int wbufp;
static audio_info_t info;
#define BUFFER_SIZE 8192
unsigned char dma_buffer[BUFFER_SIZE];
unsigned char pend_buffer[BUFFER_SIZE];
int pending;
static int lastwrite = 0;
qboolean SNDDMA_Init(void)
{
int rc;
int fmt;
int tmp;
int i;
char *s;
int caps;
if (snd_inited) {
printf("Sound already init'd\n");
return;
}
shm = &sn;
shm->splitbuffer = 0;
audio_fd = open("/dev/audio", O_WRONLY|O_NDELAY);
if (audio_fd < 0) {
if (errno == EBUSY) {
Con_Printf("Audio device is being used by another process\n");
}
perror("/dev/audio");
Con_Printf("Could not open /dev/audio\n");
return (0);
}
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
perror("/dev/audio");
Con_Printf("Could not communicate with audio device.\n");
close(audio_fd);
return 0;
}
//
// set to nonblock
//
if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
perror("/dev/audio");
close(audio_fd);
return 0;
}
AUDIO_INITINFO(&info);
shm->speed = 11025;
// try 16 bit stereo
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 2;
info.play.precision = 16;
if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 1;
info.play.precision = 16;
if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
Con_Printf("Incapable sound hardware.\n");
close(audio_fd);
return 0;
}
Con_Printf("16 bit mono sound initialized\n");
shm->samplebits = 16;
shm->channels = 1;
} else { // 16 bit stereo
Con_Printf("16 bit stereo sound initialized\n");
shm->samplebits = 16;
shm->channels = 2;
}
shm->soundalive = true;
shm->samples = sizeof(dma_buffer) / (shm->samplebits/8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *)dma_buffer;
snd_inited = 1;
return 1;
}
int SNDDMA_GetDMAPos(void)
{
if (!snd_inited)
return (0);
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
perror("/dev/audio");
Con_Printf("Could not communicate with audio device.\n");
close(audio_fd);
snd_inited = 0;
return (0);
}
return ((info.play.samples*shm->channels) % shm->samples);
}
int SNDDMA_GetSamples(void)
{
if (!snd_inited)
return (0);
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
perror("/dev/audio");
Con_Printf("Could not communicate with audio device.\n");
close(audio_fd);
snd_inited = 0;
return (0);
}
return info.play.samples;
}
void SNDDMA_Shutdown(void)
{
if (snd_inited) {
close(audio_fd);
snd_inited = 0;
}
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
int samps;
int bsize;
int bytes, b;
static unsigned char writebuf[1024];
unsigned char *p;
int idx;
int stop = paintedtime;
extern int soundtime;
if (paintedtime < wbufp)
wbufp = 0; // reset
bsize = shm->channels * (shm->samplebits/8);
bytes = (paintedtime - wbufp) * bsize;
if (!bytes)
return;
if (bytes > sizeof(writebuf)) {
bytes = sizeof(writebuf);
stop = wbufp + bytes/bsize;
}
p = writebuf;
idx = (wbufp*bsize) & (BUFFER_SIZE - 1);
for (b = bytes; b; b--) {
*p++ = dma_buffer[idx];
idx = (idx + 1) & (BUFFER_SIZE - 1);
}
wbufp = stop;
if (write(audio_fd, writebuf, bytes) < bytes)
printf("audio can't keep up!\n");
}

View file

@ -1,729 +0,0 @@
/*
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.
*/
#include "quakedef.h"
#include "winquake.h"
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
// 64K is > 1 second at 16-bit, 22050 Hz
#define WAV_BUFFERS 64
#define WAV_MASK 0x3F
#define WAV_BUFFER_SIZE 0x0400
#define SECONDARY_BUFFER_SIZE 0x10000
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
static qboolean wavonly;
static qboolean dsound_init;
static qboolean wav_init;
static qboolean snd_firsttime = true, snd_isdirect, snd_iswave;
static qboolean primary_format_set;
static int sample16;
static int snd_sent, snd_completed;
/*
* Global variables. Must be visible to window-procedure function
* so it can unlock and free the data block after it has been played.
*/
HANDLE hData;
HPSTR lpData, lpData2;
HGLOBAL hWaveHdr;
LPWAVEHDR lpWaveHdr;
HWAVEOUT hWaveOut;
WAVEOUTCAPS wavecaps;
DWORD gSndBufSize;
MMTIME mmstarttime;
LPDIRECTSOUND pDS;
LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
HINSTANCE hInstDS;
qboolean SNDDMA_InitDirect (void);
qboolean SNDDMA_InitWav (void);
/*
==================
S_BlockSound
==================
*/
void S_BlockSound (void)
{
// DirectSound takes care of blocking itself
if (snd_iswave)
{
snd_blocked++;
if (snd_blocked == 1)
{
waveOutReset (hWaveOut);
}
}
}
/*
==================
S_UnblockSound
==================
*/
void S_UnblockSound (void)
{
// DirectSound takes care of blocking itself
if (snd_iswave)
{
snd_blocked--;
}
}
/*
==================
FreeSound
==================
*/
void FreeSound (void)
{
int i;
if (pDSBuf)
{
pDSBuf->lpVtbl->Stop(pDSBuf);
pDSBuf->lpVtbl->Release(pDSBuf);
}
// only release primary buffer if it's not also the mixing buffer we just released
if (pDSPBuf && (pDSBuf != pDSPBuf))
{
pDSPBuf->lpVtbl->Release(pDSPBuf);
}
if (pDS)
{
pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL);
pDS->lpVtbl->Release(pDS);
}
if (hWaveOut)
{
waveOutReset (hWaveOut);
if (lpWaveHdr)
{
for (i=0 ; i< WAV_BUFFERS ; i++)
waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
}
waveOutClose (hWaveOut);
if (hWaveHdr)
{
GlobalUnlock(hWaveHdr);
GlobalFree(hWaveHdr);
}
if (hData)
{
GlobalUnlock(hData);
GlobalFree(hData);
}
}
pDS = NULL;
pDSBuf = NULL;
pDSPBuf = NULL;
hWaveOut = 0;
hData = 0;
hWaveHdr = 0;
lpData = NULL;
lpWaveHdr = NULL;
dsound_init = false;
wav_init = false;
}
/*
==================
SNDDMA_InitDirect
Direct-Sound support
==================
*/
sndinitstat SNDDMA_InitDirect (void)
{
DSBUFFERDESC dsbuf;
DSBCAPS dsbcaps;
DWORD dwSize, dwWrite;
DSCAPS dscaps;
WAVEFORMATEX format, pformat;
HRESULT hresult;
int reps;
memset ((void *)&sn, 0, sizeof (sn));
shm = &sn;
shm->channels = 2;
shm->samplebits = 16;
shm->speed = 11025;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = shm->channels;
format.wBitsPerSample = shm->samplebits;
format.nSamplesPerSec = shm->speed;
format.nBlockAlign = format.nChannels
*format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec
*format.nBlockAlign;
if (!hInstDS)
{
hInstDS = LoadLibrary("dsound.dll");
if (hInstDS == NULL)
{
Con_SafePrintf ("Couldn't load dsound.dll\n");
return SIS_FAILURE;
}
pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
if (!pDirectSoundCreate)
{
Con_SafePrintf ("Couldn't get DS proc addr\n");
return SIS_FAILURE;
}
}
while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK)
{
if (hresult != DSERR_ALLOCATED)
{
Con_SafePrintf ("DirectSound create failed\n");
return SIS_FAILURE;
}
if (MessageBox (NULL,
"The sound hardware is in use by another app.\n\n"
"Select Retry to try to start sound again or Cancel to run Quake with no sound.",
"Sound not available",
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
{
Con_SafePrintf ("DirectSoundCreate failure\n"
" hardware already in use\n");
return SIS_NOTAVAIL;
}
}
dscaps.dwSize = sizeof(dscaps);
if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps))
{
Con_SafePrintf ("Couldn't get DS caps\n");
}
if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
{
Con_SafePrintf ("No DirectSound driver installed\n");
FreeSound ();
return SIS_FAILURE;
}
if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE))
{
Con_SafePrintf ("Set coop level failed\n");
FreeSound ();
return SIS_FAILURE;
}
// get access to the primary buffer, if possible, so we can set the
// sound hardware format
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbuf.dwBufferBytes = 0;
dsbuf.lpwfxFormat = NULL;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
primary_format_set = false;
if (!COM_CheckParm ("-snoforceformat"))
{
if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
{
pformat = format;
if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat))
{
if (snd_firsttime)
Con_SafePrintf ("Set primary sound buffer format: no\n");
}
else
{
if (snd_firsttime)
Con_SafePrintf ("Set primary sound buffer format: yes\n");
primary_format_set = true;
}
}
}
if (!primary_format_set || !COM_CheckParm ("-primarysound"))
{
// create the secondary buffer we'll actually work with
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
dsbuf.lpwfxFormat = &format;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL))
{
Con_SafePrintf ("DS:CreateSoundBuffer Failed");
FreeSound ();
return SIS_FAILURE;
}
shm->channels = format.nChannels;
shm->samplebits = format.wBitsPerSample;
shm->speed = format.nSamplesPerSec;
if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps))
{
Con_SafePrintf ("DS:GetCaps failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (snd_firsttime)
Con_SafePrintf ("Using secondary sound buffer\n");
}
else
{
if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY))
{
Con_SafePrintf ("Set coop level failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps))
{
Con_Printf ("DS:GetCaps failed\n");
return SIS_FAILURE;
}
pDSBuf = pDSPBuf;
Con_SafePrintf ("Using primary sound buffer\n");
}
// Make sure mixer is active
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
if (snd_firsttime)
Con_SafePrintf(" %d channel(s)\n"
" %d bits/sample\n"
" %d bytes/sec\n",
shm->channels, shm->samplebits, shm->speed);
gSndBufSize = dsbcaps.dwBufferBytes;
// initialize the buffer
reps = 0;
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (++reps > 10000)
{
Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
FreeSound ();
return SIS_FAILURE;
}
}
memset(lpData, 0, dwSize);
// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging
pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0);
/* we don't want anyone to access the buffer directly w/o locking it first. */
lpData = NULL;
pDSBuf->lpVtbl->Stop(pDSBuf);
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite);
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
shm->soundalive = true;
shm->splitbuffer = false;
shm->samples = gSndBufSize/(shm->samplebits/8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) lpData;
sample16 = (shm->samplebits/8) - 1;
dsound_init = true;
return SIS_SUCCESS;
}
/*
==================
SNDDM_InitWav
Crappy windows multimedia base
==================
*/
qboolean SNDDMA_InitWav (void)
{
WAVEFORMATEX format;
int i;
HRESULT hr;
snd_sent = 0;
snd_completed = 0;
shm = &sn;
shm->channels = 2;
shm->samplebits = 16;
shm->speed = 11025;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = shm->channels;
format.wBitsPerSample = shm->samplebits;
format.nSamplesPerSec = shm->speed;
format.nBlockAlign = format.nChannels
*format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec
*format.nBlockAlign;
/* Open a waveform device for output using window callback. */
while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
&format,
0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR)
{
if (hr != MMSYSERR_ALLOCATED)
{
Con_SafePrintf ("waveOutOpen failed\n");
return false;
}
if (MessageBox (NULL,
"The sound hardware is in use by another app.\n\n"
"Select Retry to try to start sound again or Cancel to run Quake with no sound.",
"Sound not available",
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
{
Con_SafePrintf ("waveOutOpen failure;\n"
" hardware already in use\n");
return false;
}
}
/*
* Allocate and lock memory for the waveform data. The memory
* for waveform data must be globally allocated with
* GMEM_MOVEABLE and GMEM_SHARE flags.
*/
gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE;
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize);
if (!hData)
{
Con_SafePrintf ("Sound: Out of memory.\n");
FreeSound ();
return false;
}
lpData = GlobalLock(hData);
if (!lpData)
{
Con_SafePrintf ("Sound: Failed to lock.\n");
FreeSound ();
return false;
}
memset (lpData, 0, gSndBufSize);
/*
* Allocate and lock memory for the header. This memory must
* also be globally allocated with GMEM_MOVEABLE and
* GMEM_SHARE flags.
*/
hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
(DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);
if (hWaveHdr == NULL)
{
Con_SafePrintf ("Sound: Failed to Alloc header.\n");
FreeSound ();
return false;
}
lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
if (lpWaveHdr == NULL)
{
Con_SafePrintf ("Sound: Failed to lock header.\n");
FreeSound ();
return false;
}
memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
/* After allocation, set up and prepare headers. */
for (i=0 ; i<WAV_BUFFERS ; i++)
{
lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
lpWaveHdr[i].lpData = lpData + i*WAV_BUFFER_SIZE;
if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) !=
MMSYSERR_NOERROR)
{
Con_SafePrintf ("Sound: failed to prepare wave headers\n");
FreeSound ();
return false;
}
}
shm->soundalive = true;
shm->splitbuffer = false;
shm->samples = gSndBufSize/(shm->samplebits/8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) lpData;
sample16 = (shm->samplebits/8) - 1;
wav_init = true;
return true;
}
/*
==================
SNDDMA_Init
Try to find a sound device to mix for.
Returns false if nothing is found.
==================
*/
int SNDDMA_Init(void)
{
sndinitstat stat;
if (COM_CheckParm ("-wavonly"))
wavonly = true;
dsound_init = wav_init = 0;
stat = SIS_FAILURE; // assume DirectSound won't initialize
/* Init DirectSound */
if (!wavonly)
{
if (snd_firsttime || snd_isdirect)
{
stat = SNDDMA_InitDirect ();;
if (stat == SIS_SUCCESS)
{
snd_isdirect = true;
if (snd_firsttime)
Con_SafePrintf ("DirectSound initialized\n");
}
else
{
snd_isdirect = false;
Con_SafePrintf ("DirectSound failed to init\n");
}
}
}
// if DirectSound didn't succeed in initializing, try to initialize
// waveOut sound, unless DirectSound failed because the hardware is
// already allocated (in which case the user has already chosen not
// to have sound)
if (!dsound_init && (stat != SIS_NOTAVAIL))
{
if (snd_firsttime || snd_iswave)
{
snd_iswave = SNDDMA_InitWav ();
if (snd_iswave)
{
if (snd_firsttime)
Con_SafePrintf ("Wave sound initialized\n");
}
else
{
Con_SafePrintf ("Wave sound failed to init\n");
}
}
}
snd_firsttime = false;
if (!dsound_init && !wav_init)
{
if (snd_firsttime)
Con_SafePrintf ("No sound device initialized\n");
return 0;
}
return 1;
}
/*
==============
SNDDMA_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.
===============
*/
int SNDDMA_GetDMAPos(void)
{
MMTIME mmtime;
int s;
DWORD dwWrite;
if (dsound_init)
{
mmtime.wType = TIME_SAMPLES;
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
s = mmtime.u.sample - mmstarttime.u.sample;
}
else if (wav_init)
{
s = snd_sent * WAV_BUFFER_SIZE;
}
s >>= sample16;
s &= (shm->samples-1);
return s;
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
LPWAVEHDR h;
int wResult;
if (!wav_init)
return;
//
// find which sound blocks have completed
//
while (1)
{
if ( snd_completed == snd_sent )
{
Con_DPrintf ("Sound overrun\n");
break;
}
if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) )
{
break;
}
snd_completed++; // this buffer has been played
}
//
// submit two new sound blocks
//
while (((snd_sent - snd_completed) >> sample16) < 4)
{
h = lpWaveHdr + ( snd_sent&WAV_MASK );
snd_sent++;
/*
* Now the data block can be sent to the output device. The
* waveOutWrite function returns immediately and waveform
* data is sent to the output device in the background.
*/
wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR));
if (wResult != MMSYSERR_NOERROR)
{
Con_SafePrintf ("Failed to write block to device\n");
FreeSound ();
return;
}
}
}
/*
==============
SNDDMA_Shutdown
Reset the sound device for exiting
===============
*/
void SNDDMA_Shutdown(void)
{
FreeSound ();
}

View file

@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define DEFAULT_SOUND_PACKET_VOLUME 255
#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
// !!! if this is changed, it much be changed in asm_i386.h too !!!
typedef struct
{
int left;
@ -38,7 +37,6 @@ typedef struct sfx_s
cache_user_t cache;
} sfx_t;
// !!! if this is changed, it much be changed in asm_i386.h too !!!
typedef struct
{
int length;
@ -63,7 +61,6 @@ typedef struct
unsigned char *buffer;
} dma_t;
// !!! if this is changed, it much be changed in asm_i386.h too !!!
typedef struct
{
sfx_t *sfx; // sfx number

View file

@ -1,953 +0,0 @@
/*
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.
*/
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <dir.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <dpmi.h>
#include <sys/nearptr.h>
#include <conio.h>
#include "quakedef.h"
#include "dosisms.h"
#define MINIMUM_WIN_MEMORY 0x800000
#define MINIMUM_WIN_MEMORY_LEVELPAK (MINIMUM_WIN_MEMORY + 0x100000)
int end_of_memory;
qboolean lockmem, lockunlockmem, unlockmem;
static int win95;
#define STDOUT 1
#define KEYBUF_SIZE 256
static unsigned char keybuf[KEYBUF_SIZE];
static int keybuf_head=0;
static int keybuf_tail=0;
static quakeparms_t quakeparms;
int sys_checksum;
static double curtime = 0.0;
static double lastcurtime = 0.0;
static double oldtime = 0.0;
static qboolean isDedicated;
static int minmem;
float fptest_temp;
extern char start_of_memory __asm__("start");
//=============================================================================
// this is totally dependent on cwsdpmi putting the stack right after tge
// global data
// This does evil things in a Win95 DOS box!!!
#if 0
extern byte end;
#define CHECKBYTE 0xed
void Sys_InitStackCheck (void)
{
int i;
for (i=0 ; i<128*1024 ; i++)
(&end)[i] = CHECKBYTE;
}
void Sys_StackCheck (void)
{
int i;
for (i=0 ; i<128*1024 ; i++)
if ( (&end)[i] != CHECKBYTE )
break;
Con_Printf ("%i undisturbed stack bytes\n", i);
if (end != CHECKBYTE)
Sys_Error ("System stack overflow!");
}
#endif
//=============================================================================
byte scantokey[128] =
{
// 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, 9, // 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_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
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
};
byte shiftscantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 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_SHIFT,'|', 'Z', 'X', 'C', 'V', // 2
'B', 'N', 'M', '<', '>', '?', K_SHIFT,'*',
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 TrapKey(void)
{
// static int ctrl=0;
keybuf[keybuf_head] = dos_inportb(0x60);
dos_outportb(0x20, 0x20);
/*
if (scantokey[keybuf[keybuf_head]&0x7f] == K_CTRL)
ctrl=keybuf[keybuf_head]&0x80;
if (ctrl && scantokey[keybuf[keybuf_head]&0x7f] == 'c')
Sys_Error("ctrl-c hit\n");
*/
keybuf_head = (keybuf_head + 1) & (KEYBUF_SIZE-1);
}
#define SC_UPARROW 0x48
#define SC_DOWNARROW 0x50
#define SC_LEFTARROW 0x4b
#define SC_RIGHTARROW 0x4d
#define SC_LEFTSHIFT 0x2a
#define SC_RIGHTSHIFT 0x36
#define SC_RIGHTARROW 0x4d
void MaskExceptions (void);
void Sys_InitFloatTime (void);
void Sys_PushFPCW_SetHigh (void);
void Sys_PopFPCW (void);
#define LEAVE_FOR_CACHE (512*1024) //FIXME: tune
#define LOCKED_FOR_MALLOC (128*1024) //FIXME: tune
void Sys_DetectWin95 (void)
{
__dpmi_regs r;
r.x.ax = 0x160a; /* Get Windows Version */
__dpmi_int(0x2f, &r);
if(r.x.ax || r.h.bh < 4) /* Not windows or earlier than Win95 */
{
win95 = 0;
lockmem = true;
lockunlockmem = false;
unlockmem = true;
}
else
{
win95 = 1;
lockunlockmem = COM_CheckParm ("-winlockunlock");
if (lockunlockmem)
lockmem = true;
else
lockmem = COM_CheckParm ("-winlock");
unlockmem = lockmem && !lockunlockmem;
}
}
void *dos_getmaxlockedmem(int *size)
{
__dpmi_free_mem_info meminfo;
__dpmi_meminfo info;
int working_size;
void *working_memory;
int last_locked;
int extra, i, j, allocsize;
static char *msg = "Locking data...";
int m, n;
byte *x;
// first lock all the current executing image so the locked count will
// be accurate. It doesn't hurt to lock the memory multiple times
last_locked = __djgpp_selector_limit + 1;
info.size = last_locked - 4096;
info.address = __djgpp_base_address + 4096;
if (lockmem)
{
if(__dpmi_lock_linear_region(&info))
{
Sys_Error ("Lock of current memory at 0x%lx for %ldKb failed!\n",
info.address, info.size/1024);
}
}
__dpmi_get_free_memory_information(&meminfo);
if (!win95) /* Not windows or earlier than Win95 */
{
working_size = meminfo.maximum_locked_page_allocation_in_pages * 4096;
}
else
{
working_size = meminfo.largest_available_free_block_in_bytes -
LEAVE_FOR_CACHE;
}
working_size &= ~0xffff; /* Round down to 64K */
working_size += 0x10000;
do
{
working_size -= 0x10000; /* Decrease 64K and try again */
working_memory = sbrk(working_size);
} while (working_memory == (void *)-1);
extra = 0xfffc - ((unsigned)sbrk(0) & 0xffff);
if (extra > 0)
{
sbrk(extra);
working_size += extra;
}
// now grab the memory
info.address = last_locked + __djgpp_base_address;
if (!win95)
{
info.size = __djgpp_selector_limit + 1 - last_locked;
while (info.size > 0 && __dpmi_lock_linear_region(&info))
{
info.size -= 0x1000;
working_size -= 0x1000;
sbrk(-0x1000);
}
}
else
{ /* Win95 section */
j = COM_CheckParm("-winmem");
if (standard_quake)
minmem = MINIMUM_WIN_MEMORY;
else
minmem = MINIMUM_WIN_MEMORY_LEVELPAK;
if (j)
{
allocsize = ((int)(Q_atoi(com_argv[j+1]))) * 0x100000 +
LOCKED_FOR_MALLOC;
if (allocsize < (minmem + LOCKED_FOR_MALLOC))
allocsize = minmem + LOCKED_FOR_MALLOC;
}
else
{
allocsize = minmem + LOCKED_FOR_MALLOC;
}
if (!lockmem)
{
// we won't lock, just sbrk the memory
info.size = allocsize;
goto UpdateSbrk;
}
// lock the memory down
write (STDOUT, msg, strlen (msg));
for (j=allocsize ; j>(minmem + LOCKED_FOR_MALLOC) ;
j -= 0x100000)
{
info.size = j;
if (!__dpmi_lock_linear_region(&info))
goto Locked;
write (STDOUT, ".", 1);
}
// finally, try with the absolute minimum amount
for (i=0 ; i<10 ; i++)
{
info.size = minmem + LOCKED_FOR_MALLOC;
if (!__dpmi_lock_linear_region(&info))
goto Locked;
}
Sys_Error ("Can't lock memory; %d Mb lockable RAM required. "
"Try shrinking smartdrv.", info.size / 0x100000);
Locked:
UpdateSbrk:
info.address += info.size;
info.address -= __djgpp_base_address + 4; // ending point, malloc align
working_size = info.address - (int)working_memory;
sbrk(info.address-(int)sbrk(0)); // negative adjustment
}
if (lockunlockmem)
{
__dpmi_unlock_linear_region (&info);
printf ("Locked and unlocked %d Mb data\n", working_size / 0x100000);
}
else if (lockmem)
{
printf ("Locked %d Mb data\n", working_size / 0x100000);
}
else
{
printf ("Allocated %d Mb data\n", working_size / 0x100000);
}
// touch all the memory to make sure it's there. The 16-page skip is to
// keep Win 95 from thinking we're trying to page ourselves in (we are
// doing that, of course, but there's no reason we shouldn't)
x = (byte *)working_memory;
for (n=0 ; n<4 ; n++)
{
for (m=0 ; m<(working_size - 16 * 0x1000) ; m += 4)
{
sys_checksum += *(int *)&x[m];
sys_checksum += *(int *)&x[m + 16 * 0x1000];
}
}
// give some of what we locked back for malloc before returning. Done
// by cheating and passing a negative value to sbrk
working_size -= LOCKED_FOR_MALLOC;
sbrk( -(LOCKED_FOR_MALLOC));
*size = working_size;
return working_memory;
}
/*
============
Sys_FileTime
returns -1 if not present
============
*/
int Sys_FileTime (char *path)
{
struct stat buf;
if (stat (path,&buf) == -1)
return -1;
return buf.st_mtime;
}
void Sys_mkdir (char *path)
{
mkdir (path, 0777);
}
void Sys_Sleep(void)
{
}
char *Sys_ConsoleInput(void)
{
static char text[256];
static int len = 0;
char ch;
if (!isDedicated)
return NULL;
if (! kbhit())
return NULL;
ch = getche();
switch (ch)
{
case '\r':
putch('\n');
if (len)
{
text[len] = 0;
len = 0;
return text;
}
break;
case '\b':
putch(' ');
if (len)
{
len--;
putch('\b');
}
break;
default:
text[len] = ch;
len = (len + 1) & 0xff;
break;
}
return NULL;
}
void Sys_Init(void)
{
MaskExceptions ();
Sys_SetFPCW ();
dos_outportb(0x43, 0x34); // set system timer to mode 2
dos_outportb(0x40, 0); // for the Sys_FloatTime() function
dos_outportb(0x40, 0);
Sys_InitFloatTime ();
_go32_interrupt_stack_size = 4 * 1024;;
_go32_rmcb_stack_size = 4 * 1024;
}
void Sys_Shutdown(void)
{
if (!isDedicated)
dos_restoreintr(9);
if (unlockmem)
{
dos_unlockmem (&start_of_memory,
end_of_memory - (int)&start_of_memory);
dos_unlockmem (quakeparms.membase, quakeparms.memsize);
}
}
#define SC_RSHIFT 0x36
#define SC_LSHIFT 0x2a
void Sys_SendKeyEvents (void)
{
int k, next;
int outkey;
// get key events
while (keybuf_head != keybuf_tail)
{
k = keybuf[keybuf_tail++];
keybuf_tail &= (KEYBUF_SIZE-1);
if (k==0xe0)
continue; // special / pause keys
next = keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)];
if (next == 0xe1)
continue; // pause key bullshit
if (k==0xc5 && next == 0x9d)
{
Key_Event (K_PAUSE, true);
continue;
}
// extended keyboard shift key bullshit
if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
{
if ( keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]==0xe0 )
continue;
k &= 0x80;
k |= SC_RSHIFT;
}
if (k==0xc5 && keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)] == 0x9d)
continue; // more pause bullshit
outkey = scantokey[k & 0x7f];
if (k & 0x80)
Key_Event (outkey, false);
else
Key_Event (outkey, true);
}
}
// =======================================================================
// General routines
// =======================================================================
/*
================
Sys_Printf
================
*/
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
if (cls.state == ca_dedicated)
fprintf(stderr, "%s", text);
}
void Sys_AtExit (void)
{
// shutdown only once (so Sys_Error can call this function to shutdown, then
// print the error message, then call exit without exit calling this function
// again)
Sys_Shutdown();
}
void Sys_Quit (void)
{
byte screen[80*25*2];
byte *d;
char ver[6];
int i;
// load the sell screen before shuting everything down
if (registered.value)
d = COM_LoadHunkFile ("end2.bin");
else
d = COM_LoadHunkFile ("end1.bin");
if (d)
memcpy (screen, d, sizeof(screen));
// write the version number directly to the end screen
sprintf (ver, " v%4.2f", VERSION);
for (i=0 ; i<6 ; i++)
screen[0*80*2 + 72*2 + i*2] = ver[i];
Host_Shutdown();
// do the text mode sell screen
if (d)
{
memcpy ((void *)real2ptr(0xb8000), screen,80*25*2);
// set text pos
regs.x.ax = 0x0200;
regs.h.bh = 0;
regs.h.dl = 0;
regs.h.dh = 22;
dos_int86 (0x10);
}
else
printf ("couldn't load endscreen.\n");
exit(0);
}
void Sys_Error (char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
Host_Shutdown();
fprintf(stderr, "Error: %s\n", string);
// Sys_AtExit is called by exit to shutdown the system
exit(0);
}
int Sys_FileOpenRead (char *path, int *handle)
{
int h;
struct stat fileinfo;
h = open (path, O_RDONLY|O_BINARY, 0666);
*handle = h;
if (h == -1)
return -1;
if (fstat (h,&fileinfo) == -1)
Sys_Error ("Error fstating %s", path);
return fileinfo.st_size;
}
int Sys_FileOpenWrite (char *path)
{
int handle;
umask (0);
handle = open(path,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
, 0666);
if (handle == -1)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
return handle;
}
void Sys_FileClose (int handle)
{
close (handle);
}
void Sys_FileSeek (int handle, int position)
{
lseek (handle, position, SEEK_SET);
}
int Sys_FileRead (int handle, void *dest, int count)
{
return read (handle, dest, count);
}
int Sys_FileWrite (int handle, void *data, int count)
{
return write (handle, data, count);
}
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
// it's always writeable
}
/*
================
Sys_FloatTime
================
*/
double Sys_FloatTime (void)
{
int r;
unsigned t, tick;
double ft, time;
static int sametimecount;
Sys_PushFPCW_SetHigh ();
//{static float t = 0; t=t+0.05; return t;} // DEBUG
t = *(unsigned short*)real2ptr(0x46c) * 65536;
dos_outportb(0x43, 0); // latch time
r = dos_inportb(0x40);
r |= dos_inportb(0x40) << 8;
r = (r-1) & 0xffff;
tick = *(unsigned short*)real2ptr(0x46c) * 65536;
if ((tick != t) && (r & 0x8000))
t = tick;
ft = (double) (t+(65536-r)) / 1193200.0;
time = ft - oldtime;
oldtime = ft;
if (time < 0)
{
if (time > -3000.0)
time = 0.0;
else
time += 3600.0;
}
curtime += time;
if (curtime == lastcurtime)
{
sametimecount++;
if (sametimecount > 100000)
{
curtime += 1.0;
sametimecount = 0;
}
}
else
{
sametimecount = 0;
}
lastcurtime = curtime;
Sys_PopFPCW ();
return curtime;
}
/*
================
Sys_InitFloatTime
================
*/
void Sys_InitFloatTime (void)
{
int j;
Sys_FloatTime ();
oldtime = curtime;
j = COM_CheckParm("-starttime");
if (j)
{
curtime = (double) (Q_atof(com_argv[j+1]));
}
else
{
curtime = 0.0;
}
lastcurtime = curtime;
}
/*
================
Sys_GetMemory
================
*/
void Sys_GetMemory(void)
{
int j, tsize;
j = COM_CheckParm("-mem");
if (j)
{
quakeparms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
quakeparms.membase = malloc (quakeparms.memsize);
}
else
{
quakeparms.membase = dos_getmaxlockedmem (&quakeparms.memsize);
}
fprintf(stderr, "malloc'd: %d\n", quakeparms.memsize);
if (COM_CheckParm ("-heapsize"))
{
tsize = Q_atoi (com_argv[COM_CheckParm("-heapsize") + 1]) * 1024;
if (tsize < quakeparms.memsize)
quakeparms.memsize = tsize;
}
}
/*
================
Sys_PageInProgram
walks the text, data, and bss to make sure it's all paged in so that the
actual physical memory detected by Sys_GetMemory is correct.
================
*/
void Sys_PageInProgram(void)
{
int i, j;
end_of_memory = (int)sbrk(0);
if (lockmem)
{
if (dos_lockmem ((void *)&start_of_memory,
end_of_memory - (int)&start_of_memory))
Sys_Error ("Couldn't lock text and data");
}
if (lockunlockmem)
{
dos_unlockmem((void *)&start_of_memory,
end_of_memory - (int)&start_of_memory);
printf ("Locked and unlocked %d Mb image\n",
(end_of_memory - (int)&start_of_memory) / 0x100000);
}
else if (lockmem)
{
printf ("Locked %d Mb image\n",
(end_of_memory - (int)&start_of_memory) / 0x100000);
}
else
{
printf ("Loaded %d Mb image\n",
(end_of_memory - (int)&start_of_memory) / 0x100000);
}
// touch the entire image, doing the 16-page skip so Win95 doesn't think we're
// trying to page ourselves in
for (j=0 ; j<4 ; j++)
{
for(i=(int)&start_of_memory ; i<(end_of_memory - 16 * 0x1000) ; i += 4)
{
sys_checksum += *(int *)i;
sys_checksum += *(int *)(i + 16 * 0x1000);
}
}
}
/*
================
Sys_NoFPUExceptionHandler
================
*/
void Sys_NoFPUExceptionHandler(int whatever)
{
printf ("\nError: Quake requires a floating-point processor\n");
exit (0);
}
/*
================
Sys_DefaultExceptionHandler
================
*/
void Sys_DefaultExceptionHandler(int whatever)
{
}
/*
================
main
================
*/
int main (int c, char **v)
{
double time, oldtime, newtime;
extern void (*dos_error_func)(char *, ...);
static char cwd[1024];
printf ("Quake v%4.2f\n", VERSION);
// make sure there's an FPU
signal(SIGNOFP, Sys_NoFPUExceptionHandler);
signal(SIGABRT, Sys_DefaultExceptionHandler);
signal(SIGALRM, Sys_DefaultExceptionHandler);
signal(SIGKILL, Sys_DefaultExceptionHandler);
signal(SIGQUIT, Sys_DefaultExceptionHandler);
signal(SIGINT, Sys_DefaultExceptionHandler);
if (fptest_temp >= 0.0)
fptest_temp += 0.1;
COM_InitArgv (c, v);
quakeparms.argc = com_argc;
quakeparms.argv = com_argv;
dos_error_func = Sys_Error;
Sys_DetectWin95 ();
Sys_PageInProgram ();
Sys_GetMemory ();
atexit (Sys_AtExit); // in case we crash
getwd (cwd);
if (cwd[Q_strlen(cwd)-1] == '/') cwd[Q_strlen(cwd)-1] = 0;
quakeparms.basedir = cwd; //"f:/quake";
isDedicated = (COM_CheckParm ("-dedicated") != 0);
Sys_Init ();
if (!isDedicated)
dos_registerintr(9, TrapKey);
//Sys_InitStackCheck ();
Host_Init(&quakeparms);
//Sys_StackCheck ();
//Con_Printf ("Top of stack: 0x%x\n", &time);
oldtime = Sys_FloatTime ();
while (1)
{
newtime = Sys_FloatTime ();
time = newtime - oldtime;
if (cls.state == ca_dedicated && (time<sys_ticrate.value))
continue;
Host_Frame (time);
//Sys_StackCheck ();
oldtime = newtime;
}
}

View file

@ -1,457 +0,0 @@
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <errno.h>
#include "quakedef.h"
qboolean isDedicated;
int nostdout = 0;
char *basedir = ".";
char *cachedir = "/tmp";
cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display
// =======================================================================
// General routines
// =======================================================================
void Sys_DebugNumber(int y, int val)
{
}
/*
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
fprintf(stderr, "%s", text);
Con_Print (text);
}
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024], *t_p;
int l, r;
if (nostdout)
return;
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
l = strlen(text);
t_p = text;
// make sure everything goes through, even though we are non-blocking
while (l)
{
r = write (1, text, l);
if (r != l)
sleep (0);
if (r > 0)
{
t_p += r;
l -= r;
}
}
}
*/
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
unsigned char *p;
va_start (argptr,fmt);
vsprintf (text,fmt,argptr);
va_end (argptr);
if (strlen(text) > sizeof(text))
Sys_Error("memory overwrite in Sys_Printf");
if (nostdout)
return;
for (p = (unsigned char *)text; *p; p++) {
*p &= 0x7f;
if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
printf("[%02x]", *p);
else
putc(*p, stdout);
}
}
#if 0
static char end1[] =
"\x1b[?7h\x1b[40m\x1b[2J\x1b[0;1;41m\x1b[1;1H QUAKE: The Doomed Dimension \x1b[33mby \x1b[44mid\x1b[41m Software \x1b[2;1H ---------------------------------------------------------------------------- \x1b[3;1H CALL 1-800-IDGAMES TO ORDER OR FOR TECHNICAL SUPPORT \x1b[4;1H PRICE: $45.00 (PRICES MAY VARY OUTSIDE THE US.) \x1b[5;1H \x1b[6;1H \x1b[37mYes! You only have one fourth of this incredible epic. That is because most \x1b[7;1H of you have paid us nothing or at most, very little. You could steal the \x1b[8;1H game from a friend. But we both know you'll be punished by God if you do. \x1b[9;1H \x1b[33mWHY RISK ETERNAL DAMNATION? CALL 1-800-IDGAMES AND BUY NOW! \x1b[10;1H \x1b[37mRemember, we love you almost as much as He does. \x1b[11;1H \x1b[12;1H \x1b[33mProgramming: \x1b[37mJohn Carmack, Michael Abrash, John Cash \x1b[13;1H \x1b[33mDesign: \x1b[37mJohn Romero, Sandy Petersen, American McGee, Tim Willits \x1b[14;1H \x1b[33mArt: \x1b[37mAdrian Carmack, Kevin Cloud \x1b[15;1H \x1b[33mBiz: \x1b[37mJay Wilbur, Mike Wilson, Donna Jackson \x1b[16;1H \x1b[33mProjects: \x1b[37mShawn Green \x1b[33mSupport: \x1b[37mBarrett Alexander \x1b[17;1H \x1b[33mSound Effects: \x1b[37mTrent Reznor and Nine Inch Nails \x1b[18;1H For other information or details on ordering outside the US, check out the \x1b[19;1H files accompanying QUAKE or our website at http://www.idsoftware.com. \x1b[20;1H \x1b[0;41mQuake is a trademark of Id Software, inc., (c)1996 Id Software, inc. \x1b[21;1H All rights reserved. NIN logo is a registered trademark licensed to \x1b[22;1H Nothing Interactive, Inc. All rights reserved. \x1b[40m\x1b[23;1H\x1b[0m";
static char end2[] =
"\x1b[?7h\x1b[40m\x1b[2J\x1b[0;1;41m\x1b[1;1H QUAKE \x1b[33mby \x1b[44mid\x1b[41m Software \x1b[2;1H ----------------------------------------------------------------------------- \x1b[3;1H \x1b[37mWhy did you quit from the registered version of QUAKE? Did the \x1b[4;1H scary monsters frighten you? Or did Mr. Sandman tug at your \x1b[5;1H little lids? No matter! What is important is you love our \x1b[6;1H game, and gave us your money. Congratulations, you are probably \x1b[7;1H not a thief. \x1b[8;1H Thank You. \x1b[9;1H \x1b[33;44mid\x1b[41m Software is: \x1b[10;1H PROGRAMMING: \x1b[37mJohn Carmack, Michael Abrash, John Cash \x1b[11;1H \x1b[33mDESIGN: \x1b[37mJohn Romero, Sandy Petersen, American McGee, Tim Willits \x1b[12;1H \x1b[33mART: \x1b[37mAdrian Carmack, Kevin Cloud \x1b[13;1H \x1b[33mBIZ: \x1b[37mJay Wilbur, Mike Wilson \x1b[33mPROJECTS MAN: \x1b[37mShawn Green \x1b[14;1H \x1b[33mBIZ ASSIST: \x1b[37mDonna Jackson \x1b[33mSUPPORT: \x1b[37mBarrett Alexander \x1b[15;1H \x1b[33mSOUND EFFECTS AND MUSIC: \x1b[37mTrent Reznor and Nine Inch Nails \x1b[16;1H \x1b[17;1H If you need help running QUAKE refer to the text files in the \x1b[18;1H QUAKE directory, or our website at http://www.idsoftware.com. \x1b[19;1H If all else fails, call our technical support at 1-800-IDGAMES. \x1b[20;1H \x1b[0;41mQuake is a trademark of Id Software, inc., (c)1996 Id Software, inc. \x1b[21;1H All rights reserved. NIN logo is a registered trademark licensed \x1b[22;1H to Nothing Interactive, Inc. All rights reserved. \x1b[23;1H\x1b[40m\x1b[0m";
#endif
void Sys_Quit (void)
{
Host_Shutdown();
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
#if 0
if (registered.value)
printf("%s", end2);
else
printf("%s", end1);
#endif
fflush(stdout);
exit(0);
}
void Sys_Init(void)
{
#if id386
Sys_SetFPCW();
#endif
}
void Sys_Error (char *error, ...)
{
va_list argptr;
char string[1024];
// change stdin to non blocking
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
fprintf(stderr, "Error: %s\n", string);
Host_Shutdown ();
exit (1);
}
void Sys_Warn (char *warning, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,warning);
vsprintf (string,warning,argptr);
va_end (argptr);
fprintf(stderr, "Warning: %s", string);
}
/*
============
Sys_FileTime
returns -1 if not present
============
*/
int Sys_FileTime (char *path)
{
struct stat buf;
if (stat (path,&buf) == -1)
return -1;
return buf.st_mtime;
}
void Sys_mkdir (char *path)
{
mkdir (path, 0777);
}
int Sys_FileOpenRead (char *path, int *handle)
{
int h;
struct stat fileinfo;
h = open (path, O_RDONLY, 0666);
*handle = h;
if (h == -1)
return -1;
if (fstat (h,&fileinfo) == -1)
Sys_Error ("Error fstating %s", path);
return fileinfo.st_size;
}
int Sys_FileOpenWrite (char *path)
{
int handle;
umask (0);
handle = open(path,O_RDWR | O_CREAT | O_TRUNC
, 0666);
if (handle == -1)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
return handle;
}
int Sys_FileWrite (int handle, void *src, int count)
{
return write (handle, src, count);
}
void Sys_FileClose (int handle)
{
close (handle);
}
void Sys_FileSeek (int handle, int position)
{
lseek (handle, position, SEEK_SET);
}
int Sys_FileRead (int handle, void *dest, int count)
{
return read (handle, dest, count);
}
void Sys_DebugLog(char *file, char *fmt, ...)
{
va_list argptr;
static char data[1024];
int fd;
va_start(argptr, fmt);
vsprintf(data, fmt, argptr);
va_end(argptr);
// fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666);
fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
write(fd, data, strlen(data));
close(fd);
}
void Sys_EditFile(char *filename)
{
char cmd[256];
char *term;
char *editor;
term = getenv("TERM");
if (term && !strcmp(term, "xterm"))
{
editor = getenv("VISUAL");
if (!editor)
editor = getenv("EDITOR");
if (!editor)
editor = getenv("EDIT");
if (!editor)
editor = "vi";
sprintf(cmd, "xterm -e %s %s", editor, filename);
system(cmd);
}
}
double Sys_FloatTime (void)
{
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
// =======================================================================
// Sleeps for microseconds
// =======================================================================
static volatile int oktogo;
void alarm_handler(int x)
{
oktogo=1;
}
void Sys_LineRefresh(void)
{
}
void floating_point_exception_handler(int whatever)
{
// Sys_Warn("floating point exception\n");
signal(SIGFPE, floating_point_exception_handler);
}
char *Sys_ConsoleInput(void)
{
static char text[256];
int len;
fd_set fdset;
struct timeval timeout;
if (cls.state == ca_dedicated) {
FD_ZERO(&fdset);
FD_SET(0, &fdset); // stdin
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
return NULL;
len = read (0, text, sizeof(text));
if (len < 1)
return NULL;
text[len-1] = 0; // rip off the /n and terminate
return text;
}
return NULL;
}
#if !id386
void Sys_HighFPPrecision (void)
{
}
void Sys_LowFPPrecision (void)
{
}
#endif
int main (int c, char **v)
{
double time, oldtime, newtime;
quakeparms_t parms;
extern int vcrFile;
extern int recording;
int j;
// static char cwd[1024];
// signal(SIGFPE, floating_point_exception_handler);
signal(SIGFPE, SIG_IGN);
memset(&parms, 0, sizeof(parms));
COM_InitArgv(c, v);
parms.argc = com_argc;
parms.argv = com_argv;
#ifdef GLQUAKE
parms.memsize = 16*1024*1024;
#else
parms.memsize = 8*1024*1024;
#endif
j = COM_CheckParm("-mem");
if (j)
parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
parms.membase = malloc (parms.memsize);
parms.basedir = basedir;
// caching is disabled by default, use -cachedir to enable
// parms.cachedir = cachedir;
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
Host_Init(&parms);
Sys_Init();
if (COM_CheckParm("-nostdout"))
nostdout = 1;
else {
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION);
}
oldtime = Sys_FloatTime () - 0.1;
while (1)
{
// find time spent rendering last frame
newtime = Sys_FloatTime ();
time = newtime - oldtime;
if (cls.state == ca_dedicated)
{ // play vcrfiles at max speed
if (time < sys_ticrate.value && (vcrFile == -1 || recording) )
{
usleep(1);
continue; // not time to run a server only tic yet
}
time = sys_ticrate.value;
}
if (time > sys_ticrate.value*2)
oldtime = newtime;
else
oldtime += time;
Host_Frame (time);
// graphic debugging aids
if (sys_linerefresh.value)
Sys_LineRefresh ();
}
}
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
int r;
unsigned long addr;
int psize = getpagesize();
addr = (startaddr & ~(psize-1)) - psize;
// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
// addr, startaddr+length, length);
r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
if (r < 0)
Sys_Error("Protection change failed\n");
}

View file

@ -1,232 +0,0 @@
/*
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.
*/
// sys_null.h -- null system driver to aid porting efforts
#include "quakedef.h"
#include "errno.h"
/*
===============================================================================
FILE IO
===============================================================================
*/
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i] = f;
*hndl = i;
return filelength(f);
}
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
return i;
}
void Sys_FileClose (int handle)
{
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
}
void Sys_FileSeek (int handle, int position)
{
fseek (sys_handles[handle], position, SEEK_SET);
}
int Sys_FileRead (int handle, void *dest, int count)
{
return fread (dest, 1, count, sys_handles[handle]);
}
int Sys_FileWrite (int handle, void *data, int count)
{
return fwrite (data, 1, count, sys_handles[handle]);
}
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
void Sys_mkdir (char *path)
{
}
/*
===============================================================================
SYSTEM IO
===============================================================================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
}
void Sys_Error (char *error, ...)
{
va_list argptr;
printf ("Sys_Error: ");
va_start (argptr,error);
vprintf (error,argptr);
va_end (argptr);
printf ("\n");
exit (1);
}
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
va_start (argptr,fmt);
vprintf (fmt,argptr);
va_end (argptr);
}
void Sys_Quit (void)
{
exit (0);
}
double Sys_FloatTime (void)
{
static double t;
t += 0.1;
return t;
}
char *Sys_ConsoleInput (void)
{
return NULL;
}
void Sys_Sleep (void)
{
}
void Sys_SendKeyEvents (void)
{
}
void Sys_HighFPPrecision (void)
{
}
void Sys_LowFPPrecision (void)
{
}
//=============================================================================
void main (int argc, char **argv)
{
static quakeparms_t parms;
parms.memsize = 8*1024*1024;
parms.membase = malloc (parms.memsize);
parms.basedir = ".";
COM_InitArgv (argc, argv);
parms.argc = com_argc;
parms.argv = com_argv;
printf ("Host_Init\n");
Host_Init (&parms);
while (1)
{
Host_Frame (0.1);
}
}

View file

@ -1,352 +0,0 @@
/*
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.
*/
// sys_sun.h -- Sun system driver
#include "quakedef.h"
#include "errno.h"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <fcntl.h>
#include <stddef.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
qboolean isDedicated;
/*
===============================================================================
FILE IO
===============================================================================
*/
#define MAX_HANDLES 10
typedef struct
{
FILE *hFile;
char *pMap;
int nLen;
int nPos;
} MEMFILE;
MEMFILE sys_handles[MAX_HANDLES];
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i].hFile)
return i;
Sys_Error ("out of handles");
return -1;
}
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i].hFile = f;
sys_handles[i].nLen = filelength(f);
sys_handles[i].nPos = 0;
sys_handles[i].pMap = mmap( 0, sys_handles[i].nLen, PROT_READ, MAP_SHARED, fileno( sys_handles[i].hFile ), 0 );
if (!sys_handles[i].pMap || (sys_handles[i].pMap == (char *)-1))
{
printf( "mmap %s failed!", path );
sys_handles[i].pMap = NULL;
}
*hndl = i;
return( sys_handles[i].nLen );
}
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i].hFile = f;
sys_handles[i].nLen = 0;
sys_handles[i].nPos = 0;
sys_handles[i].pMap = NULL;
return i;
}
void Sys_FileClose (int handle)
{
if (sys_handles[handle].pMap)
if (munmap( sys_handles[handle].pMap, sys_handles[handle].nLen ) != 0)
printf( "failed to unmap handle %d\n", handle );
fclose (sys_handles[handle].hFile);
sys_handles[handle].hFile = NULL;
}
void Sys_FileSeek (int handle, int position)
{
if (sys_handles[handle].pMap)
{
sys_handles[handle].nPos = position;
}
else fseek (sys_handles[handle].hFile, position, SEEK_SET);
}
int Sys_FileRead (int handle, void *dest, int count)
{
if (sys_handles[handle].pMap)
{
int nPos = sys_handles[handle].nPos;
if (count < 0) count = 0;
if (nPos + count > sys_handles[handle].nLen)
count = sys_handles[handle].nLen - nPos;
memcpy( dest, &sys_handles[handle].pMap[nPos], count );
sys_handles[handle].nPos = nPos + count;
return( count );
}
else return fread (dest, 1, count, sys_handles[handle].hFile);
}
int Sys_FileWrite (int handle, void *data, int count)
{
if (sys_handles[handle].pMap)
Sys_Error( "Attempted to write to read-only file %d!\n", handle );
return fwrite (data, 1, count, sys_handles[handle].hFile);
}
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
void Sys_mkdir (char *path)
{
mkdir( path, 0777 );
}
/*
===============================================================================
SYSTEM IO
===============================================================================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
int r;
unsigned long addr;
int psize = getpagesize();
addr = (startaddr & ~(psize-1)) - psize;
// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
// addr, startaddr+length, length);
r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
if (r < 0)
Sys_Error("Protection change failed\n");
}
void Sys_Error (char *error, ...)
{
va_list argptr;
printf ("Sys_Error: ");
va_start (argptr,error);
vprintf (error,argptr);
va_end (argptr);
printf ("\n");
Host_Shutdown();
exit (1);
}
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
va_start (argptr,fmt);
vprintf (fmt,argptr);
va_end (argptr);
}
void Sys_Quit (void)
{
Host_Shutdown();
exit (0);
}
double Sys_FloatTime (void)
{
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
char *Sys_ConsoleInput (void)
{
static char text[256];
int len;
fd_set readfds;
int ready;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
ready = select(1, &readfds, 0, 0, &timeout);
if (ready>0)
{
len = read (0, text, sizeof(text));
if (len >= 1)
{
text[len-1] = 0; // rip off the /n and terminate
return text;
}
}
return 0;
}
void Sys_Sleep (void)
{
}
#if !id386
void Sys_HighFPPrecision (void)
{
}
void Sys_LowFPPrecision (void)
{
}
#endif
void Sys_Init(void)
{
#if id386
Sys_SetFPCW();
#endif
}
//=============================================================================
int main (int argc, char **argv)
{
static quakeparms_t parms;
float time, oldtime, newtime;
parms.memsize = 16*1024*1024;
parms.membase = malloc (parms.memsize);
parms.basedir = ".";
parms.cachedir = NULL;
COM_InitArgv (argc, argv);
parms.argc = com_argc;
parms.argv = com_argv;
printf ("Host_Init\n");
Host_Init (&parms);
Sys_Init();
// unroll the simulation loop to give the video side a chance to see _vid_default_mode
Host_Frame( 0.1 );
VID_SetDefaultMode();
oldtime = Sys_FloatTime();
while (1)
{
newtime = Sys_FloatTime();
Host_Frame (newtime - oldtime);
oldtime = newtime;
}
return 0;
}

View file

@ -1,893 +0,0 @@
/*
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.
*/
// sys_win.c -- Win32 system interface code
#include "quakedef.h"
#include "winquake.h"
#include "errno.h"
#include "resource.h"
#include "conproc.h"
#define MINIMUM_WIN_MEMORY 0x0880000
#define MAXIMUM_WIN_MEMORY 0x1000000
#define CONSOLE_ERROR_TIMEOUT 60.0 // # of seconds to wait on Sys_Error running
// dedicated before exiting
#define PAUSE_SLEEP 50 // sleep time on pause or minimization
#define NOT_FOCUS_SLEEP 20 // sleep time when not focus
int starttime;
qboolean ActiveApp, Minimized;
qboolean WinNT;
static double pfreq;
static double curtime = 0.0;
static double lastcurtime = 0.0;
static int lowshift;
qboolean isDedicated;
static qboolean sc_return_on_enter = false;
HANDLE hinput, houtput;
static char *tracking_tag = "Clams & Mooses";
static HANDLE tevent;
static HANDLE hFile;
static HANDLE heventParent;
static HANDLE heventChild;
void MaskExceptions (void);
void Sys_InitFloatTime (void);
void Sys_PushFPCW_SetHigh (void);
void Sys_PopFPCW (void);
volatile int sys_checksum;
/*
================
Sys_PageIn
================
*/
void Sys_PageIn (void *ptr, int size)
{
byte *x;
int j, m, n;
// touch all the memory to make sure it's there. The 16-page skip is to
// keep Win 95 from thinking we're trying to page ourselves in (we are
// doing that, of course, but there's no reason we shouldn't)
x = (byte *)ptr;
for (n=0 ; n<4 ; n++)
{
for (m=0 ; m<(size - 16 * 0x1000) ; m += 4)
{
sys_checksum += *(int *)&x[m];
sys_checksum += *(int *)&x[m + 16 * 0x1000];
}
}
}
/*
===============================================================================
FILE IO
===============================================================================
*/
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
int t;
t = VID_ForceUnlockedAndReturnState ();
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
VID_ForceLockState (t);
return end;
}
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i, retval;
int t;
t = VID_ForceUnlockedAndReturnState ();
i = findhandle ();
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
retval = -1;
}
else
{
sys_handles[i] = f;
*hndl = i;
retval = filelength(f);
}
VID_ForceLockState (t);
return retval;
}
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
int t;
t = VID_ForceUnlockedAndReturnState ();
i = findhandle ();
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
VID_ForceLockState (t);
return i;
}
void Sys_FileClose (int handle)
{
int t;
t = VID_ForceUnlockedAndReturnState ();
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
VID_ForceLockState (t);
}
void Sys_FileSeek (int handle, int position)
{
int t;
t = VID_ForceUnlockedAndReturnState ();
fseek (sys_handles[handle], position, SEEK_SET);
VID_ForceLockState (t);
}
int Sys_FileRead (int handle, void *dest, int count)
{
int t, x;
t = VID_ForceUnlockedAndReturnState ();
x = fread (dest, 1, count, sys_handles[handle]);
VID_ForceLockState (t);
return x;
}
int Sys_FileWrite (int handle, void *data, int count)
{
int t, x;
t = VID_ForceUnlockedAndReturnState ();
x = fwrite (data, 1, count, sys_handles[handle]);
VID_ForceLockState (t);
return x;
}
int Sys_FileTime (char *path)
{
FILE *f;
int t, retval;
t = VID_ForceUnlockedAndReturnState ();
f = fopen(path, "rb");
if (f)
{
fclose(f);
retval = 1;
}
else
{
retval = -1;
}
VID_ForceLockState (t);
return retval;
}
void Sys_mkdir (char *path)
{
_mkdir (path);
}
/*
===============================================================================
SYSTEM IO
===============================================================================
*/
/*
================
Sys_MakeCodeWriteable
================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
DWORD flOldProtect;
if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
Sys_Error("Protection change failed\n");
}
#ifndef _M_IX86
void Sys_SetFPCW (void)
{
}
void Sys_PushFPCW_SetHigh (void)
{
}
void Sys_PopFPCW (void)
{
}
void MaskExceptions (void)
{
}
#endif
/*
================
Sys_Init
================
*/
void Sys_Init (void)
{
LARGE_INTEGER PerformanceFreq;
unsigned int lowpart, highpart;
OSVERSIONINFO vinfo;
MaskExceptions ();
Sys_SetFPCW ();
if (!QueryPerformanceFrequency (&PerformanceFreq))
Sys_Error ("No hardware timer available");
// get 32 out of the 64 time bits such that we have around
// 1 microsecond resolution
lowpart = (unsigned int)PerformanceFreq.LowPart;
highpart = (unsigned int)PerformanceFreq.HighPart;
lowshift = 0;
while (highpart || (lowpart > 2000000.0))
{
lowshift++;
lowpart >>= 1;
lowpart |= (highpart & 1) << 31;
highpart >>= 1;
}
pfreq = 1.0 / (double)lowpart;
Sys_InitFloatTime ();
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
if (!GetVersionEx (&vinfo))
Sys_Error ("Couldn't get OS info");
if ((vinfo.dwMajorVersion < 4) ||
(vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
{
Sys_Error ("WinQuake requires at least Win95 or NT 4.0");
}
if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
WinNT = true;
else
WinNT = false;
}
void Sys_Error (char *error, ...)
{
va_list argptr;
char text[1024], text2[1024];
char *text3 = "Press Enter to exit\n";
char *text4 = "***********************************\n";
char *text5 = "\n";
DWORD dummy;
double starttime;
static int in_sys_error0 = 0;
static int in_sys_error1 = 0;
static int in_sys_error2 = 0;
static int in_sys_error3 = 0;
if (!in_sys_error3)
{
in_sys_error3 = 1;
VID_ForceUnlockedAndReturnState ();
}
va_start (argptr, error);
vsprintf (text, error, argptr);
va_end (argptr);
if (isDedicated)
{
va_start (argptr, error);
vsprintf (text, error, argptr);
va_end (argptr);
sprintf (text2, "ERROR: %s\n", text);
WriteFile (houtput, text5, strlen (text5), &dummy, NULL);
WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
WriteFile (houtput, text2, strlen (text2), &dummy, NULL);
WriteFile (houtput, text3, strlen (text3), &dummy, NULL);
WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
starttime = Sys_FloatTime ();
sc_return_on_enter = true; // so Enter will get us out of here
while (!Sys_ConsoleInput () &&
((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT))
{
}
}
else
{
// switch to windowed so the message box is visible, unless we already
// tried that and failed
if (!in_sys_error0)
{
in_sys_error0 = 1;
VID_SetDefaultMode ();
MessageBox(NULL, text, "Quake Error",
MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
}
else
{
MessageBox(NULL, text, "Double Quake Error",
MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
}
}
if (!in_sys_error1)
{
in_sys_error1 = 1;
Host_Shutdown ();
}
// shut down QHOST hooks if necessary
if (!in_sys_error2)
{
in_sys_error2 = 1;
DeinitConProc ();
}
exit (1);
}
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[1024];
DWORD dummy;
if (isDedicated)
{
va_start (argptr,fmt);
vsprintf (text, fmt, argptr);
va_end (argptr);
WriteFile(houtput, text, strlen (text), &dummy, NULL);
}
}
void Sys_Quit (void)
{
VID_ForceUnlockedAndReturnState ();
Host_Shutdown();
if (tevent)
CloseHandle (tevent);
if (isDedicated)
FreeConsole ();
// shut down QHOST hooks if necessary
DeinitConProc ();
exit (0);
}
/*
================
Sys_FloatTime
================
*/
double Sys_FloatTime (void)
{
static int sametimecount;
static unsigned int oldtime;
static int first = 1;
LARGE_INTEGER PerformanceCount;
unsigned int temp, t2;
double time;
Sys_PushFPCW_SetHigh ();
QueryPerformanceCounter (&PerformanceCount);
temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
if (first)
{
oldtime = temp;
first = 0;
}
else
{
// check for turnover or backward time
if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
{
oldtime = temp; // so we can't get stuck
}
else
{
t2 = temp - oldtime;
time = (double)t2 * pfreq;
oldtime = temp;
curtime += time;
if (curtime == lastcurtime)
{
sametimecount++;
if (sametimecount > 100000)
{
curtime += 1.0;
sametimecount = 0;
}
}
else
{
sametimecount = 0;
}
lastcurtime = curtime;
}
}
Sys_PopFPCW ();
return curtime;
}
/*
================
Sys_InitFloatTime
================
*/
void Sys_InitFloatTime (void)
{
int j;
Sys_FloatTime ();
j = COM_CheckParm("-starttime");
if (j)
{
curtime = (double) (Q_atof(com_argv[j+1]));
}
else
{
curtime = 0.0;
}
lastcurtime = curtime;
}
char *Sys_ConsoleInput (void)
{
static char text[256];
static int len;
INPUT_RECORD recs[1024];
int count;
int i, dummy;
int ch, numread, numevents;
if (!isDedicated)
return NULL;
for ( ;; )
{
if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
Sys_Error ("Error getting # of console events");
if (numevents <= 0)
break;
if (!ReadConsoleInput(hinput, recs, 1, &numread))
Sys_Error ("Error reading console input");
if (numread != 1)
Sys_Error ("Couldn't read console input");
if (recs[0].EventType == KEY_EVENT)
{
if (!recs[0].Event.KeyEvent.bKeyDown)
{
ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
switch (ch)
{
case '\r':
WriteFile(houtput, "\r\n", 2, &dummy, NULL);
if (len)
{
text[len] = 0;
len = 0;
return text;
}
else if (sc_return_on_enter)
{
// special case to allow exiting from the error handler on Enter
text[0] = '\r';
len = 0;
return text;
}
break;
case '\b':
WriteFile(houtput, "\b \b", 3, &dummy, NULL);
if (len)
{
len--;
}
break;
default:
if (ch >= ' ')
{
WriteFile(houtput, &ch, 1, &dummy, NULL);
text[len] = ch;
len = (len + 1) & 0xff;
}
break;
}
}
}
}
return NULL;
}
void Sys_Sleep (void)
{
Sleep (1);
}
void Sys_SendKeyEvents (void)
{
MSG msg;
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
{
// we always update if there are any event, even if we're paused
scr_skipupdate = 0;
if (!GetMessage (&msg, NULL, 0, 0))
Sys_Quit ();
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
/*
==============================================================================
WINDOWS CRAP
==============================================================================
*/
/*
==================
WinMain
==================
*/
void SleepUntilInput (int time)
{
MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
}
/*
==================
WinMain
==================
*/
HINSTANCE global_hInstance;
int global_nCmdShow;
char *argv[MAX_NUM_ARGVS];
static char *empty_string = "";
HWND hwnd_dialog;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
quakeparms_t parms;
double time, oldtime, newtime;
MEMORYSTATUS lpBuffer;
static char cwd[1024];
int t;
RECT rect;
/* previous instances do not exist in Win32 */
if (hPrevInstance)
return 0;
global_hInstance = hInstance;
global_nCmdShow = nCmdShow;
lpBuffer.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus (&lpBuffer);
if (!GetCurrentDirectory (sizeof(cwd), cwd))
Sys_Error ("Couldn't determine current directory");
if (cwd[Q_strlen(cwd)-1] == '/')
cwd[Q_strlen(cwd)-1] = 0;
parms.basedir = cwd;
parms.cachedir = NULL;
parms.argc = 1;
argv[0] = empty_string;
while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
{
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
lpCmdLine++;
if (*lpCmdLine)
{
argv[parms.argc] = lpCmdLine;
parms.argc++;
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
lpCmdLine++;
if (*lpCmdLine)
{
*lpCmdLine = 0;
lpCmdLine++;
}
}
}
parms.argv = argv;
COM_InitArgv (parms.argc, parms.argv);
parms.argc = com_argc;
parms.argv = com_argv;
isDedicated = (COM_CheckParm ("-dedicated") != 0);
if (!isDedicated)
{
hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
if (hwnd_dialog)
{
if (GetWindowRect (hwnd_dialog, &rect))
{
if (rect.left > (rect.top * 2))
{
SetWindowPos (hwnd_dialog, 0,
(rect.left / 2) - ((rect.right - rect.left) / 2),
rect.top, 0, 0,
SWP_NOZORDER | SWP_NOSIZE);
}
}
ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
UpdateWindow (hwnd_dialog);
SetForegroundWindow (hwnd_dialog);
}
}
// take the greater of all the available memory or half the total memory,
// but at least 8 Mb and no more than 16 Mb, unless they explicitly
// request otherwise
parms.memsize = lpBuffer.dwAvailPhys;
if (parms.memsize < MINIMUM_WIN_MEMORY)
parms.memsize = MINIMUM_WIN_MEMORY;
if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
parms.memsize = lpBuffer.dwTotalPhys >> 1;
if (parms.memsize > MAXIMUM_WIN_MEMORY)
parms.memsize = MAXIMUM_WIN_MEMORY;
if (COM_CheckParm ("-heapsize"))
{
t = COM_CheckParm("-heapsize") + 1;
if (t < com_argc)
parms.memsize = Q_atoi (com_argv[t]) * 1024;
}
parms.membase = malloc (parms.memsize);
if (!parms.membase)
Sys_Error ("Not enough memory free; check disk space\n");
Sys_PageIn (parms.membase, parms.memsize);
tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!tevent)
Sys_Error ("Couldn't create event");
if (isDedicated)
{
if (!AllocConsole ())
{
Sys_Error ("Couldn't create dedicated server console");
}
hinput = GetStdHandle (STD_INPUT_HANDLE);
houtput = GetStdHandle (STD_OUTPUT_HANDLE);
// give QHOST a chance to hook into the console
if ((t = COM_CheckParm ("-HFILE")) > 0)
{
if (t < com_argc)
hFile = (HANDLE)Q_atoi (com_argv[t+1]);
}
if ((t = COM_CheckParm ("-HPARENT")) > 0)
{
if (t < com_argc)
heventParent = (HANDLE)Q_atoi (com_argv[t+1]);
}
if ((t = COM_CheckParm ("-HCHILD")) > 0)
{
if (t < com_argc)
heventChild = (HANDLE)Q_atoi (com_argv[t+1]);
}
InitConProc (hFile, heventParent, heventChild);
}
Sys_Init ();
// because sound is off until we become active
S_BlockSound ();
Sys_Printf ("Host_Init\n");
Host_Init (&parms);
oldtime = Sys_FloatTime ();
/* main window message loop */
while (1)
{
if (isDedicated)
{
newtime = Sys_FloatTime ();
time = newtime - oldtime;
while (time < sys_ticrate.value )
{
Sys_Sleep();
newtime = Sys_FloatTime ();
time = newtime - oldtime;
}
}
else
{
// yield the CPU for a little while when paused, minimized, or not the focus
if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
{
SleepUntilInput (PAUSE_SLEEP);
scr_skipupdate = 1; // no point in bothering to draw
}
else if (!ActiveApp && !DDActive)
{
SleepUntilInput (NOT_FOCUS_SLEEP);
}
newtime = Sys_FloatTime ();
time = newtime - oldtime;
}
Host_Frame (time);
oldtime = newtime;
}
/* return success of application */
return TRUE;
}

View file

@ -1,325 +0,0 @@
/*
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.
*/
// sys_null.h -- null system driver to aid porting efforts
#include "quakedef.h"
#include "winquake.h"
#include "errno.h"
#include <sys\types.h>
#include <sys\timeb.h>
/*
===============================================================================
FILE IO
===============================================================================
*/
#define MAX_HANDLES 10
FILE *sys_handles[MAX_HANDLES];
int findhandle (void)
{
int i;
for (i=1 ; i<MAX_HANDLES ; i++)
if (!sys_handles[i])
return i;
Sys_Error ("out of handles");
return -1;
}
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
int Sys_FileOpenRead (char *path, int *hndl)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "rb");
if (!f)
{
*hndl = -1;
return -1;
}
sys_handles[i] = f;
*hndl = i;
return filelength(f);
}
int Sys_FileOpenWrite (char *path)
{
FILE *f;
int i;
i = findhandle ();
f = fopen(path, "wb");
if (!f)
Sys_Error ("Error opening %s: %s", path,strerror(errno));
sys_handles[i] = f;
return i;
}
void Sys_FileClose (int handle)
{
fclose (sys_handles[handle]);
sys_handles[handle] = NULL;
}
void Sys_FileSeek (int handle, int position)
{
fseek (sys_handles[handle], position, SEEK_SET);
}
int Sys_FileRead (int handle, void *dest, int count)
{
return fread (dest, 1, count, sys_handles[handle]);
}
int Sys_FileWrite (int handle, void *data, int count)
{
return fwrite (data, 1, count, sys_handles[handle]);
}
int Sys_FileTime (char *path)
{
FILE *f;
f = fopen(path, "rb");
if (f)
{
fclose(f);
return 1;
}
return -1;
}
void Sys_mkdir (char *path)
{
}
/*
===============================================================================
SYSTEM IO
===============================================================================
*/
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
}
void Sys_DebugLog(char *file, char *fmt, ...)
{
}
void Sys_Error (char *error, ...)
{
va_list argptr;
char text[1024];
va_start (argptr,error);
vsprintf (text, error,argptr);
va_end (argptr);
// MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
printf ("ERROR: %s\n", text);
exit (1);
}
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
va_start (argptr,fmt);
vprintf (fmt,argptr);
va_end (argptr);
}
void Sys_Quit (void)
{
exit (0);
}
double Sys_FloatTime (void)
{
double t;
struct _timeb tstruct;
static int starttime;
_ftime( &tstruct );
if (!starttime)
starttime = tstruct.time;
t = (tstruct.time-starttime) + tstruct.millitm*0.001;
return t;
}
void Sys_Sleep (void)
{
}
void Sys_SendKeyEvents (void)
{
}
void Sys_HighFPPrecision (void)
{
}
void Sys_LowFPPrecision (void)
{
}
char *Sys_ConsoleInput (void)
{
static char text[256];
static int len;
INPUT_RECORD recs[1024];
int count;
int i;
int c;
// read a line out
while (_kbhit())
{
c = _getch();
putch (c);
if (c == '\r')
{
text[len] = 0;
putch ('\n');
len = 0;
return text;
}
if (c == 8)
{
putch (' ');
putch (c);
len--;
text[len] = 0;
continue;
}
text[len] = c;
len++;
text[len] = 0;
if (len == sizeof(text))
len = 0;
}
return NULL;
}
/*
==================
main
==================
*/
char *newargv[256];
int main (int argc, char **argv)
{
MSG msg;
quakeparms_t parms;
double time, oldtime;
static char cwd[1024];
memset (&parms, 0, sizeof(parms));
parms.memsize = 16384*1024;
parms.membase = malloc (parms.memsize);
_getcwd (cwd, sizeof(cwd));
if (cwd[Q_strlen(cwd)-1] == '\\')
cwd[Q_strlen(cwd)-1] = 0;
parms.basedir = cwd; //"f:/quake";
// parms.basedir = "f:\\quake";
COM_InitArgv (argc, argv);
// dedicated server ONLY!
if (!COM_CheckParm ("-dedicated"))
{
memcpy (newargv, argv, argc*4);
newargv[argc] = "-dedicated";
argc++;
argv = newargv;
COM_InitArgv (argc, argv);
}
parms.argc = argc;
parms.argv = argv;
printf ("Host_Init\n");
Host_Init (&parms);
oldtime = Sys_FloatTime ();
/* main window message loop */
while (1)
{
time = Sys_FloatTime();
if (time - oldtime < sys_ticrate.value )
{
Sleep(1);
continue;
}
Host_Frame ( time - oldtime );
oldtime = time;
}
/* return success of application */
return TRUE;
}

View file

@ -1,599 +0,0 @@
/*
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.
*/
//
// vgamodes.h: VGA mode set tables
//
#include "vregset.h"
int VGA_InitMode (viddef_t *vid, vmode_t *pcurrentmode);
void VGA_SwapBuffers (viddef_t *vid, vmode_t *pcurrentmode, vrect_t *rects);
void VGA_SetPalette (viddef_t *vid, vmode_t *pcurrentmode,
unsigned char *pal);
///////////////////////////////////////////////////////////////////////////
// the following base mode descriptors plus extra data together provide all
// the data needed to do VGA mode sets
///////////////////////////////////////////////////////////////////////////
typedef struct {
int vidbuffer;
int *pregset;
} vextra_t;
int vrsnull[] = {
VRS_END,
};
int vrs320x200x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x13, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
VRS_END,
};
int vrs360x200x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0x67,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_END,
};
int vrs320x240x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x13, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0x4109,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0x0014,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_WORD_OUT, CRTC_INDEX, 0xE317,
VRS_END,
};
int vrs360x240x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0xE7,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0x4109,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_WORD_OUT, CRTC_INDEX, 0x0014,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_WORD_OUT, CRTC_INDEX, 0xE317,
VRS_END,
};
int vrs320x350x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x10, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
VRS_BYTE_OUT, MISC_OUTPUT, 0xA3, // 350-scan-line scan rate
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
//
// set the vertical counts for 350-scan-line mode
//
VRS_WORD_OUT, CRTC_INDEX, 0xBF06,
VRS_WORD_OUT, CRTC_INDEX, 0x1F07,
VRS_WORD_OUT, CRTC_INDEX, 0x8310,
VRS_WORD_OUT, CRTC_INDEX, 0x8511,
VRS_WORD_OUT, CRTC_INDEX, 0x5D12,
VRS_WORD_OUT, CRTC_INDEX, 0x6315,
VRS_WORD_OUT, CRTC_INDEX, 0xBA16,
VRS_END,
};
int vrs360x350x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0xA7, // 350-scan-line scan rate
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
//
// set the vertical counts for 350-scan-line mode and 360 pixels across
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0xBF06,
VRS_WORD_OUT, CRTC_INDEX, 0x1F07,
VRS_WORD_OUT, CRTC_INDEX, 0x8310,
VRS_WORD_OUT, CRTC_INDEX, 0x8511,
VRS_WORD_OUT, CRTC_INDEX, 0x5D12,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_WORD_OUT, CRTC_INDEX, 0x6315,
VRS_WORD_OUT, CRTC_INDEX, 0xBA16,
VRS_END,
};
int vrs320x400x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x10, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
VRS_END,
};
int vrs360x400x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0x67,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_END,
};
int vrs320x480x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_BYTE_OUT, SC_INDEX, MEMORY_MODE,
VRS_BYTE_RMW, SC_DATA, ~0x08, 0x04,
VRS_BYTE_OUT, GC_INDEX, GRAPHICS_MODE,
VRS_BYTE_RMW, GC_DATA, ~0x10, 0x00,
VRS_BYTE_OUT, GC_INDEX, MISCELLANOUS,
VRS_BYTE_RMW, GC_DATA, ~0x02, 0x00,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// stop scanning each line twice
//
VRS_BYTE_OUT, CRTC_INDEX, MAX_SCAN_LINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x1F, 0x00,
//
// change the CRTC from doubleword to byte mode
//
VRS_BYTE_OUT, CRTC_INDEX, UNDERLINE,
VRS_BYTE_RMW, CRTC_DATA, ~0x40, 0x00,
VRS_BYTE_OUT, CRTC_INDEX, MODE_CONTROL,
VRS_BYTE_RMW, CRTC_DATA, ~0x00, 0x40,
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_END,
};
int vrs360x480x256planar[] = {
//
// switch to linear, non-chain4 mode
//
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 1,
VRS_WORD_OUT, SC_INDEX, 0x0604,
VRS_BYTE_OUT, MISC_OUTPUT, 0xE7,
VRS_BYTE_OUT, SC_INDEX, SYNC_RESET,
VRS_BYTE_OUT, SC_DATA, 3,
//
// unprotect CRTC0 through CRTC0
//
VRS_BYTE_OUT, CRTC_INDEX, 0x11,
VRS_BYTE_RMW, CRTC_DATA, ~0x80, 0x00,
//
// set up the CRT Controller
//
VRS_WORD_OUT, CRTC_INDEX, 0x6B00,
VRS_WORD_OUT, CRTC_INDEX, 0x5901,
VRS_WORD_OUT, CRTC_INDEX, 0x5A02,
VRS_WORD_OUT, CRTC_INDEX, 0x8E03,
VRS_WORD_OUT, CRTC_INDEX, 0x5E04,
VRS_WORD_OUT, CRTC_INDEX, 0x8A05,
VRS_WORD_OUT, CRTC_INDEX, 0x0D06,
VRS_WORD_OUT, CRTC_INDEX, 0x3E07,
VRS_WORD_OUT, CRTC_INDEX, 0x4009,
VRS_WORD_OUT, CRTC_INDEX, 0xEA10,
VRS_WORD_OUT, CRTC_INDEX, 0xAC11,
VRS_WORD_OUT, CRTC_INDEX, 0xDF12,
VRS_WORD_OUT, CRTC_INDEX, 0x3013,
VRS_WORD_OUT, CRTC_INDEX, 0x0014,
VRS_WORD_OUT, CRTC_INDEX, 0xE715,
VRS_WORD_OUT, CRTC_INDEX, 0x0616,
VRS_WORD_OUT, CRTC_INDEX, 0xE317,
VRS_END,
};
//
// extra VGA-specific data for vgavidmodes
//
vextra_t extra320x200x256linear = {
1, vrsnull
};
vextra_t extra320x200x256planar = {
1, vrs320x200x256planar
};
vextra_t extra360x200x256planar = {
1, vrs360x200x256planar
};
vextra_t extra320x240x256planar = {
1, vrs320x240x256planar
};
vextra_t extra360x240x256planar = {
1, vrs360x240x256planar
};
vextra_t extra320x350x256planar = {
1, vrs320x350x256planar
};
vextra_t extra360x350x256planar = {
1, vrs360x350x256planar
};
vextra_t extra320x400x256planar = {
1, vrs320x400x256planar
};
vextra_t extra360x400x256planar = {
1, vrs360x400x256planar
};
vextra_t extra320x480x256planar = {
1, vrs320x480x256planar
};
vextra_t extra360x480x256planar = {
1, vrs360x480x256planar
};
//
// base mode descriptors, in ascending order of number of pixels
//
vmode_t vgavidmodes[] = {
{
NULL,
"320x200", " ***** standard VGA modes ***** ",
320, 200, (200.0/320.0)*(320.0/240.0), 320, 0, 1, &extra320x200x256linear,
VGA_InitMode, VGA_SwapBuffers, VGA_SetPalette,
VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x200", " ***** Mode X-style modes ***** ",
320, 200, (200.0/320.0)*(320.0/240.0), 320, 1, 1, &extra320x200x256planar,
VGA_InitMode, VGA_SwapBuffers, VGA_SetPalette,
VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x200", NULL, 360, 200, (200.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x200x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x240", NULL, 320, 240, (240.0/320.0)*(320.0/240.0),
320, 1, 1, &extra320x240x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x240", NULL, 360, 240, (240.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x240x256planar,
VGA_InitMode, VGA_SwapBuffers, VGA_SetPalette,
VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x350", NULL, 320, 350, (350.0/320.0)*(320.0/240.0),
320, 1, 1, &extra320x350x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x350", NULL, 360, 350, (350.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x350x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x400", NULL, 320, 400, (400.0/320.0)*(320.0/240.0), 320,
1, 1, &extra320x400x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x400", NULL, 360, 400, (400.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x400x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"320x480", NULL, 320, 480, (480.0/320.0)*(320.0/240.0),
320, 1, 1, &extra320x480x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
{
NULL,
"360x480", NULL, 360, 480, (480.0/360.0)*(320.0/240.0),
384, 1, 1, &extra360x480x256planar, VGA_InitMode,
VGA_SwapBuffers,
VGA_SetPalette, VGA_BeginDirectRect, VGA_EndDirectRect
},
};

View file

@ -1,115 +0,0 @@
/*
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.
*/
#include "quakedef.h"
#include "d_local.h"
#include <3ds.h>
viddef_t vid; // global video state
#define BASEWIDTH 400
#define BASEHEIGHT 240
byte vid_buffer[BASEWIDTH*BASEHEIGHT];
short zbuffer[BASEWIDTH*BASEHEIGHT];
byte surfcache[512*1024];
uint16_t *framebuffer;
uint16_t d_8to16table[256];
void VID_SetPalette (unsigned char *palette)
{
int i;
unsigned char r, g, b;
if(palette==NULL)
return;
for(i = 0; i < 256; i++){
r = palette[i*3+0];
g = palette[i*3+1];
b = palette[i*3+2];
d_8to16table[i] = RGB8_to_565(r,g,b);
}
}
void VID_ShiftPalette (unsigned char *palette)
{
VID_SetPalette(palette);
}
void VID_Init (unsigned char *palette)
{
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.width = vid.conwidth = BASEWIDTH;
vid.height = vid.conheight = BASEHEIGHT;
vid.aspect = 1.0;
vid.numpages = 1;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
vid.buffer = vid.conbuffer = vid_buffer;
vid.rowbytes = vid.conrowbytes = BASEWIDTH;
d_pzbuffer = zbuffer;
D_InitCaches (surfcache, sizeof(surfcache));
VID_SetPalette(palette);
framebuffer = (uint16_t*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
}
void VID_Shutdown (void)
{
}
void VID_Update (vrect_t *rects)
{
int x, y;
for(x=0; x<400; x++)
{
for(y=0; y<240;y++)
{
framebuffer[(x*240 + (239 -y))] = d_8to16table[vid.buffer[y*400 + x]];
}
}
}
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
}

View file

@ -1,87 +0,0 @@
/*
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.
*/
// vid_null.c -- null video driver to aid porting efforts
#include "quakedef.h"
#include "d_local.h"
viddef_t vid; // global video state
#define BASEWIDTH 320
#define BASEHEIGHT 200
byte vid_buffer[BASEWIDTH*BASEHEIGHT];
short zbuffer[BASEWIDTH*BASEHEIGHT];
byte surfcache[256*1024];
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
void VID_SetPalette (unsigned char *palette)
{
}
void VID_ShiftPalette (unsigned char *palette)
{
}
void VID_Init (unsigned char *palette)
{
vid.maxwarpwidth = vid.width = vid.conwidth = BASEWIDTH;
vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT;
vid.aspect = 1.0;
vid.numpages = 1;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
vid.buffer = vid.conbuffer = vid_buffer;
vid.rowbytes = vid.conrowbytes = BASEWIDTH;
d_pzbuffer = zbuffer;
D_InitCaches (surfcache, sizeof(surfcache));
}
void VID_Shutdown (void)
{
}
void VID_Update (vrect_t *rects)
{
}
/*
================
D_BeginDirectRect
================
*/
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
/*
================
D_EndDirectRect
================
*/
void D_EndDirectRect (int x, int y, int width, int height)
{
}

View file

@ -1,81 +0,0 @@
/*
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.
*/
//
// vregset.c: video register-setting interpreter
//
#include <dos.h>
#include <conio.h>
#include "quakedef.h"
#include "vregset.h"
//#define outportb loutportb
void loutportb (int port, int val)
{
printf ("port, val: %x %x\n", port, val);
getch ();
}
/*
================
VideoRegisterSet
================
*/
void VideoRegisterSet (int *pregset)
{
int port, temp0, temp1, temp2;
for ( ;; )
{
switch (*pregset++)
{
case VRS_END:
return;
case VRS_BYTE_OUT:
port = *pregset++;
outportb (port, *pregset++);
break;
case VRS_BYTE_RMW:
port = *pregset++;
temp0 = *pregset++;
temp1 = *pregset++;
temp2 = inportb (port);
temp2 &= temp0;
temp2 |= temp1;
outportb (port, temp2);
break;
case VRS_WORD_OUT:
port = *pregset++;
outportb (port, *pregset & 0xFF);
outportb (port+1, *pregset >> 8);
pregset++;
break;
default:
Sys_Error ("VideoRegisterSet: Invalid command\n");
}
}
}

View file

@ -1,56 +0,0 @@
/*
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.
*/
//
// vregset.h: header file for video register-setting interpreter
//
//
// registers & subregisters
//
#define MISC_OUTPUT 0x3C2
#define SC_INDEX 0x3C4
#define SC_DATA 0x3C5
#define SYNC_RESET 0
#define MAP_MASK 2
#define MEMORY_MODE 4
#define GC_INDEX 0x3CE
#define GC_DATA 0x3CF
#define READ_MAP 4
#define GRAPHICS_MODE 5
#define MISCELLANOUS 6
#define CRTC_INDEX 0x3D4
#define CRTC_DATA 0x3D5
#define MAX_SCAN_LINE 9
#define UNDERLINE 0x14
#define MODE_CONTROL 0x17
//
// register-set commands
//
#define VRS_END 0
#define VRS_BYTE_OUT 1
#define VRS_BYTE_RMW 2
#define VRS_WORD_OUT 3
void VideoRegisterSet (int *pregset);

View file

@ -1,114 +0,0 @@
/*
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.
*/
// winquake.h: Win32-specific Quake header file
#pragma warning( disable : 4229 ) // mgraph gets this
#include <windows.h>
#define WM_MOUSEWHEEL 0x020A
#ifndef SERVERONLY
#include <ddraw.h>
#include <dsound.h>
#ifndef GLQUAKE
#include <mgraph.h>
#endif
#endif
extern HINSTANCE global_hInstance;
extern int global_nCmdShow;
#ifndef SERVERONLY
extern LPDIRECTDRAW lpDD;
extern qboolean DDActive;
extern LPDIRECTDRAWSURFACE lpPrimary;
extern LPDIRECTDRAWSURFACE lpFrontBuffer;
extern LPDIRECTDRAWSURFACE lpBackBuffer;
extern LPDIRECTDRAWPALETTE lpDDPal;
extern LPDIRECTSOUND pDS;
extern LPDIRECTSOUNDBUFFER pDSBuf;
extern DWORD gSndBufSize;
//#define SNDBUFSIZE 65536
void VID_LockBuffer (void);
void VID_UnlockBuffer (void);
#endif
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
extern modestate_t modestate;
extern HWND mainwindow;
extern qboolean ActiveApp, Minimized;
extern qboolean WinNT;
int VID_ForceUnlockedAndReturnState (void);
void VID_ForceLockState (int lk);
void IN_ShowMouse (void);
void IN_DeactivateMouse (void);
void IN_HideMouse (void);
void IN_ActivateMouse (void);
void IN_RestoreOriginalMouseState (void);
void IN_SetQuakeMouseState (void);
void IN_MouseEvent (int mstate);
extern qboolean winsock_lib_initialized;
extern cvar_t _windowed_mouse;
extern int window_center_x, window_center_y;
extern RECT window_rect;
extern qboolean mouseinitialized;
extern HWND hwnd_dialog;
extern HANDLE hinput, houtput;
void IN_UpdateClipCursor (void);
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify);
void S_BlockSound (void);
void S_UnblockSound (void);
void VID_SetDefaultMode (void);
int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData);
int (PASCAL FAR *pWSACleanup)(void);
int (PASCAL FAR *pWSAGetLastError)(void);
SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol);
int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp);
int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname,
const char FAR * optval, int optlen);
int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags,
struct sockaddr FAR *from, int FAR * fromlen);
int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags,
const struct sockaddr FAR *to, int tolen);
int (PASCAL FAR *pclosesocket)(SOCKET s);
int (PASCAL FAR *pgethostname)(char FAR * name, int namelen);
struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name);
struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr,
int len, int type);
int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name,
int FAR * namelen);