mirror of
https://github.com/nzp-team/glquake.git
synced 2025-04-22 09:31:18 +00:00
Clean up legacy glquake files from other platforms
This commit is contained in:
parent
664cfe3b99
commit
d657027ab0
80 changed files with 0 additions and 24293 deletions
1077
source/adivtab.h
1077
source/adivtab.h
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
@ -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
|
||||
|
142
source/block16.h
142
source/block16.h
|
@ -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
|
143
source/block8.h
143
source/block8.h
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
477
source/cd_win.c
477
source/cd_win.c
|
@ -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");
|
||||
}
|
365
source/conproc.c
365
source/conproc.c
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
331
source/d_edge.c
331
source/d_edge.c
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
229
source/d_iface.h
229
source/d_iface.h
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
173
source/d_init.c
173
source/d_init.c
|
@ -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);
|
||||
}
|
||||
|
111
source/d_local.h
111
source/d_local.h
|
@ -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);
|
||||
|
|
@ -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 ();
|
||||
}
|
||||
|
207
source/d_part.c
207
source/d_part.c
|
@ -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
|
||||
|
1111
source/d_polyse.c
1111
source/d_polyse.c
File diff suppressed because it is too large
Load diff
449
source/d_scan.c
449
source/d_scan.c
|
@ -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
|
||||
|
138
source/d_sky.c
138
source/d_sky.c
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
335
source/d_surf.c
335
source/d_surf.c
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
257
source/dos_v2.c
257
source/dos_v2.c
|
@ -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 *) ®s);
|
||||
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;
|
||||
}
|
||||
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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_ */
|
222
source/mplib.c
222
source/mplib.c
|
@ -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, ®s, ®s);
|
||||
}
|
||||
|
||||
int
|
||||
MGenWait(void)
|
||||
{
|
||||
REGISTERS regs;
|
||||
|
||||
regs.d.eax = MGENVXD_WAIT_ORD << 16 | MGENVXD_DEVICE_ID;
|
||||
int386(CHUNNEL_INT, ®s, ®s);
|
||||
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, ®s, ®s);
|
||||
|
||||
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, ®s, ®s);
|
||||
|
||||
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, ®s, ®s);
|
||||
|
||||
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, ®s, ®s);
|
||||
*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, ®s, ®s);
|
||||
|
||||
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, ®s, ®s);
|
||||
|
||||
return regs.d.eax;
|
||||
}
|
||||
|
||||
int MGenSanityCheck(void)
|
||||
{
|
||||
REGISTERS regs;
|
||||
|
||||
regs.d.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID;
|
||||
int386(CHUNNEL_INT, ®s, ®s);
|
||||
|
||||
return regs.d.eax;
|
||||
}
|
||||
|
||||
void MGenWakeupDll(void)
|
||||
{
|
||||
REGISTERS regs;
|
||||
|
||||
regs.d.eax = MGENVXD_WAKEUPDLL_ORD << 16 | MGENVXD_DEVICE_ID;
|
||||
int386(CHUNNEL_INT, ®s, ®s);
|
||||
}
|
1001
source/mplpc.c
1001
source/mplpc.c
File diff suppressed because it is too large
Load diff
763
source/net_bw.c
763
source/net_bw.c
|
@ -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(ðdevinfo, 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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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);
|
1285
source/net_comx.c
1285
source/net_comx.c
File diff suppressed because it is too large
Load diff
162
source/net_dos.c
162
source/net_dos.c
|
@ -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;
|
706
source/net_ipx.c
706
source/net_ipx.c
|
@ -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 *)®s);
|
||||
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 *)®s);
|
||||
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 *)®s);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
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 *)®s);
|
||||
}
|
||||
|
||||
|
||||
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 *)®s);
|
||||
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 *)®s);
|
||||
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 *)®s);
|
||||
|
||||
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 *)®s);
|
||||
|
||||
// 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 *)®s);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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);
|
443
source/net_mp.c
443
source/net_mp.c
|
@ -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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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);
|
|
@ -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;
|
951
source/net_ser.c
951
source/net_ser.c
|
@ -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;
|
||||
}
|
|
@ -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);
|
414
source/net_udp.c
414
source/net_udp.c
|
@ -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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
120
source/net_win.c
120
source/net_win.c
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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);
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
653
source/snd_dos.c
653
source/snd_dos.c
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
1293
source/snd_gus.c
1293
source/snd_gus.c
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
218
source/snd_sun.c
218
source/snd_sun.c
|
@ -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");
|
||||
|
||||
}
|
||||
|
729
source/snd_win.c
729
source/snd_win.c
|
@ -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 ();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
953
source/sys_dos.c
953
source/sys_dos.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
352
source/sys_sun.c
352
source/sys_sun.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
893
source/sys_win.c
893
source/sys_win.c
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
},
|
||||
};
|
||||
|
115
source/vid_ctr.c
115
source/vid_ctr.c
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
Loading…
Reference in a new issue