diff --git a/3.15_Changes.txt b/3.15_Changes.txt new file mode 100644 index 000000000..df3678934 --- /dev/null +++ b/3.15_Changes.txt @@ -0,0 +1,107 @@ + +Quake2 3.15 Upgrade +------------------- + +This upgrade addresses several features, including security, playability, and +enhancements. + +A new map is also included (in baseq2\pak3.pak) called match1, Reckless +Abandon. This map is designed for one on one deathmatch play. It was built +by American McGee and Dave "Zoid" Kirsch. + +This patch replaces the following files: + + quake2.exe + 3dfxgl.dll + pvrgl.dll + ref_gl.dll + ref_soft.dll + baseq2\gamex86.dll + +Changes +------- + +- Added visible weapons support. This is precached with a special symbol, i.e. + gi.modelindex("#w_shotgun.md2") which causes the client to autobind it to + the players current weapon model. Plug in player models can optionally + support the visible weapons. Any that do not support it will use their + default weapon.md2 files automatically. + Visible weapons files for plug in player models are not downloaded + automatically--only the default weapon.md2 (and skin) is. + The Visible weapon models themselves are not included. They can be + downloaded from http://www.telefragged.com/vwep/ +- Rewrote the some of the net code to use optimized network packets for + projectiles. This is transparent to the game code, but improves netplay + substancially. The hyperblaster doesn't flood modem players anymore. +- Rewrote the packet checksum code to be more portable and defeat proxy bots + yet again. +- Autodownload support is in. The following items will be automatcally + downloaded as needed: + - world map (and textures) + - models + - sounds (precached ones) + - plug in player model, skin, skin_i and weapon.md2 + downloads go to a temp file (maps/blah.tmp for example) and get renamed + when done. autoresume is supported (if you lose connect during the + download, just reconnect and resume). Server has fine control over + the downloads with the following new cvars: + allow_download - global download on/off + allow_download_players - players download on/off + allow_download_models - models download on/off + allow_download_sounds - sounds download on/off + allow_download_maps - maps download on/off + maps that are in pak files will _not_ autodownload from the server, this + is for copyright considerations. + The QuakeWorld bug of the server map changing while download a map has + been fixed. +- New option in the Multiplayer/Player Setup menu for setting your connection + speed. This sets a default rate for the player and can improve net + performance for modem connections. +- Rewrote some of the save game code to make it more portable. I wanted to + completely rewrite the entire save game system and make it portable across + versions and operating systems, but this would require an enormous amount + of work. +- Added another 512 configure strings for general usage for mod makers. + This gives lots of room for general string displays on the HUD and in other + data. +- Player movement code re-written to be similiar to that of NetQuake and + later versions of QuakeWorld. Player has more control in the air and + gets a boost in vertical speed when jumping off the top of ramps. +- Fixed up serverrecord so that it works correctly with the later versions. + serverrecord lets the server do a recording of the current game that + demo editors can use to make demos from any PVS in the level. Server + recorded demos are BIG. Will look at using delta compression in them + to cut down the size. +- Copy protection CD check has been removed. +- Quake2 3.15 has changed the protocol (so old servers will not run) but + all existing game dlls can run on the new version (albiet without the + new features such as visible weapons). +- Added flood protection. Controlled from the following cvars: + flood_msgs - maximum number of messages allowed in the time period + specified by flood_persecond + flood_persecond - time period that a maximum of flood_msgs messages are + permitted + flood_waitdelay - amount of time a client gets muzzled for flooding +- fixed it so blaster/hyperblaster shots aren't treated as solid when + predicting--you aren't clipped against them now. +- gender support is now in. The userinfo cvar "gender" can be set to + male/female/none (none for neutral messages). This doesn't affect sounds + but does affect death messages in the game. The models male and cyborg + default to gender male, and female and crackhor default to female. + Everything else defaults to none, but you can set it by typing + "gender male" or "gender female" as appropriate. +- IP banning support ala QW. It's built into the game dll as 'sv' console + commands. This list is: + sv addip - adds an ip to the ban list + sv listip - removes an ip from the ban list + sv writeip - writes the ban list to /listip.cfg. You can + exec this on a server load to load the list on subsequent server runs. + like so: quake2 +set dedicated 1 +exec listip.cfg + sv removeip - remove an ip from the list + the ip list is a simple mask system. Adding 192.168 to the list + would block out everyone in the 192.168.*.* net block. You get 1024 bans, + if you need more, recompile the game dll. :) + A new cvar is also supported called 'filterban'. It defaults to one which + means "allow everyone to connect _except_ those matching in the ban list." + If you set it to zero, the meaning reverses like so, "don't allow anyone + to connect unless they are in the list." diff --git a/ref_soft/r_polysa.asm b/ref_soft/r_polysa.asm new file mode 100644 index 000000000..339cc6259 --- /dev/null +++ b/ref_soft/r_polysa.asm @@ -0,0 +1,812 @@ + .386P + .model FLAT +; +; d_polysa.s +; x86 assembly-language polygon model drawing code +; + +include qasm.inc +include d_if.inc + +if id386 + +; !!! if this is changed, it must be changed in d_polyse.c too !!! +;DPS_MAXSPANS equ (MAXHEIGHT+1) +; 1 extra for spanpackage that marks end + +;SPAN_SIZE equ (((DPS_MAXSPANS + 1 + ((CACHE_SIZE - 1) / spanpackage_t_size)) + 1) * spanpackage_t_size) + +MASK_1K equ 03FFh + +_DATA SEGMENT + + align 4 +;p10_minus_p20 dd 0 +;p01_minus_p21 dd 0 +;temp0 dd 0 +;temp1 dd 0 +;Ltemp dd 0 + +aff8entryvec_table dd LDraw8, LDraw7, LDraw6, LDraw5 + dd LDraw4, LDraw3, LDraw2, LDraw1, LDraw8IR, LDraw7IR, LDraw6IR, LDraw5IR, LDraw4IR, LDraw3IR, LDraw2IR, LDraw1IR + +lzistepx dd 0 + + externdef _rand1k:dword + externdef _rand1k_index:dword + externdef _alias_colormap:dword + +;PGM + externdef _irtable:dword + externdef _iractive:byte +;PGM + +_DATA ENDS +_TEXT SEGMENT + + +;---------------------------------------------------------------------- +; 8-bpp horizontal span drawing code for affine polygons, with smooth +; shading and no transparency +;---------------------------------------------------------------------- + +;=================================== +;=================================== + +pspans equ 4+8 + + public _D_PolysetAff8Start +_D_PolysetAff8Start: + + public _R_PolysetDrawSpans8_Opaque +_R_PolysetDrawSpans8_Opaque: + + push esi ; preserve register variables + push ebx + + mov esi,ds:dword ptr[pspans+esp] ; point to the first span descriptor + mov ecx,ds:dword ptr[_r_zistepx] + + push ebp ; preserve caller's stack frame + push edi + + ror ecx,16 ; put high 16 bits of 1/z step in low word + mov edx,ds:dword ptr[spanpackage_t_count+esi] + + mov ds:dword ptr[lzistepx],ecx + +LSpanLoop: + +; lcount = d_aspancount - pspanpackage->count; +; +; errorterm += erroradjustup; +; if (errorterm >= 0) +; { +; d_aspancount += d_countextrastep; +; errorterm -= erroradjustdown; +; } +; else +; { +; d_aspancount += ubasestep; +; } + + mov eax,ds:dword ptr[_d_aspancount] + sub eax,edx + + mov edx,ds:dword ptr[_erroradjustup] + mov ebx,ds:dword ptr[_errorterm] + add ebx,edx + js LNoTurnover + + mov edx,ds:dword ptr[_erroradjustdown] + mov edi,ds:dword ptr[_d_countextrastep] + sub ebx,edx + mov ebp,ds:dword ptr[_d_aspancount] + mov ds:dword ptr[_errorterm],ebx + add ebp,edi + mov ds:dword ptr[_d_aspancount],ebp + jmp LRightEdgeStepped + +LNoTurnover: + mov edi,ds:dword ptr[_d_aspancount] + mov edx,ds:dword ptr[_ubasestep] + mov ds:dword ptr[_errorterm],ebx + add edi,edx + mov ds:dword ptr[_d_aspancount],edi + +LRightEdgeStepped: + cmp eax,1 + + jl LNextSpan + jz LExactlyOneLong + +; +; set up advancetable +; + mov ecx,ds:dword ptr[_a_ststepxwhole] + mov edx,ds:dword ptr[_r_affinetridesc+atd_skinwidth] + + mov ds:dword ptr[advancetable+4],ecx ; advance base in t + add ecx,edx + + mov ds:dword ptr[advancetable],ecx ; advance extra in t + mov ecx,ds:dword ptr[_a_tstepxfrac] + + mov cx,ds:word ptr[_r_lstepx] + mov edx,eax ; count + + mov ds:dword ptr[tstep],ecx + add edx,7 + + shr edx,3 ; count of full and partial loops + mov ebx,ds:dword ptr[spanpackage_t_sfrac+esi] + + mov bx,dx + mov ecx,ds:dword ptr[spanpackage_t_pz+esi] + + neg eax + + mov edi,ds:dword ptr[spanpackage_t_pdest+esi] + and eax,7 ; 0->0, 1->7, 2->6, ... , 7->1 + + sub edi,eax ; compensate for hardwired offsets + sub ecx,eax + + sub ecx,eax + mov edx,ds:dword ptr[spanpackage_t_tfrac+esi] + + mov dx,ds:word ptr[spanpackage_t_light+esi] + mov ebp,ds:dword ptr[spanpackage_t_zi+esi] + + ror ebp,16 ; put high 16 bits of 1/z in low word + push esi + + push eax + mov al, [_iractive] + cmp al, 0 + pop eax + jne IRInsert + + mov esi,ds:dword ptr[spanpackage_t_ptex+esi] + jmp dword ptr[aff8entryvec_table+eax*4] + +IRInsert: + mov esi,ds:dword ptr[spanpackage_t_ptex+esi] + add eax, 8 + jmp dword ptr[aff8entryvec_table+eax*4] + +; %bx = count of full and partial loops +; %ebx high word = sfrac +; %ecx = pz +; %dx = light +; %edx high word = tfrac +; %esi = ptex +; %edi = pdest +; %ebp = 1/z +; tstep low word = C(r_lstepx) +; tstep high word = C(a_tstepxfrac) +; C(a_sstepxfrac) low word = 0 +; C(a_sstepxfrac) high word = C(a_sstepxfrac) + +;=== +;Standard Draw Loop +;=== +LDrawLoop: + + mov al,[_iractive] + cmp al,0 + jne LDrawLoopIR + +; FIXME: do we need to clamp light? We may need at least a buffer bit to +; keep it from poking into tfrac and causing problems + +LDraw8: + cmp bp,ds:word ptr[ecx] + jl Lp1 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch8: + mov ds:byte ptr[edi],al +Lp1: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw7: + cmp bp,ds:word ptr[2+ecx] + jl Lp2 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[2+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch7: + mov ds:byte ptr[1+edi],al +Lp2: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw6: + cmp bp,ds:word ptr[4+ecx] + jl Lp3 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[4+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch6: + mov ds:byte ptr[2+edi],al +Lp3: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw5: + cmp bp,ds:word ptr[6+ecx] + jl Lp4 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[6+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch5: + mov ds:byte ptr[3+edi],al +Lp4: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw4: + cmp bp,ds:word ptr[8+ecx] + jl Lp5 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[8+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch4: + mov ds:byte ptr[4+edi],al +Lp5: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw3: + cmp bp,ds:word ptr[10+ecx] + jl Lp6 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[10+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch3: + mov ds:byte ptr[5+edi],al +Lp6: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw2: + cmp bp,ds:word ptr[12+ecx] + jl Lp7 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[12+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch2: + mov ds:byte ptr[6+edi],al +Lp7: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw1: + cmp bp,ds:word ptr[14+ecx] + jl Lp8 + xor eax,eax + mov ah,dh + mov al,ds:byte ptr[esi] + mov ds:word ptr[14+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch1: + mov ds:byte ptr[7+edi],al +Lp8: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + add edi,8 + add ecx,16 + + dec bx + jnz LDrawLoop + + pop esi ; restore spans pointer +LNextSpan: + add esi,offset spanpackage_t_size ; point to next span +LNextSpanESISet: + mov edx,ds:dword ptr[spanpackage_t_count+esi] + cmp edx,offset -999999 ; any more spans? + jnz LSpanLoop ; yes + + pop edi + pop ebp ; restore the caller's stack frame + pop ebx ; restore register variables + pop esi + ret + +;======= +; IR active draw loop +;======= +LDrawLoopIR: + +; FIXME: do we need to clamp light? We may need at least a buffer bit to +; keep it from poking into tfrac and causing problems + +LDraw8IR: + cmp bp,ds:word ptr[ecx] + jl Lp1IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch8IR: + mov ds:byte ptr[edi],al +Lp1IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw7IR: + cmp bp,ds:word ptr[2+ecx] + jl Lp2IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[2+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch7IR: + mov ds:byte ptr[1+edi],al +Lp2IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw6IR: + cmp bp,ds:word ptr[4+ecx] + jl Lp3IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[4+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch6IR: + mov ds:byte ptr[2+edi],al +Lp3IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw5IR: + cmp bp,ds:word ptr[6+ecx] + jl Lp4IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[6+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch5IR: + mov ds:byte ptr[3+edi],al +Lp4IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw4IR: + cmp bp,ds:word ptr[8+ecx] + jl Lp5IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[8+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch4IR: + mov ds:byte ptr[4+edi],al +Lp5IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw3IR: + cmp bp,ds:word ptr[10+ecx] + jl Lp6IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[10+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch3IR: + mov ds:byte ptr[5+edi],al +Lp6IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw2IR: + cmp bp,ds:word ptr[12+ecx] + jl Lp7IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[12+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch2IR: + mov ds:byte ptr[6+edi],al +Lp7IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LDraw1IR: + cmp bp,ds:word ptr[14+ecx] + jl Lp8IR + xor eax,eax + mov al,ds:byte ptr[esi] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[14+ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch1IR: + mov ds:byte ptr[7+edi],al +Lp8IR: + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebp,ds:dword ptr[lzistepx] + adc ebp,0 + add ebx,ds:dword ptr[_a_sstepxfrac] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + add edi,8 + add ecx,16 + + dec bx + jnz LDrawLoopIR + + pop esi ; restore spans pointer +LNextSpanIR: + add esi,offset spanpackage_t_size ; point to next span +LNextSpanESISetIR: + mov edx,ds:dword ptr[spanpackage_t_count+esi] + cmp edx,offset -999999 ; any more spans? + jnz LSpanLoop ; yes + + pop edi + pop ebp ; restore the caller's stack frame + pop ebx ; restore register variables + pop esi + ret + +;======= +; Standard One-Long Draw +;======= +; draw a one-long span + +LExactlyOneLong: + mov al,[_iractive] + cmp al,0 + jne LExactlyOneLongIR + + mov ecx,ds:dword ptr[spanpackage_t_pz+esi] + mov ebp,ds:dword ptr[spanpackage_t_zi+esi] + + ror ebp,16 ; put high 16 bits of 1/z in low word + mov ebx,ds:dword ptr[spanpackage_t_ptex+esi] + + cmp bp,ds:word ptr[ecx] + jl LNextSpan + xor eax,eax + mov edi,ds:dword ptr[spanpackage_t_pdest+esi] + mov ah,ds:byte ptr[spanpackage_t_light+1+esi] + add esi,offset spanpackage_t_size ; point to next span + mov al,ds:byte ptr[ebx] + mov ds:word ptr[ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch9: + mov ds:byte ptr[edi],al + + jmp LNextSpanESISet + + +;======== +;======== +; draw a one-long span + +LExactlyOneLongIR: + + mov ecx,ds:dword ptr[spanpackage_t_pz+esi] + mov ebp,ds:dword ptr[spanpackage_t_zi+esi] + + ror ebp,16 ; put high 16 bits of 1/z in low word + mov ebx,ds:dword ptr[spanpackage_t_ptex+esi] + + cmp bp,ds:word ptr[ecx] + jl LNextSpanIR + xor eax,eax + mov edi,ds:dword ptr[spanpackage_t_pdest+esi] + add esi,offset spanpackage_t_size ; point to next span + mov al,ds:byte ptr[ebx] + mov al,ds:byte ptr[_irtable+eax] + mov ds:word ptr[ecx],bp + mov al,ds:byte ptr[12345678h+eax] +LPatch9IR: + mov ds:byte ptr[edi],al + + jmp LNextSpanESISetIR + +;=================================== +;=================================== + public _D_Aff8Patch +_D_Aff8Patch: + mov eax,[_alias_colormap] + mov ds:dword ptr[LPatch1-4],eax + mov ds:dword ptr[LPatch2-4],eax + mov ds:dword ptr[LPatch3-4],eax + mov ds:dword ptr[LPatch4-4],eax + mov ds:dword ptr[LPatch5-4],eax + mov ds:dword ptr[LPatch6-4],eax + mov ds:dword ptr[LPatch7-4],eax + mov ds:dword ptr[LPatch8-4],eax + mov ds:dword ptr[LPatch9-4],eax + mov ds:dword ptr[LPatch1IR-4],eax + mov ds:dword ptr[LPatch2IR-4],eax + mov ds:dword ptr[LPatch3IR-4],eax + mov ds:dword ptr[LPatch4IR-4],eax + mov ds:dword ptr[LPatch5IR-4],eax + mov ds:dword ptr[LPatch6IR-4],eax + mov ds:dword ptr[LPatch7IR-4],eax + mov ds:dword ptr[LPatch8IR-4],eax + mov ds:dword ptr[LPatch9IR-4],eax + + ret + + + +;=================================== +;=================================== + +height equ 4+16 + + public _R_PolysetScanLeftEdge +_R_PolysetScanLeftEdge: + push ebp ; preserve caller stack frame pointer + push esi ; preserve register variables + push edi + push ebx + + mov eax,ds:dword ptr[height+esp] + mov ecx,ds:dword ptr[_d_sfrac] + + and eax,0FFFFh + mov ebx,ds:dword ptr[_d_ptex] + or ecx,eax + mov esi,ds:dword ptr[_d_pedgespanpackage] + mov edx,ds:dword ptr[_d_tfrac] + mov edi,ds:dword ptr[_d_light] + mov ebp,ds:dword ptr[_d_zi] + +; %eax: scratch +; %ebx: d_ptex +; %ecx: d_sfrac in high word, count in low word +; %edx: d_tfrac +; %esi: d_pedgespanpackage, errorterm, scratch alternately +; %edi: d_light +; %ebp: d_zi + +; do +; { + +LScanLoop: + +; d_pedgespanpackage->ptex = ptex; +; d_pedgespanpackage->pdest = d_pdest; +; d_pedgespanpackage->pz = d_pz; +; d_pedgespanpackage->count = d_aspancount; +; d_pedgespanpackage->light = d_light; +; d_pedgespanpackage->zi = d_zi; +; d_pedgespanpackage->sfrac = d_sfrac << 16; +; d_pedgespanpackage->tfrac = d_tfrac << 16; + mov ds:dword ptr[spanpackage_t_ptex+esi],ebx + mov eax,ds:dword ptr[_d_pdest] + mov ds:dword ptr[spanpackage_t_pdest+esi],eax + mov eax,ds:dword ptr[_d_pz] + mov ds:dword ptr[spanpackage_t_pz+esi],eax + mov eax,ds:dword ptr[_d_aspancount] + mov ds:dword ptr[spanpackage_t_count+esi],eax + mov ds:dword ptr[spanpackage_t_light+esi],edi + mov ds:dword ptr[spanpackage_t_zi+esi],ebp + mov ds:dword ptr[spanpackage_t_sfrac+esi],ecx + mov ds:dword ptr[spanpackage_t_tfrac+esi],edx + +; pretouch the next cache line + mov al,ds:byte ptr[spanpackage_t_size+esi] + +; d_pedgespanpackage++; + add esi,offset spanpackage_t_size + mov eax,ds:dword ptr[_erroradjustup] + mov ds:dword ptr[_d_pedgespanpackage],esi + +; errorterm += erroradjustup; + mov esi,ds:dword ptr[_errorterm] + add esi,eax + mov eax,ds:dword ptr[_d_pdest] + +; if (errorterm >= 0) +; { + js LNoLeftEdgeTurnover + +; errorterm -= erroradjustdown; +; d_pdest += d_pdestextrastep; + sub esi,ds:dword ptr[_erroradjustdown] + add eax,ds:dword ptr[_d_pdestextrastep] + mov ds:dword ptr[_errorterm],esi + mov ds:dword ptr[_d_pdest],eax + +; d_pz += d_pzextrastep; +; d_aspancount += d_countextrastep; +; d_ptex += d_ptexextrastep; +; d_sfrac += d_sfracextrastep; +; d_ptex += d_sfrac >> 16; +; d_sfrac &= 0xFFFF; +; d_tfrac += d_tfracextrastep; + mov eax,ds:dword ptr[_d_pz] + mov esi,ds:dword ptr[_d_aspancount] + add eax,ds:dword ptr[_d_pzextrastep] + add ecx,ds:dword ptr[_d_sfracextrastep] + adc ebx,ds:dword ptr[_d_ptexextrastep] + add esi,ds:dword ptr[_d_countextrastep] + mov ds:dword ptr[_d_pz],eax + mov eax,ds:dword ptr[_d_tfracextrastep] + mov ds:dword ptr[_d_aspancount],esi + add edx,eax + +; if (d_tfrac & 0x10000) +; { + jnc LSkip1 + +; d_ptex += r_affinetridesc.skinwidth; +; d_tfrac &= 0xFFFF; + add ebx,ds:dword ptr[_r_affinetridesc+atd_skinwidth] + +; } + +LSkip1: + +; d_light += d_lightextrastep; +; d_zi += d_ziextrastep; + add edi,ds:dword ptr[_d_lightextrastep] + add ebp,ds:dword ptr[_d_ziextrastep] + +; } + mov esi,ds:dword ptr[_d_pedgespanpackage] + dec ecx + test ecx,0FFFFh + jnz LScanLoop + + pop ebx + pop edi + pop esi + pop ebp + ret + +; else +; { + +LNoLeftEdgeTurnover: + mov ds:dword ptr[_errorterm],esi + +; d_pdest += d_pdestbasestep; + add eax,ds:dword ptr[_d_pdestbasestep] + mov ds:dword ptr[_d_pdest],eax + +; d_pz += d_pzbasestep; +; d_aspancount += ubasestep; +; d_ptex += d_ptexbasestep; +; d_sfrac += d_sfracbasestep; +; d_ptex += d_sfrac >> 16; +; d_sfrac &= 0xFFFF; + mov eax,ds:dword ptr[_d_pz] + mov esi,ds:dword ptr[_d_aspancount] + add eax,ds:dword ptr[_d_pzbasestep] + add ecx,ds:dword ptr[_d_sfracbasestep] + adc ebx,ds:dword ptr[_d_ptexbasestep] + add esi,ds:dword ptr[_ubasestep] + mov ds:dword ptr[_d_pz],eax + mov ds:dword ptr[_d_aspancount],esi + +; d_tfrac += d_tfracbasestep; + mov esi,ds:dword ptr[_d_tfracbasestep] + add edx,esi + +; if (d_tfrac & 0x10000) +; { + jnc LSkip2 + +; d_ptex += r_affinetridesc.skinwidth; +; d_tfrac &= 0xFFFF; + add ebx,ds:dword ptr[_r_affinetridesc+atd_skinwidth] + +; } + +LSkip2: + +; d_light += d_lightbasestep; +; d_zi += d_zibasestep; + add edi,ds:dword ptr[_d_lightbasestep] + add ebp,ds:dword ptr[_d_zibasestep] + +; } +; } while (--height); + mov esi,ds:dword ptr[_d_pedgespanpackage] + dec ecx + test ecx,0FFFFh + jnz LScanLoop + + pop ebx + pop edi + pop esi + pop ebp + ret + +_TEXT ENDS +endif ;id386 + END diff --git a/ref_soft/r_polyse.c b/ref_soft/r_polyse.c new file mode 100644 index 000000000..28088fe1d --- /dev/null +++ b/ref_soft/r_polyse.c @@ -0,0 +1,1539 @@ +/* +Copyright (C) 1997-2001 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_polyset.c: routines for drawing sets of polygons sharing the same +// texture (used for Alias models) + +#include "r_local.h" + +int rand1k[] = { +#include "rand1k.h" +}; + +#define MASK_1K 0x3FF + +int rand1k_index = 0; + +// TODO: put in span spilling to shrink list size +// !!! if this is changed, it must be changed in d_polysa.s too !!! +#define DPS_MAXSPANS MAXHEIGHT+1 + // 1 extra for spanpackage that marks end + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct { + void *pdest; + short *pz; + int count; + byte *ptex; + int sfrac, tfrac, light, zi; +} spanpackage_t; + +typedef struct { + int isflattop; + int numleftedges; + int *pleftedgevert0; + int *pleftedgevert1; + int *pleftedgevert2; + int numrightedges; + int *prightedgevert0; + int *prightedgevert1; + int *prightedgevert2; +} edgetable; + +aliastriangleparms_t aliastriangleparms; + +int r_p0[6], r_p1[6], r_p2[6]; + +byte *d_pcolormap; + +int d_aflatcolor; +int d_xdenom; + +edgetable *pedgetable; + +edgetable edgetables[12] = { + {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 }, + {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, + {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, + {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 }, + {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, + {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 }, + {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, + {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, + {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, + {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, +}; + +// FIXME: some of these can become statics +int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole; +int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy; +int r_zistepx, r_zistepy; +int d_aspancount, d_countextrastep; + +spanpackage_t *a_spans; +spanpackage_t *d_pedgespanpackage; +static int ystart; +byte *d_pdest, *d_ptex; +short *d_pz; +int d_sfrac, d_tfrac, d_light, d_zi; +int d_ptexextrastep, d_sfracextrastep; +int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; +int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; +int d_sfracbasestep, d_tfracbasestep; +int d_ziextrastep, d_zibasestep; +int d_pzextrastep, d_pzbasestep; + +typedef struct { + int quotient; + int remainder; +} adivtab_t; + +static adivtab_t adivtab[32*32] = { +#include "adivtab.h" +}; + +byte *skintable[MAX_LBM_HEIGHT]; +int skinwidth; +byte *skinstart; + +void (*d_pdrawspans)(spanpackage_t *pspanpackage); + +void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage); +void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage); +void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage); + +void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage); +void R_PolysetCalcGradients (int skinwidth); +void R_DrawNonSubdiv (void); +void R_PolysetSetEdgeTable (void); +void R_RasterizeAliasPolySmooth (void); +void R_PolysetScanLeftEdge(int height); +void R_PolysetScanLeftEdge_C(int height); + +// ====================== +// PGM +// 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 +byte iractive = 0; +byte irtable[256] = { 79, 78, 77, 76, 75, 74, 73, 72, // black/white + 71, 70, 69, 68, 67, 66, 65, 64, + 64, 65, 66, 67, 68, 69, 70, 71, // dark taupe + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // slate grey + 72, 73, 74, 75, 76, 77, 78, 79, + 208, 208, 208, 208, 208, 208, 208, 208, // unused?' + 64, 66, 68, 70, 72, 74, 76, 78, // dark yellow + + 64, 65, 66, 67, 68, 69, 70, 71, // dark red + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // grey/tan + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 66, 68, 70, 72, 74, 76, 78, // chocolate + 68, 67, 66, 65, 64, 65, 66, 67, // mauve / teal + 68, 69, 70, 71, 72, 73, 74, 75, + 76, 76, 77, 77, 78, 78, 79, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // more mauve + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // olive + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // maroon + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // sky blue + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // olive again + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // nuclear green + 64, 65, 66, 67, 68, 69, 70, 71, // bright yellow + + 64, 65, 66, 67, 68, 69, 70, 71, // fire colors + 72, 73, 74, 75, 76, 77, 78, 79, + 208, 208, 64, 64, 70, 71, 72, 64, // mishmash1 + 66, 68, 70, 64, 65, 66, 67, 68}; // mishmash2 +// PGM +// ====================== + +/* +================ +R_PolysetUpdateTables +================ +*/ +void R_PolysetUpdateTables (void) +{ + int i; + byte *s; + + if (r_affinetridesc.skinwidth != skinwidth || + r_affinetridesc.pskin != skinstart) + { + skinwidth = r_affinetridesc.skinwidth; + skinstart = r_affinetridesc.pskin; + s = skinstart; + for (i=0 ; iv[1] - aliastriangleparms.b->v[1] ) * ( aliastriangleparms.a->v[0] - aliastriangleparms.c->v[0] ) - + ( aliastriangleparms.a->v[0] - aliastriangleparms.b->v[0] ) * ( aliastriangleparms.a->v[1] - aliastriangleparms.c->v[1] ); + */ + + dv0_ab = aliastriangleparms.a->u - aliastriangleparms.b->u; + dv1_ab = aliastriangleparms.a->v - aliastriangleparms.b->v; + + if ( !( dv0_ab | dv1_ab ) ) + return; + + dv0_ac = aliastriangleparms.a->u - aliastriangleparms.c->u; + dv1_ac = aliastriangleparms.a->v - aliastriangleparms.c->v; + + if ( !( dv0_ac | dv1_ac ) ) + return; + + d_xdenom = ( dv0_ac * dv1_ab ) - ( dv0_ab * dv1_ac ); + + if ( d_xdenom < 0 ) + { + a_spans = spans; + + r_p0[0] = aliastriangleparms.a->u; // u + r_p0[1] = aliastriangleparms.a->v; // v + r_p0[2] = aliastriangleparms.a->s; // s + r_p0[3] = aliastriangleparms.a->t; // t + r_p0[4] = aliastriangleparms.a->l; // light + r_p0[5] = aliastriangleparms.a->zi; // iz + + r_p1[0] = aliastriangleparms.b->u; + r_p1[1] = aliastriangleparms.b->v; + r_p1[2] = aliastriangleparms.b->s; + r_p1[3] = aliastriangleparms.b->t; + r_p1[4] = aliastriangleparms.b->l; + r_p1[5] = aliastriangleparms.b->zi; + + r_p2[0] = aliastriangleparms.c->u; + r_p2[1] = aliastriangleparms.c->v; + r_p2[2] = aliastriangleparms.c->s; + r_p2[3] = aliastriangleparms.c->t; + r_p2[4] = aliastriangleparms.c->l; + r_p2[5] = aliastriangleparms.c->zi; + + R_PolysetSetEdgeTable (); + R_RasterizeAliasPolySmooth (); + } +} + + +/* +=================== +R_PolysetScanLeftEdge_C +==================== +*/ +void R_PolysetScanLeftEdge_C(int height) +{ + do + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_pdest += d_pdestextrastep; + d_pz += d_pzextrastep; + d_aspancount += d_countextrastep; + d_ptex += d_ptexextrastep; + d_sfrac += d_sfracextrastep; + d_ptex += d_sfrac >> 16; + + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracextrastep; + if (d_tfrac & 0x10000) + { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightextrastep; + d_zi += d_ziextrastep; + errorterm -= erroradjustdown; + } + else + { + d_pdest += d_pdestbasestep; + d_pz += d_pzbasestep; + d_aspancount += ubasestep; + d_ptex += d_ptexbasestep; + d_sfrac += d_sfracbasestep; + d_ptex += d_sfrac >> 16; + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracbasestep; + if (d_tfrac & 0x10000) + { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightbasestep; + d_zi += d_zibasestep; + } + } while (--height); +} + +/* +=================== +FloorDivMod + +Returns mathematically correct (floor-based) quotient and remainder for +numer and denom, both of which should contain no fractional part. The +quotient must fit in 32 bits. +FIXME: GET RID OF THIS! (FloorDivMod) +==================== +*/ +void FloorDivMod (float numer, float denom, int *quotient, + int *rem) +{ + int q, r; + float x; + + if (numer >= 0.0) + { + + x = floor(numer / denom); + q = (int)x; + r = (int)floor(numer - (x * denom)); + } + else + { + // + // perform operations with positive values, and fix mod to make floor-based + // + x = floor(-numer / denom); + q = -(int)x; + r = (int)floor(-numer - (x * denom)); + if (r != 0) + { + q--; + r = (int)denom - r; + } + } + + *quotient = q; + *rem = r; +} + + +/* +=================== +R_PolysetSetUpForLineScan +==================== +*/ +void R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, + fixed8_t endvertu, fixed8_t endvertv) +{ + float dm, dn; + int tm, tn; + adivtab_t *ptemp; + +// TODO: implement x86 version + + errorterm = -1; + + tm = endvertu - startvertu; + tn = endvertv - startvertv; + + if (((tm <= 16) && (tm >= -15)) && + ((tn <= 16) && (tn >= -15))) + { + ptemp = &adivtab[((tm+15) << 5) + (tn+15)]; + ubasestep = ptemp->quotient; + erroradjustup = ptemp->remainder; + erroradjustdown = tn; + } + else + { + dm = tm; + dn = tn; + + FloorDivMod (dm, dn, &ubasestep, &erroradjustup); + + erroradjustdown = dn; + } +} + + + +/* +================ +R_PolysetCalcGradients +================ +*/ +#if id386 && !defined __linux__ +void R_PolysetCalcGradients( int skinwidth ) +{ + static float xstepdenominv, ystepdenominv, t0, t1; + static float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; + static float one = 1.0F, negative_one = -1.0F; + static unsigned long t0_int, t1_int; + + extern unsigned long fpu_sp24_ceil_cw, fpu_ceil_cw, fpu_chop_cw; + + /* + p00_minus_p20 = r_p0[0] - r_p2[0]; + p01_minus_p21 = r_p0[1] - r_p2[1]; + p10_minus_p20 = r_p1[0] - r_p2[0]; + p11_minus_p21 = r_p1[1] - r_p2[1]; + */ + + __asm mov eax, dword ptr [r_p0+0] + __asm mov ebx, dword ptr [r_p0+4] + __asm sub eax, dword ptr [r_p2+0] + __asm sub ebx, dword ptr [r_p2+4] + __asm mov p00_minus_p20, eax + __asm mov p01_minus_p21, ebx + __asm fild dword ptr p00_minus_p20 + __asm fild dword ptr p01_minus_p21 + __asm mov eax, dword ptr [r_p1+0] + __asm mov ebx, dword ptr [r_p1+4] + __asm sub eax, dword ptr [r_p2+0] + __asm sub ebx, dword ptr [r_p2+4] + __asm fstp p01_minus_p21 + __asm fstp p00_minus_p20 + __asm mov p10_minus_p20, eax + __asm mov p11_minus_p21, ebx + __asm fild dword ptr p10_minus_p20 + __asm fild dword ptr p11_minus_p21 + __asm fstp p11_minus_p21 + __asm fstp p10_minus_p20 + + /* + xstepdenominv = 1.0 / (float)d_xdenom; + + ystepdenominv = -xstepdenominv; + */ + + /* + ** put FPU in single precision ceil mode + */ + __asm fldcw word ptr [fpu_sp24_ceil_cw] +// __asm fldcw word ptr [fpu_ceil_cw] + + __asm fild dword ptr d_xdenom ; d_xdenom + __asm fdivr one ; 1 / d_xdenom + __asm fst xstepdenominv ; + __asm fmul negative_one ; -( 1 / d_xdenom ) + +// ceil () for light so positive steps are exaggerated, negative steps +// diminished, pushing us away from underflow toward overflow. Underflow is +// very visible, overflow is very unlikely, because of ambient lighting + /* + t0 = r_p0[4] - r_p2[4]; + t1 = r_p1[4] - r_p2[4]; + r_lstepx = (int) + ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); + r_lstepy = (int) + ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+16] + __asm mov ebx, dword ptr [r_p1+16] + __asm sub eax, dword ptr [r_p2+16] + __asm sub ebx, dword ptr [r_p2+16] + + __asm fstp ystepdenominv ; (empty) + + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; t1 + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_lstepx] + __asm fistp dword ptr [r_lstepy] + + /* + ** put FPU back into extended precision chop mode + */ + __asm fldcw word ptr [fpu_chop_cw] + + /* + t0 = r_p0[2] - r_p2[2]; + t1 = r_p1[2] - r_p2[2]; + r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * + ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+8] + __asm mov ebx, dword ptr [r_p1+8] + __asm sub eax, dword ptr [r_p2+8] + __asm sub ebx, dword ptr [r_p2+8] + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; (empty) + + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_sstepx] + __asm fistp dword ptr [r_sstepy] + + /* + t0 = r_p0[3] - r_p2[3]; + t1 = r_p1[3] - r_p2[3]; + r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+12] + __asm mov ebx, dword ptr [r_p1+12] + __asm sub eax, dword ptr [r_p2+12] + __asm sub ebx, dword ptr [r_p2+12] + + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; (empty) + + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_tstepx] + __asm fistp dword ptr [r_tstepy] + + /* + t0 = r_p0[5] - r_p2[5]; + t1 = r_p1[5] - r_p2[5]; + r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+20] + __asm mov ebx, dword ptr [r_p1+20] + __asm sub eax, dword ptr [r_p2+20] + __asm sub ebx, dword ptr [r_p2+20] + + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; (empty) + + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_zistepx] + __asm fistp dword ptr [r_zistepy] + + /* +#if id386ALIAS + a_sstepxfrac = r_sstepx << 16; + a_tstepxfrac = r_tstepx << 16; +#else + a_sstepxfrac = r_sstepx & 0xFFFF; + a_tstepxfrac = r_tstepx & 0xFFFF; +#endif + */ + __asm mov eax, d_pdrawspans + __asm cmp eax, offset R_PolysetDrawSpans8_Opaque + __asm mov eax, r_sstepx + __asm mov ebx, r_tstepx + __asm jne translucent +//#if id386ALIAS + __asm shl eax, 16 + __asm shl ebx, 16 + __asm jmp done_with_steps +//#else +translucent: + __asm and eax, 0ffffh + __asm and ebx, 0ffffh +//#endif +done_with_steps: + __asm mov a_sstepxfrac, eax + __asm mov a_tstepxfrac, ebx + + /* + a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); + */ + __asm mov ebx, r_tstepx + __asm mov ecx, r_sstepx + __asm sar ebx, 16 + __asm mov eax, skinwidth + __asm mul ebx + __asm sar ecx, 16 + __asm add eax, ecx + __asm mov a_ststepxwhole, eax +} +#else +void R_PolysetCalcGradients (int skinwidth) +{ + float xstepdenominv, ystepdenominv, t0, t1; + float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; + + p00_minus_p20 = r_p0[0] - r_p2[0]; + p01_minus_p21 = r_p0[1] - r_p2[1]; + p10_minus_p20 = r_p1[0] - r_p2[0]; + p11_minus_p21 = r_p1[1] - r_p2[1]; + + xstepdenominv = 1.0 / (float)d_xdenom; + + ystepdenominv = -xstepdenominv; + +// ceil () for light so positive steps are exaggerated, negative steps +// diminished, pushing us away from underflow toward overflow. Underflow is +// very visible, overflow is very unlikely, because of ambient lighting + t0 = r_p0[4] - r_p2[4]; + t1 = r_p1[4] - r_p2[4]; + r_lstepx = (int) + ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); + r_lstepy = (int) + ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + + t0 = r_p0[2] - r_p2[2]; + t1 = r_p1[2] - r_p2[2]; + r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[3] - r_p2[3]; + t1 = r_p1[3] - r_p2[3]; + r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[5] - r_p2[5]; + t1 = r_p1[5] - r_p2[5]; + r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + a_sstepxfrac = r_sstepx << 16; + a_tstepxfrac = r_tstepx << 16; + } + else +#endif + { +//#else + a_sstepxfrac = r_sstepx & 0xFFFF; + a_tstepxfrac = r_tstepx & 0xFFFF; + } +//#endif + + a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); +} +#endif + +/* +================ +R_PolysetDrawThreshSpans8 + +Random fizzle fade rasterizer +================ +*/ +void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + rand1k_index = (rand1k_index + 1) & MASK_1K; + + if (rand1k[rand1k_index] <= r_affinetridesc.vis_thresh) + { + *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; + *lpz = lzi >> 16; + } + } + + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + + +/* +================ +R_PolysetDrawSpans8 +================ +*/ +void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + int temp = vid.colormap[*lptex + ( llight & 0xFF00 )]; + + *lpdest = vid.alphamap[temp+ *lpdest*256]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lpz = pspanpackage->pz; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + *lpdest = vid.alphamap[r_aliasblendcolor + *lpdest*256]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + int temp = vid.colormap[*lptex + ( llight & 0xFF00 )]; + + *lpdest = vid.alphamap[temp*256 + *lpdest]; + *lpz = lzi >> 16; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lpz = pspanpackage->pz; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + *lpdest = vid.alphamap[r_aliasblendcolor*256 + *lpdest]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +#if !id386 +void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage) +{ + int lcount; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + int lsfrac, ltfrac; + byte *lpdest; + byte *lptex; + int llight; + int lzi; + short *lpz; + + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { +//PGM + if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE) + *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; + else + *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; +//PGM + *lpz = lzi >> 16; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} +#endif + + +/* +================ +R_PolysetFillSpans8 +================ +*/ +void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) +{ + int color; + +// FIXME: do z buffering + + color = d_aflatcolor++; + + while (1) + { + int lcount; + byte *lpdest; + + lcount = pspanpackage->count; + + if (lcount == -1) + return; + + if (lcount) + { + lpdest = pspanpackage->pdest; + + do + { + *lpdest++ = color; + } while (--lcount); + } + + pspanpackage++; + } +} + +/* +================ +R_RasterizeAliasPolySmooth +================ +*/ +void R_RasterizeAliasPolySmooth (void) +{ + int initialleftheight, initialrightheight; + int *plefttop, *prighttop, *pleftbottom, *prightbottom; + int working_lstepx, originalcount; + + plefttop = pedgetable->pleftedgevert0; + prighttop = pedgetable->prightedgevert0; + + pleftbottom = pedgetable->pleftedgevert1; + prightbottom = pedgetable->prightedgevert1; + + initialleftheight = pleftbottom[1] - plefttop[1]; + initialrightheight = prightbottom[1] - prighttop[1]; + +// +// set the s, t, and light gradients, which are consistent across the triangle +// because being a triangle, things are affine +// + R_PolysetCalcGradients (r_affinetridesc.skinwidth); +// +// rasterize the polygon +// + +// +// scan out the top (and possibly only) part of the left edge +// + d_pedgespanpackage = a_spans; + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + + d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfrac = (plefttop[2] & 0xFFFF) << 16; + d_tfrac = (plefttop[3] & 0xFFFF) << 16; + } +//#else + else +#endif + { + d_sfrac = plefttop[2] & 0xFFFF; + d_tfrac = plefttop[3] & 0xFFFF; + } +//#endif + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdest = (byte *)d_viewbuffer + + ystart * r_screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (initialleftheight == 1) + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + } + else + { + R_PolysetSetUpForLineScan(plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_pzbasestep = (d_zwidth + ubasestep) << 1; + d_pzextrastep = d_pzbasestep + 2; + } +//#else + else +#endif + { + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + } +//#endif + + d_pdestbasestep = r_screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + + // TODO: can reuse partial expressions here + + // for negative steps in x along left edge, bias toward overflow rather than + // underflow (sort of turning the floor () we did in the gradient calcs into + // ceil (), but plus a little bit) + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; + } + else +#endif + { +//#else + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + } +//#endif + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16; + d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16; + } + else +#endif + { +//#else + d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF; + } +//#endif + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + R_PolysetScanLeftEdge (initialleftheight); + } + else +#endif + { + R_PolysetScanLeftEdge_C(initialleftheight); + } + } + +// +// scan out the bottom part of the left edge, if it exists +// + if (pedgetable->numleftedges == 2) + { + int height; + + plefttop = pleftbottom; + pleftbottom = pedgetable->pleftedgevert2; + + height = pleftbottom[1] - plefttop[1]; + +// TODO: make this a function; modularize this function in general + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + d_sfrac = 0; + d_tfrac = 0; + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdest = (byte *)d_viewbuffer + ystart * r_screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (height == 1) + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + } + else + { + R_PolysetSetUpForLineScan(plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + + d_pdestbasestep = r_screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_pzbasestep = (d_zwidth + ubasestep) << 1; + d_pzextrastep = d_pzbasestep + 2; + } +//#else + else +#endif + { + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + } +//#endif + + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; + } +//#else + else +#endif + { + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + } +//#endif + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16; + d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16; + } + else +#endif +//#endif + { + d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF; + } +//#endif + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + R_PolysetScanLeftEdge (height); + } + else +#endif + { + R_PolysetScanLeftEdge_C(height); + } + } + } + +// scan out the top (and possibly only) part of the right edge, updating the +// count field + d_pedgespanpackage = a_spans; + + R_PolysetSetUpForLineScan(prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + d_aspancount = 0; + d_countextrastep = ubasestep + 1; + originalcount = a_spans[initialrightheight].count; + a_spans[initialrightheight].count = -999999; // mark end of the spanpackages + (*d_pdrawspans) (a_spans); + +// scan out the bottom part of the right edge, if it exists + if (pedgetable->numrightedges == 2) + { + int height; + spanpackage_t *pstart; + + pstart = a_spans + initialrightheight; + pstart->count = originalcount; + + d_aspancount = prightbottom[0] - prighttop[0]; + + prighttop = prightbottom; + prightbottom = pedgetable->prightedgevert2; + + height = prightbottom[1] - prighttop[1]; + + R_PolysetSetUpForLineScan(prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + + d_countextrastep = ubasestep + 1; + a_spans[initialrightheight + height].count = -999999; + // mark end of the spanpackages + (*d_pdrawspans) (pstart); + } +} + + +/* +================ +R_PolysetSetEdgeTable +================ +*/ +void R_PolysetSetEdgeTable (void) +{ + int edgetableindex; + + edgetableindex = 0; // assume the vertices are already in + // top to bottom order + +// +// determine which edges are right & left, and the order in which +// to rasterize them +// + if (r_p0[1] >= r_p1[1]) + { + if (r_p0[1] == r_p1[1]) + { + if (r_p0[1] < r_p2[1]) + pedgetable = &edgetables[2]; + else + pedgetable = &edgetables[5]; + + return; + } + else + { + edgetableindex = 1; + } + } + + if (r_p0[1] == r_p2[1]) + { + if (edgetableindex) + pedgetable = &edgetables[8]; + else + pedgetable = &edgetables[9]; + + return; + } + else if (r_p1[1] == r_p2[1]) + { + if (edgetableindex) + pedgetable = &edgetables[10]; + else + pedgetable = &edgetables[11]; + + return; + } + + if (r_p0[1] > r_p2[1]) + edgetableindex += 2; + + if (r_p1[1] > r_p2[1]) + edgetableindex += 4; + + pedgetable = &edgetables[edgetableindex]; +} + + diff --git a/ref_soft/r_rast.c b/ref_soft/r_rast.c new file mode 100644 index 000000000..ddcb5dfb4 --- /dev/null +++ b/ref_soft/r_rast.c @@ -0,0 +1,852 @@ +/* +Copyright (C) 1997-2001 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_rast.c + +#include + +#include "r_local.h" + +#define MAXLEFTCLIPEDGES 100 + +// !!! if these are changed, they must be changed in asm_draw.h too !!! +#define FULLY_CLIPPED_CACHED 0x80000000 +#define FRAMECOUNT_MASK 0x7FFFFFFF + +unsigned int cacheoffset; + +int c_faceclip; // number of faces clipped + + +clipplane_t *entity_clipplanes; +clipplane_t view_clipplanes[4]; +clipplane_t world_clipplanes[16]; + +medge_t *r_pedge; + +qboolean r_leftclipped, r_rightclipped; +static qboolean makeleftedge, makerightedge; +qboolean r_nearzionly; + +int sintable[1280]; +int intsintable[1280]; +int blanktable[1280]; // PGM + +mvertex_t r_leftenter, r_leftexit; +mvertex_t r_rightenter, r_rightexit; + +typedef struct +{ + float u,v; + int ceilv; +} evert_t; + +int r_emitted; +float r_nearzi; +float r_u1, r_v1, r_lzi1; +int r_ceilv1; + +qboolean r_lastvertvalid; +int r_skyframe; + +msurface_t *r_skyfaces; +mplane_t r_skyplanes[6]; +mtexinfo_t r_skytexinfo[6]; +mvertex_t *r_skyverts; +medge_t *r_skyedges; +int *r_skysurfedges; + +// I just copied this data from a box map... +int skybox_planes[12] = {2,-128, 0,-128, 2,128, 1,128, 0,128, 1,-128}; + +int box_surfedges[24] = { 1,2,3,4, -1,5,6,7, 8,9,-6,10, -2,-7,-9,11, + 12,-3,-11,-8, -12,-10,-5,-4}; +int box_edges[24] = { 1,2, 2,3, 3,4, 4,1, 1,5, 5,6, 6,2, 7,8, 8,6, 5,7, 8,3, 7,4}; + +int box_faces[6] = {0,0,2,2,2,0}; + +vec3_t box_vecs[6][2] = { + { {0,-1,0}, {-1,0,0} }, + { {0,1,0}, {0,0,-1} }, + { {0,-1,0}, {1,0,0} }, + { {1,0,0}, {0,0,-1} }, + { {0,-1,0}, {0,0,-1} }, + { {-1,0,0}, {0,0,-1} } +}; + +float box_verts[8][3] = { + {-1,-1,-1}, + {-1,1,-1}, + {1,1,-1}, + {1,-1,-1}, + {-1,-1,1}, + {-1,1,1}, + {1,-1,1}, + {1,1,1} +}; + +// down, west, up, north, east, south +// {"rt", "bk", "lf", "ft", "up", "dn"}; + +/* +================ +R_InitSkyBox + +================ +*/ +void R_InitSkyBox (void) +{ + int i; + extern model_t *loadmodel; + + r_skyfaces = loadmodel->surfaces + loadmodel->numsurfaces; + loadmodel->numsurfaces += 6; + r_skyverts = loadmodel->vertexes + loadmodel->numvertexes; + loadmodel->numvertexes += 8; + r_skyedges = loadmodel->edges + loadmodel->numedges; + loadmodel->numedges += 12; + r_skysurfedges = loadmodel->surfedges + loadmodel->numsurfedges; + loadmodel->numsurfedges += 24; + if (loadmodel->numsurfaces > MAX_MAP_FACES + || loadmodel->numvertexes > MAX_MAP_VERTS + || loadmodel->numedges > MAX_MAP_EDGES) + ri.Sys_Error (ERR_DROP, "InitSkyBox: map overflow"); + + memset (r_skyfaces, 0, 6*sizeof(*r_skyfaces)); + for (i=0 ; i<6 ; i++) + { + r_skyplanes[i].normal[skybox_planes[i*2]] = 1; + r_skyplanes[i].dist = skybox_planes[i*2+1]; + + VectorCopy (box_vecs[i][0], r_skytexinfo[i].vecs[0]); + VectorCopy (box_vecs[i][1], r_skytexinfo[i].vecs[1]); + + r_skyfaces[i].plane = &r_skyplanes[i]; + r_skyfaces[i].numedges = 4; + r_skyfaces[i].flags = box_faces[i] | SURF_DRAWSKYBOX; + r_skyfaces[i].firstedge = loadmodel->numsurfedges-24+i*4; + r_skyfaces[i].texinfo = &r_skytexinfo[i]; + r_skyfaces[i].texturemins[0] = -128; + r_skyfaces[i].texturemins[1] = -128; + r_skyfaces[i].extents[0] = 256; + r_skyfaces[i].extents[1] = 256; + } + + for (i=0 ; i<24 ; i++) + if (box_surfedges[i] > 0) + r_skysurfedges[i] = loadmodel->numedges-13 + box_surfedges[i]; + else + r_skysurfedges[i] = - (loadmodel->numedges-13 + -box_surfedges[i]); + + for(i=0 ; i<12 ; i++) + { + r_skyedges[i].v[0] = loadmodel->numvertexes-9+box_edges[i*2+0]; + r_skyedges[i].v[1] = loadmodel->numvertexes-9+box_edges[i*2+1]; + r_skyedges[i].cachededgeoffset = 0; + } +} + +/* +================ +R_EmitSkyBox +================ +*/ +void R_EmitSkyBox (void) +{ + int i, j; + int oldkey; + + if (insubmodel) + return; // submodels should never have skies + if (r_skyframe == r_framecount) + return; // already set this frame + + r_skyframe = r_framecount; + + // set the eight fake vertexes + for (i=0 ; i<8 ; i++) + for (j=0 ; j<3 ; j++) + r_skyverts[i].position[j] = r_origin[j] + box_verts[i][j]*128; + + // set the six fake planes + for (i=0 ; i<6 ; i++) + if (skybox_planes[i*2+1] > 0) + r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]+128; + else + r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]-128; + + // fix texture offseets + for (i=0 ; i<6 ; i++) + { + r_skytexinfo[i].vecs[0][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[0]); + r_skytexinfo[i].vecs[1][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[1]); + } + + // emit the six faces + oldkey = r_currentkey; + r_currentkey = 0x7ffffff0; + for (i=0 ; i<6 ; i++) + { + R_RenderFace (r_skyfaces + i, 15); + } + r_currentkey = oldkey; // bsp sorting order +} + + +#if !id386 + +/* +================ +R_EmitEdge +================ +*/ +void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) +{ + edge_t *edge, *pcheck; + int u_check; + float u, u_step; + vec3_t local, transformed; + float *world; + int v, v2, ceilv0; + float scale, lzi0, u0, v0; + int side; + + if (r_lastvertvalid) + { + u0 = r_u1; + v0 = r_v1; + lzi0 = r_lzi1; + ceilv0 = r_ceilv1; + } + else + { + world = &pv0->position[0]; + + // transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + lzi0 = 1.0 / transformed[2]; + + // FIXME: build x/yscale into transform? + scale = xscale * lzi0; + u0 = (xcenter + scale*transformed[0]); + if (u0 < r_refdef.fvrectx_adj) + u0 = r_refdef.fvrectx_adj; + if (u0 > r_refdef.fvrectright_adj) + u0 = r_refdef.fvrectright_adj; + + scale = yscale * lzi0; + v0 = (ycenter - scale*transformed[1]); + if (v0 < r_refdef.fvrecty_adj) + v0 = r_refdef.fvrecty_adj; + if (v0 > r_refdef.fvrectbottom_adj) + v0 = r_refdef.fvrectbottom_adj; + + ceilv0 = (int) ceil(v0); + } + + world = &pv1->position[0]; + +// transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + r_lzi1 = 1.0 / transformed[2]; + + scale = xscale * r_lzi1; + r_u1 = (xcenter + scale*transformed[0]); + if (r_u1 < r_refdef.fvrectx_adj) + r_u1 = r_refdef.fvrectx_adj; + if (r_u1 > r_refdef.fvrectright_adj) + r_u1 = r_refdef.fvrectright_adj; + + scale = yscale * r_lzi1; + r_v1 = (ycenter - scale*transformed[1]); + if (r_v1 < r_refdef.fvrecty_adj) + r_v1 = r_refdef.fvrecty_adj; + if (r_v1 > r_refdef.fvrectbottom_adj) + r_v1 = r_refdef.fvrectbottom_adj; + + if (r_lzi1 > lzi0) + lzi0 = r_lzi1; + + if (lzi0 > r_nearzi) // for mipmap finding + r_nearzi = lzi0; + +// for right edges, all we want is the effect on 1/z + if (r_nearzionly) + return; + + r_emitted = 1; + + r_ceilv1 = (int) ceil(r_v1); + + +// create the edge + if (ceilv0 == r_ceilv1) + { + // we cache unclipped horizontal edges as fully clipped + if (cacheoffset != 0x7FFFFFFF) + { + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + } + + return; // horizontal edge + } + + side = ceilv0 > r_ceilv1; + + edge = edge_p++; + + edge->owner = r_pedge; + + edge->nearzi = lzi0; + + if (side == 0) + { + // trailing edge (go from p1 to p2) + v = ceilv0; + v2 = r_ceilv1 - 1; + + edge->surfs[0] = surface_p - surfaces; + edge->surfs[1] = 0; + + u_step = ((r_u1 - u0) / (r_v1 - v0)); + u = u0 + ((float)v - v0) * u_step; + } + else + { + // leading edge (go from p2 to p1) + v2 = ceilv0 - 1; + v = r_ceilv1; + + edge->surfs[0] = 0; + edge->surfs[1] = surface_p - surfaces; + + u_step = ((u0 - r_u1) / (v0 - r_v1)); + u = r_u1 + ((float)v - r_v1) * u_step; + } + + edge->u_step = u_step*0x100000; + edge->u = u*0x100000 + 0xFFFFF; + +// we need to do this to avoid stepping off the edges if a very nearly +// horizontal edge is less than epsilon above a scan, and numeric error causes +// it to incorrectly extend to the scan, and the extension of the line goes off +// the edge of the screen +// FIXME: is this actually needed? + if (edge->u < r_refdef.vrect_x_adj_shift20) + edge->u = r_refdef.vrect_x_adj_shift20; + if (edge->u > r_refdef.vrectright_adj_shift20) + edge->u = r_refdef.vrectright_adj_shift20; + +// +// sort the edge in normally +// + u_check = edge->u; + if (edge->surfs[0]) + u_check++; // sort trailers after leaders + + if (!newedges[v] || newedges[v]->u >= u_check) + { + edge->next = newedges[v]; + newedges[v] = edge; + } + else + { + pcheck = newedges[v]; + while (pcheck->next && pcheck->next->u < u_check) + pcheck = pcheck->next; + edge->next = pcheck->next; + pcheck->next = edge; + } + + edge->nextremove = removeedges[v2]; + removeedges[v2] = edge; +} + + +/* +================ +R_ClipEdge +================ +*/ +void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) +{ + float d0, d1, f; + mvertex_t clipvert; + + if (clip) + { + do + { + d0 = DotProduct (pv0->position, clip->normal) - clip->dist; + d1 = DotProduct (pv1->position, clip->normal) - clip->dist; + + if (d0 >= 0) + { + // point 0 is unclipped + if (d1 >= 0) + { + // both points are unclipped + continue; + } + + // only point 1 is clipped + + // we don't cache clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) + { + r_leftclipped = true; + r_leftexit = clipvert; + } + else if (clip->rightedge) + { + r_rightclipped = true; + r_rightexit = clipvert; + } + + R_ClipEdge (pv0, &clipvert, clip->next); + return; + } + else + { + // point 0 is clipped + if (d1 < 0) + { + // both points are clipped + // we do cache fully clipped edges + if (!r_leftclipped) + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + return; + } + + // only point 0 is clipped + r_lastvertvalid = false; + + // we don't cache partially clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) + { + r_leftclipped = true; + r_leftenter = clipvert; + } + else if (clip->rightedge) + { + r_rightclipped = true; + r_rightenter = clipvert; + } + + R_ClipEdge (&clipvert, pv1, clip->next); + return; + } + } while ((clip = clip->next) != NULL); + } + +// add the edge + R_EmitEdge (pv0, pv1); +} + +#endif // !id386 + + +/* +================ +R_EmitCachedEdge +================ +*/ +void R_EmitCachedEdge (void) +{ + edge_t *pedge_t; + + pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset); + + if (!pedge_t->surfs[0]) + pedge_t->surfs[0] = surface_p - surfaces; + else + pedge_t->surfs[1] = surface_p - surfaces; + + if (pedge_t->nearzi > r_nearzi) // for mipmap finding + r_nearzi = pedge_t->nearzi; + + r_emitted = 1; +} + + +/* +================ +R_RenderFace +================ +*/ +void R_RenderFace (msurface_t *fa, int clipflags) +{ + int i, lindex; + unsigned mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t *pedges, tedge; + clipplane_t *pclip; + + // translucent surfaces are not drawn by the edge renderer + if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + { + fa->nextalphasurface = r_alpha_surfaces; + r_alpha_surfaces = fa; + return; + } + + // sky surfaces encountered in the world will cause the + // environment box surfaces to be emited + if ( fa->texinfo->flags & SURF_SKY ) + { + R_EmitSkyBox (); + return; + } + +// skip out if no more surfs + if ((surface_p) >= surf_max) + { + r_outofsurfaces++; + return; + } + +// ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + fa->numedges + 4) >= edge_max) + { + r_outofedges += fa->numedges; + return; + } + + c_faceclip++; + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; + pedges = currentmodel->edges; + r_lastvertvalid = false; + + for (i=0 ; inumedges ; i++) + { + lindex = currentmodel->surfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + + // if the edge is cached, we can just reuse the edge + if (!insubmodel) + { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) + { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) + { + r_lastvertvalid = false; + continue; + } + } + else + { + if ((((unsigned long)edge_p - (unsigned long)r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *)((unsigned long)r_edges + + r_pedge->cachededgeoffset))->owner == r_pedge)) + { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + + // assume it's cacheable + cacheoffset = (byte *)edge_p - (byte *)r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], + &r_pcurrentvertbase[r_pedge->v[1]], + pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + else + { + lindex = -lindex; + r_pedge = &pedges[lindex]; + // if the edge is cached, we can just reuse the edge + if (!insubmodel) + { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) + { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) + { + r_lastvertvalid = false; + continue; + } + } + else + { + // it's cached if the cached edge is valid and is owned + // by this medge_t + if ((((unsigned long)edge_p - (unsigned long)r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *)((unsigned long)r_edges + + r_pedge->cachededgeoffset))->owner == r_pedge)) + { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + + // assume it's cacheable + cacheoffset = (byte *)edge_p - (byte *)r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], + &r_pcurrentvertbase[r_pedge->v[0]], + pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + } + +// if there was a clip off the left edge, add that edge too +// FIXME: faster to do in screen space? +// FIXME: share clipped edges? + if (makeleftedge) + { + r_pedge = &tedge; + r_lastvertvalid = false; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + +// if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) + { + r_pedge = &tedge; + r_lastvertvalid = false; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + +// if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + r_polycount++; + + surface_p->msurf = fa; + surface_p->nearzi = r_nearzi; + surface_p->flags = fa->flags; + surface_p->insubmodel = insubmodel; + surface_p->spanstate = 0; + surface_p->entity = currententity; + surface_p->key = r_currentkey++; + surface_p->spans = NULL; + + pplane = fa->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - + ycenter * surface_p->d_zistepv; + + surface_p++; +} + + +/* +================ +R_RenderBmodelFace +================ +*/ +void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) +{ + int i; + unsigned mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t tedge; + clipplane_t *pclip; + + if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + { + psurf->nextalphasurface = r_alpha_surfaces; + r_alpha_surfaces = psurf; + return; + } + +// skip out if no more surfs + if (surface_p >= surf_max) + { + r_outofsurfaces++; + return; + } + +// ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + psurf->numedges + 4) >= edge_max) + { + r_outofedges += psurf->numedges; + return; + } + + c_faceclip++; + +// this is a dummy to give the caching mechanism someplace to write to + r_pedge = &tedge; + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (r_clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; +// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching +// can be used? + r_lastvertvalid = false; + + for ( ; pedges ; pedges = pedges->pnext) + { + r_leftclipped = r_rightclipped = false; + R_ClipEdge (pedges->v[0], pedges->v[1], pclip); + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + } + +// if there was a clip off the left edge, add that edge too +// FIXME: faster to do in screen space? +// FIXME: share clipped edges? + if (makeleftedge) + { + r_pedge = &tedge; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + +// if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) + { + r_pedge = &tedge; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + +// if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + r_polycount++; + + surface_p->msurf = psurf; + surface_p->nearzi = r_nearzi; + surface_p->flags = psurf->flags; + surface_p->insubmodel = true; + surface_p->spanstate = 0; + surface_p->entity = currententity; + surface_p->key = r_currentbkey; + surface_p->spans = NULL; + + pplane = psurf->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - + ycenter * surface_p->d_zistepv; + + surface_p++; +} + diff --git a/ref_soft/r_scan.c b/ref_soft/r_scan.c new file mode 100644 index 000000000..af95576d5 --- /dev/null +++ b/ref_soft/r_scan.c @@ -0,0 +1,591 @@ +/* +Copyright (C) 1997-2001 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 "r_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, u2, v2; + byte *dest; + int *turb; + int *col; + byte **row; + + static int cached_width, cached_height; + static byte *rowptr[1200+AMP2*2]; + static int column[1600+AMP2*2]; + + // + // these are constant over resolutions, and can be saved + // + w = r_newrefdef.width; + h = r_newrefdef.height; + if (w != cached_width || h != cached_height) + { + cached_width = w; + cached_height = h; + for (v=0 ; v>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)(r_newrefdef.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 + + (r_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); +} + +//==================== +//PGM +/* +============= +NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures + but the turbulence is automatically 0. +============= +*/ +void NonTurbulent8 (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)(r_newrefdef.time*SPEED)&(CYCLE-1)); + r_turb_turb = blanktable; + + 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 + + (r_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); +} +//PGM +//==================== + + +#if !id386 + +/* +============= +D_DrawSpans16 + + FIXME: actually make this subdivide by 16 instead of 8!!! +============= +*/ +void D_DrawSpans16 (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 + + (r_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; + float 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 + diff --git a/ref_soft/r_scana.asm b/ref_soft/r_scana.asm new file mode 100644 index 000000000..1b0058061 --- /dev/null +++ b/ref_soft/r_scana.asm @@ -0,0 +1,73 @@ + .386P + .model FLAT +; +; d_scana.s +; x86 assembly-language turbulent texture mapping code +; + +include qasm.inc +include d_if.inc + +if id386 + +_DATA SEGMENT + +_DATA ENDS +_TEXT SEGMENT + +;---------------------------------------------------------------------- +; turbulent texture mapping code +;---------------------------------------------------------------------- + + align 4 + public _D_DrawTurbulent8Span +_D_DrawTurbulent8Span: + push ebp ; preserve caller's stack frame pointer + push esi ; preserve register variables + push edi + push ebx + + mov esi,ds:dword ptr[_r_turb_s] + mov ecx,ds:dword ptr[_r_turb_t] + mov edi,ds:dword ptr[_r_turb_pdest] + mov ebx,ds:dword ptr[_r_turb_spancount] + +Llp: + mov eax,ecx + mov edx,esi + sar eax,16 + mov ebp,ds:dword ptr[_r_turb_turb] + sar edx,16 + and eax,offset CYCLE-1 + and edx,offset CYCLE-1 + mov eax,ds:dword ptr[ebp+eax*4] + mov edx,ds:dword ptr[ebp+edx*4] + add eax,esi + sar eax,16 + add edx,ecx + sar edx,16 + and eax,offset TURB_TEX_SIZE-1 + and edx,offset TURB_TEX_SIZE-1 + shl edx,6 + mov ebp,ds:dword ptr[_r_turb_pbase] + add edx,eax + inc edi + add esi,ds:dword ptr[_r_turb_sstep] + add ecx,ds:dword ptr[_r_turb_tstep] + mov dl,ds:byte ptr[ebp+edx*1] + dec ebx + mov ds:byte ptr[-1+edi],dl + jnz Llp + + mov ds:dword ptr[_r_turb_pdest],edi + + pop ebx ; restore register variables + pop edi + pop esi + pop ebp ; restore caller's stack frame pointer + ret + + +_TEXT ENDS +endif ;id386 + END diff --git a/ref_soft/r_spr8.asm b/ref_soft/r_spr8.asm new file mode 100644 index 000000000..7b06b25c0 --- /dev/null +++ b/ref_soft/r_spr8.asm @@ -0,0 +1,884 @@ + .386P + .model FLAT +; +; d_spr8.s +; x86 assembly-language horizontal 8-bpp transparent span-drawing code. +; + +include qasm.inc +include d_if.inc + +if id386 + +;---------------------------------------------------------------------- +; 8-bpp horizontal span drawing code for polygons, with transparency. +;---------------------------------------------------------------------- + +_TEXT SEGMENT + +; out-of-line, rarely-needed clamping code + +LClampHigh0: + mov esi,ds:dword ptr[_bbextents] + jmp LClampReentry0 +LClampHighOrLow0: + jg LClampHigh0 + xor esi,esi + jmp LClampReentry0 + +LClampHigh1: + mov edx,ds:dword ptr[_bbextentt] + jmp LClampReentry1 +LClampHighOrLow1: + jg LClampHigh1 + xor edx,edx + jmp LClampReentry1 + +LClampLow2: + mov ebp,2048 + jmp LClampReentry2 +LClampHigh2: + mov ebp,ds:dword ptr[_bbextents] + jmp LClampReentry2 + +LClampLow3: + mov ecx,2048 + jmp LClampReentry3 +LClampHigh3: + mov ecx,ds:dword ptr[_bbextentt] + jmp LClampReentry3 + +LClampLow4: + mov eax,2048 + jmp LClampReentry4 +LClampHigh4: + mov eax,ds:dword ptr[_bbextents] + jmp LClampReentry4 + +LClampLow5: + mov ebx,2048 + jmp LClampReentry5 +LClampHigh5: + mov ebx,ds:dword ptr[_bbextentt] + jmp LClampReentry5 + + +pspans equ 4+16 + + align 4 + public _D_SpriteDrawSpansXXX +_D_SpriteDrawSpansXXX: + push ebp ; preserve caller's stack frame + push edi + push esi ; preserve register variables + push ebx + +; +; set up scaled-by-8 steps, for 8-long segments; also set up cacheblock +; and span list pointers, and 1/z step in 0.32 fixed-point +; +; FIXME: any overlap from rearranging? + fld ds:dword ptr[_d_sdivzstepu] + fmul ds:dword ptr[fp_8] + mov edx,ds:dword ptr[_cacheblock] + fld ds:dword ptr[_d_tdivzstepu] + fmul ds:dword ptr[fp_8] + mov ebx,ds:dword ptr[pspans+esp] ; point to the first span descriptor + fld ds:dword ptr[_d_zistepu] + fmul ds:dword ptr[fp_8] + mov ds:dword ptr[pbase],edx ; pbase = cacheblock + fld ds:dword ptr[_d_zistepu] + fmul ds:dword ptr[fp_64kx64k] + fxch st(3) + fstp ds:dword ptr[sdivz8stepu] + fstp ds:dword ptr[zi8stepu] + fstp ds:dword ptr[tdivz8stepu] + fistp ds:dword ptr[izistep] + mov eax,ds:dword ptr[izistep] + ror eax,16 ; put upper 16 bits in low word + mov ecx,ds:dword ptr[sspan_t_count+ebx] + mov ds:dword ptr[izistep],eax + + cmp ecx,0 + jle LNextSpan + +LSpanLoop: + +; +; set up the initial s/z, t/z, and 1/z on the FP stack, and generate the +; initial s and t values +; +; FIXME: pipeline FILD? + fild ds:dword ptr[sspan_t_v+ebx] + fild ds:dword ptr[sspan_t_u+ebx] + + fld st(1) ; dv | du | dv + fmul ds:dword ptr[_d_sdivzstepv] ; dv*d_sdivzstepv | du | dv + fld st(1) ; du | dv*d_sdivzstepv | du | dv + fmul ds:dword ptr[_d_sdivzstepu] ; du*d_sdivzstepu | dv*d_sdivzstepv | du | dv + fld st(2) ; du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv + fmul ds:dword ptr[_d_tdivzstepu] ; du*d_tdivzstepu | du*d_sdivzstepu | +; dv*d_sdivzstepv | du | dv + fxch st(1) ; du*d_sdivzstepu | du*d_tdivzstepu | +; dv*d_sdivzstepv | du | dv + faddp st(2),st(0) ; du*d_tdivzstepu | +; du*d_sdivzstepu + dv*d_sdivzstepv | du | dv + fxch st(1) ; du*d_sdivzstepu + dv*d_sdivzstepv | +; du*d_tdivzstepu | du | dv + fld st(3) ; dv | du*d_sdivzstepu + dv*d_sdivzstepv | +; du*d_tdivzstepu | du | dv + fmul ds:dword ptr[_d_tdivzstepv] ; dv*d_tdivzstepv | +; du*d_sdivzstepu + dv*d_sdivzstepv | +; du*d_tdivzstepu | du | dv + fxch st(1) ; du*d_sdivzstepu + dv*d_sdivzstepv | +; dv*d_tdivzstepv | du*d_tdivzstepu | du | dv + fadd ds:dword ptr[_d_sdivzorigin] ; sdivz = d_sdivzorigin + dv*d_sdivzstepv + +; du*d_sdivzstepu; stays in %st(2) at end + fxch st(4) ; dv | dv*d_tdivzstepv | du*d_tdivzstepu | du | +; s/z + fmul ds:dword ptr[_d_zistepv] ; dv*d_zistepv | dv*d_tdivzstepv | +; du*d_tdivzstepu | du | s/z + fxch st(1) ; dv*d_tdivzstepv | dv*d_zistepv | +; du*d_tdivzstepu | du | s/z + faddp st(2),st(0) ; dv*d_zistepv | +; dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z + fxch st(2) ; du | dv*d_tdivzstepv + du*d_tdivzstepu | +; dv*d_zistepv | s/z + fmul ds:dword ptr[_d_zistepu] ; du*d_zistepu | +; dv*d_tdivzstepv + du*d_tdivzstepu | +; dv*d_zistepv | s/z + fxch st(1) ; dv*d_tdivzstepv + du*d_tdivzstepu | +; du*d_zistepu | dv*d_zistepv | s/z + fadd ds:dword ptr[_d_tdivzorigin] ; tdivz = d_tdivzorigin + dv*d_tdivzstepv + +; du*d_tdivzstepu; stays in %st(1) at end + fxch st(2) ; dv*d_zistepv | du*d_zistepu | t/z | s/z + faddp st(1),st(0) ; dv*d_zistepv + du*d_zistepu | t/z | s/z + + fld ds:dword ptr[fp_64k] ; fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z + fxch st(1) ; dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z + fadd ds:dword ptr[_d_ziorigin] ; zi = d_ziorigin + dv*d_zistepv + +; du*d_zistepu; stays in %st(0) at end +; 1/z | fp_64k | t/z | s/z + + fld st(0) ; FIXME: get rid of stall on FMUL? + fmul ds:dword ptr[fp_64kx64k] + fxch st(1) + +; +; calculate and clamp s & t +; + fdiv st(2),st(0) ; 1/z | z*64k | t/z | s/z + fxch st(1) + + fistp ds:dword ptr[izi] ; 0.32 fixed-point 1/z + mov ebp,ds:dword ptr[izi] + +; +; set pz to point to the first z-buffer pixel in the span +; + ror ebp,16 ; put upper 16 bits in low word + mov eax,ds:dword ptr[sspan_t_v+ebx] + mov ds:dword ptr[izi],ebp + mov ebp,ds:dword ptr[sspan_t_u+ebx] + imul ds:dword ptr[_d_zrowbytes] + shl ebp,1 ; a word per pixel + add eax,ds:dword ptr[_d_pzbuffer] + add eax,ebp + mov ds:dword ptr[pz],eax + +; +; point %edi to the first pixel in the span +; + mov ebp,ds:dword ptr[_d_viewbuffer] + mov eax,ds:dword ptr[sspan_t_v+ebx] + push ebx ; preserve spans pointer + mov edx,ds:dword ptr[_tadjust] + mov esi,ds:dword ptr[_sadjust] + mov edi,ds:dword ptr[_d_scantable+eax*4] ; v * screenwidth + add edi,ebp + mov ebp,ds:dword ptr[sspan_t_u+ebx] + add edi,ebp ; pdest = &pdestspan[scans->u]; + +; +; now start the FDIV for the end of the span +; + cmp ecx,8 + ja LSetupNotLast1 + + dec ecx + jz LCleanup1 ; if only one pixel, no need to start an FDIV + mov ds:dword ptr[spancountminus1],ecx + +; finish up the s and t calcs + fxch st(1) ; z*64k | 1/z | t/z | s/z + + fld st(0) ; z*64k | z*64k | 1/z | t/z | s/z + fmul st(0),st(4) ; s | z*64k | 1/z | t/z | s/z + fxch st(1) ; z*64k | s | 1/z | t/z | s/z + fmul st(0),st(3) ; t | s | 1/z | t/z | s/z + fxch st(1) ; s | t | 1/z | t/z | s/z + fistp ds:dword ptr[s] ; 1/z | t | t/z | s/z + fistp ds:dword ptr[t] ; 1/z | t/z | s/z + + fild ds:dword ptr[spancountminus1] + + fld ds:dword ptr[_d_tdivzstepu] ; _d_tdivzstepu | spancountminus1 + fld ds:dword ptr[_d_zistepu] ; _d_zistepu | _d_tdivzstepu | spancountminus1 + fmul st(0),st(2) ; _d_zistepu*scm1 | _d_tdivzstepu | scm1 + fxch st(1) ; _d_tdivzstepu | _d_zistepu*scm1 | scm1 + fmul st(0),st(2) ; _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1 + fxch st(2) ; scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1 + fmul ds:dword ptr[_d_sdivzstepu] ; _d_sdivzstepu*scm1 | _d_zistepu*scm1 | +; _d_tdivzstepu*scm1 + fxch st(1) ; _d_zistepu*scm1 | _d_sdivzstepu*scm1 | +; _d_tdivzstepu*scm1 + faddp st(3),st(0) ; _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1 + fxch st(1) ; _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1 + faddp st(3),st(0) ; _d_sdivzstepu*scm1 + faddp st(3),st(0) + + fld ds:dword ptr[fp_64k] + fdiv st(0),st(1) ; this is what we've gone to all this trouble to +; overlap + jmp LFDIVInFlight1 + +LCleanup1: +; finish up the s and t calcs + fxch st(1) ; z*64k | 1/z | t/z | s/z + + fld st(0) ; z*64k | z*64k | 1/z | t/z | s/z + fmul st(0),st(4) ; s | z*64k | 1/z | t/z | s/z + fxch st(1) ; z*64k | s | 1/z | t/z | s/z + fmul st(0),st(3) ; t | s | 1/z | t/z | s/z + fxch st(1) ; s | t | 1/z | t/z | s/z + fistp ds:dword ptr[s] ; 1/z | t | t/z | s/z + fistp ds:dword ptr[t] ; 1/z | t/z | s/z + jmp LFDIVInFlight1 + + align 4 +LSetupNotLast1: +; finish up the s and t calcs + fxch st(1) ; z*64k | 1/z | t/z | s/z + + fld st(0) ; z*64k | z*64k | 1/z | t/z | s/z + fmul st(0),st(4) ; s | z*64k | 1/z | t/z | s/z + fxch st(1) ; z*64k | s | 1/z | t/z | s/z + fmul st(0),st(3) ; t | s | 1/z | t/z | s/z + fxch st(1) ; s | t | 1/z | t/z | s/z + fistp ds:dword ptr[s] ; 1/z | t | t/z | s/z + fistp ds:dword ptr[t] ; 1/z | t/z | s/z + + fadd ds:dword ptr[zi8stepu] + fxch st(2) + fadd ds:dword ptr[sdivz8stepu] + fxch st(2) + fld ds:dword ptr[tdivz8stepu] + faddp st(2),st(0) + fld ds:dword ptr[fp_64k] + fdiv st(0),st(1) ; z = 1/1/z +; this is what we've gone to all this trouble to +; overlap +LFDIVInFlight1: + + add esi,ds:dword ptr[s] + add edx,ds:dword ptr[t] + mov ebx,ds:dword ptr[_bbextents] + mov ebp,ds:dword ptr[_bbextentt] + cmp esi,ebx + ja LClampHighOrLow0 +LClampReentry0: + mov ds:dword ptr[s],esi + mov ebx,ds:dword ptr[pbase] + shl esi,16 + cmp edx,ebp + mov ds:dword ptr[sfracf],esi + ja LClampHighOrLow1 +LClampReentry1: + mov ds:dword ptr[t],edx + mov esi,ds:dword ptr[s] ; sfrac = scans->sfrac; + shl edx,16 + mov eax,ds:dword ptr[t] ; tfrac = scans->tfrac; + sar esi,16 + mov ds:dword ptr[tfracf],edx + +; +; calculate the texture starting address +; + sar eax,16 + add esi,ebx + imul eax,ds:dword ptr[_cachewidth] ; (tfrac >> 16) * cachewidth + add esi,eax ; psource = pbase + (sfrac >> 16) + +; ((tfrac >> 16) * cachewidth); + +; +; determine whether last span or not +; + cmp ecx,8 + jna LLastSegment + +; +; not the last segment; do full 8-wide segment +; +LNotLastSegment: + +; +; advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to +; get there +; + +; pick up after the FDIV that was left in flight previously + + fld st(0) ; duplicate it + fmul st(0),st(4) ; s = s/z * z + fxch st(1) + fmul st(0),st(3) ; t = t/z * z + fxch st(1) + fistp ds:dword ptr[snext] + fistp ds:dword ptr[tnext] + mov eax,ds:dword ptr[snext] + mov edx,ds:dword ptr[tnext] + + sub ecx,8 ; count off this segments' pixels + mov ebp,ds:dword ptr[_sadjust] + push ecx ; remember count of remaining pixels + mov ecx,ds:dword ptr[_tadjust] + + add ebp,eax + add ecx,edx + + mov eax,ds:dword ptr[_bbextents] + mov edx,ds:dword ptr[_bbextentt] + + cmp ebp,2048 + jl LClampLow2 + cmp ebp,eax + ja LClampHigh2 +LClampReentry2: + + cmp ecx,2048 + jl LClampLow3 + cmp ecx,edx + ja LClampHigh3 +LClampReentry3: + + mov ds:dword ptr[snext],ebp + mov ds:dword ptr[tnext],ecx + + sub ebp,ds:dword ptr[s] + sub ecx,ds:dword ptr[t] + +; +; set up advancetable +; + mov eax,ecx + mov edx,ebp + sar edx,19 ; sstep >>= 16; + mov ebx,ds:dword ptr[_cachewidth] + sar eax,19 ; tstep >>= 16; + jz LIsZero + imul eax,ebx ; (tstep >> 16) * cachewidth; +LIsZero: + add eax,edx ; add in sstep +; (tstep >> 16) * cachewidth + (sstep >> 16); + mov edx,ds:dword ptr[tfracf] + mov ds:dword ptr[advancetable+4],eax ; advance base in t + add eax,ebx ; ((tstep >> 16) + 1) * cachewidth + +; (sstep >> 16); + shl ebp,13 ; left-justify sstep fractional part + mov ds:dword ptr[sstep],ebp + mov ebx,ds:dword ptr[sfracf] + shl ecx,13 ; left-justify tstep fractional part + mov ds:dword ptr[advancetable],eax ; advance extra in t + mov ds:dword ptr[tstep],ecx + + mov ecx,ds:dword ptr[pz] + mov ebp,ds:dword ptr[izi] + + cmp bp,ds:word ptr[ecx] + jl Lp1 + mov al,ds:byte ptr[esi] ; get first source texel + cmp al,offset TRANSPARENT_COLOR + jz Lp1 + mov ds:word ptr[ecx],bp + mov ds:byte ptr[edi],al ; store first dest pixel +Lp1: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] ; advance tfrac fractional part by tstep frac + + sbb eax,eax ; turn tstep carry into -1 (0 if none) + add ebx,ds:dword ptr[sstep] ; advance sfrac fractional part by sstep frac + adc esi,ds:dword ptr[advancetable+4+eax*4] ; point to next source texel + + cmp bp,ds:word ptr[2+ecx] + jl Lp2 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp2 + mov ds:word ptr[2+ecx],bp + mov ds:byte ptr[1+edi],al +Lp2: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + cmp bp,ds:word ptr[4+ecx] + jl Lp3 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp3 + mov ds:word ptr[4+ecx],bp + mov ds:byte ptr[2+edi],al +Lp3: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + cmp bp,ds:word ptr[6+ecx] + jl Lp4 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp4 + mov ds:word ptr[6+ecx],bp + mov ds:byte ptr[3+edi],al +Lp4: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + cmp bp,ds:word ptr[8+ecx] + jl Lp5 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp5 + mov ds:word ptr[8+ecx],bp + mov ds:byte ptr[4+edi],al +Lp5: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +; +; start FDIV for end of next segment in flight, so it can overlap +; + pop eax + cmp eax,8 ; more than one segment after this? + ja LSetupNotLast2 ; yes + + dec eax + jz LFDIVInFlight2 ; if only one pixel, no need to start an FDIV + mov ds:dword ptr[spancountminus1],eax + fild ds:dword ptr[spancountminus1] + + fld ds:dword ptr[_d_zistepu] ; _d_zistepu | spancountminus1 + fmul st(0),st(1) ; _d_zistepu*scm1 | scm1 + fld ds:dword ptr[_d_tdivzstepu] ; _d_tdivzstepu | _d_zistepu*scm1 | scm1 + fmul st(0),st(2) ; _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1 + fxch st(1) ; _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1 + faddp st(3),st(0) ; _d_tdivzstepu*scm1 | scm1 + fxch st(1) ; scm1 | _d_tdivzstepu*scm1 + fmul ds:dword ptr[_d_sdivzstepu] ; _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1 + fxch st(1) ; _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1 + faddp st(3),st(0) ; _d_sdivzstepu*scm1 + fld ds:dword ptr[fp_64k] ; 64k | _d_sdivzstepu*scm1 + fxch st(1) ; _d_sdivzstepu*scm1 | 64k + faddp st(4),st(0) ; 64k + + fdiv st(0),st(1) ; this is what we've gone to all this trouble to +; overlap + jmp LFDIVInFlight2 + + align 4 +LSetupNotLast2: + fadd ds:dword ptr[zi8stepu] + fxch st(2) + fadd ds:dword ptr[sdivz8stepu] + fxch st(2) + fld ds:dword ptr[tdivz8stepu] + faddp st(2),st(0) + fld ds:dword ptr[fp_64k] + fdiv st(0),st(1) ; z = 1/1/z +; this is what we've gone to all this trouble to +; overlap +LFDIVInFlight2: + push eax + + cmp bp,ds:word ptr[10+ecx] + jl Lp6 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp6 + mov ds:word ptr[10+ecx],bp + mov ds:byte ptr[5+edi],al +Lp6: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + cmp bp,ds:word ptr[12+ecx] + jl Lp7 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp7 + mov ds:word ptr[12+ecx],bp + mov ds:byte ptr[6+edi],al +Lp7: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + cmp bp,ds:word ptr[14+ecx] + jl Lp8 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp8 + mov ds:word ptr[14+ecx],bp + mov ds:byte ptr[7+edi],al +Lp8: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + + add edi,8 + add ecx,16 + mov ds:dword ptr[tfracf],edx + mov edx,ds:dword ptr[snext] + mov ds:dword ptr[sfracf],ebx + mov ebx,ds:dword ptr[tnext] + mov ds:dword ptr[s],edx + mov ds:dword ptr[t],ebx + + mov ds:dword ptr[pz],ecx + mov ds:dword ptr[izi],ebp + + pop ecx ; retrieve count + +; +; determine whether last span or not +; + cmp ecx,8 ; are there multiple segments remaining? + ja LNotLastSegment ; yes + +; +; last segment of scan +; +LLastSegment: + +; +; advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to +; get there. The number of pixels left is variable, and we want to land on the +; last pixel, not step one past it, so we can't run into arithmetic problems +; + test ecx,ecx + jz LNoSteps ; just draw the last pixel and we're done + +; pick up after the FDIV that was left in flight previously + + + fld st(0) ; duplicate it + fmul st(0),st(4) ; s = s/z * z + fxch st(1) + fmul st(0),st(3) ; t = t/z * z + fxch st(1) + fistp ds:dword ptr[snext] + fistp ds:dword ptr[tnext] + + mov ebx,ds:dword ptr[_tadjust] + mov eax,ds:dword ptr[_sadjust] + + add eax,ds:dword ptr[snext] + add ebx,ds:dword ptr[tnext] + + mov ebp,ds:dword ptr[_bbextents] + mov edx,ds:dword ptr[_bbextentt] + + cmp eax,2048 + jl LClampLow4 + cmp eax,ebp + ja LClampHigh4 +LClampReentry4: + mov ds:dword ptr[snext],eax + + cmp ebx,2048 + jl LClampLow5 + cmp ebx,edx + ja LClampHigh5 +LClampReentry5: + + cmp ecx,1 ; don't bother + je LOnlyOneStep ; if two pixels in segment, there's only one step, +; of the segment length + sub eax,ds:dword ptr[s] + sub ebx,ds:dword ptr[t] + + add eax,eax ; convert to 15.17 format so multiply by 1.31 + add ebx,ebx ; reciprocal yields 16.48 + imul ds:dword ptr[reciprocal_table-8+ecx*4] ; sstep = (snext - s) / (spancount-1) + mov ebp,edx + + mov eax,ebx + imul ds:dword ptr[reciprocal_table-8+ecx*4] ; tstep = (tnext - t) / (spancount-1) + +LSetEntryvec: +; +; set up advancetable +; + mov ebx,ds:dword ptr[spr8entryvec_table+ecx*4] + mov eax,edx + push ebx ; entry point into code for RET later + mov ecx,ebp + sar ecx,16 ; sstep >>= 16; + mov ebx,ds:dword ptr[_cachewidth] + sar edx,16 ; tstep >>= 16; + jz LIsZeroLast + imul edx,ebx ; (tstep >> 16) * cachewidth; +LIsZeroLast: + add edx,ecx ; add in sstep +; (tstep >> 16) * cachewidth + (sstep >> 16); + mov ecx,ds:dword ptr[tfracf] + mov ds:dword ptr[advancetable+4],edx ; advance base in t + add edx,ebx ; ((tstep >> 16) + 1) * cachewidth + +; (sstep >> 16); + shl ebp,16 ; left-justify sstep fractional part + mov ebx,ds:dword ptr[sfracf] + shl eax,16 ; left-justify tstep fractional part + mov ds:dword ptr[advancetable],edx ; advance extra in t + + mov ds:dword ptr[tstep],eax + mov ds:dword ptr[sstep],ebp + mov edx,ecx + + mov ecx,ds:dword ptr[pz] + mov ebp,ds:dword ptr[izi] + + ret ; jump to the number-of-pixels handler + +;---------------------------------------- + +LNoSteps: + mov ecx,ds:dword ptr[pz] + sub edi,7 ; adjust for hardwired offset + sub ecx,14 + jmp LEndSpan + + +LOnlyOneStep: + sub eax,ds:dword ptr[s] + sub ebx,ds:dword ptr[t] + mov ebp,eax + mov edx,ebx + jmp LSetEntryvec + +;---------------------------------------- + + public Spr8Entry2_8 +Spr8Entry2_8: + sub edi,6 ; adjust for hardwired offsets + sub ecx,12 + mov al,ds:byte ptr[esi] + jmp LLEntry2_8 + +;---------------------------------------- + + public Spr8Entry3_8 +Spr8Entry3_8: + sub edi,5 ; adjust for hardwired offsets + sub ecx,10 + jmp LLEntry3_8 + +;---------------------------------------- + + public Spr8Entry4_8 +Spr8Entry4_8: + sub edi,4 ; adjust for hardwired offsets + sub ecx,8 + jmp LLEntry4_8 + +;---------------------------------------- + + public Spr8Entry5_8 +Spr8Entry5_8: + sub edi,3 ; adjust for hardwired offsets + sub ecx,6 + jmp LLEntry5_8 + +;---------------------------------------- + + public Spr8Entry6_8 +Spr8Entry6_8: + sub edi,2 ; adjust for hardwired offsets + sub ecx,4 + jmp LLEntry6_8 + +;---------------------------------------- + + public Spr8Entry7_8 +Spr8Entry7_8: + dec edi ; adjust for hardwired offsets + sub ecx,2 + jmp LLEntry7_8 + +;---------------------------------------- + + public Spr8Entry8_8 +Spr8Entry8_8: + cmp bp,ds:word ptr[ecx] + jl Lp9 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp9 + mov ds:word ptr[ecx],bp + mov ds:byte ptr[edi],al +Lp9: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] +LLEntry7_8: + cmp bp,ds:word ptr[2+ecx] + jl Lp10 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp10 + mov ds:word ptr[2+ecx],bp + mov ds:byte ptr[1+edi],al +Lp10: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] +LLEntry6_8: + cmp bp,ds:word ptr[4+ecx] + jl Lp11 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp11 + mov ds:word ptr[4+ecx],bp + mov ds:byte ptr[2+edi],al +Lp11: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] +LLEntry5_8: + cmp bp,ds:word ptr[6+ecx] + jl Lp12 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp12 + mov ds:word ptr[6+ecx],bp + mov ds:byte ptr[3+edi],al +Lp12: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] +LLEntry4_8: + cmp bp,ds:word ptr[8+ecx] + jl Lp13 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp13 + mov ds:word ptr[8+ecx],bp + mov ds:byte ptr[4+edi],al +Lp13: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] +LLEntry3_8: + cmp bp,ds:word ptr[10+ecx] + jl Lp14 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp14 + mov ds:word ptr[10+ecx],bp + mov ds:byte ptr[5+edi],al +Lp14: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] +LLEntry2_8: + cmp bp,ds:word ptr[12+ecx] + jl Lp15 + mov al,ds:byte ptr[esi] + cmp al,offset TRANSPARENT_COLOR + jz Lp15 + mov ds:word ptr[12+ecx],bp + mov ds:byte ptr[6+edi],al +Lp15: + add ebp,ds:dword ptr[izistep] + adc ebp,0 + add edx,ds:dword ptr[tstep] + sbb eax,eax + add ebx,ds:dword ptr[sstep] + adc esi,ds:dword ptr[advancetable+4+eax*4] + +LEndSpan: + cmp bp,ds:word ptr[14+ecx] + jl Lp16 + mov al,ds:byte ptr[esi] ; load first texel in segment + cmp al,offset TRANSPARENT_COLOR + jz Lp16 + mov ds:word ptr[14+ecx],bp + mov ds:byte ptr[7+edi],al +Lp16: + +; +; clear s/z, t/z, 1/z from FP stack +; + fstp st(0) + fstp st(0) + fstp st(0) + + pop ebx ; restore spans pointer +LNextSpan: + add ebx,offset sspan_t_size ; point to next span + mov ecx,ds:dword ptr[sspan_t_count+ebx] + cmp ecx,0 ; any more spans? + jg LSpanLoop ; yes + jz LNextSpan ; yes, but this one's empty + + pop ebx ; restore register variables + pop esi + pop edi + pop ebp ; restore the caller's stack frame + ret + +_TEXT ENDS +endif ; id386 + END diff --git a/ref_soft/r_sprite.c b/ref_soft/r_sprite.c new file mode 100644 index 000000000..76f8545e7 --- /dev/null +++ b/ref_soft/r_sprite.c @@ -0,0 +1,123 @@ +/* +Copyright (C) 1997-2001 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_sprite.c +#include "r_local.h" + +extern polydesc_t r_polydesc; + +void R_BuildPolygonFromSurface(msurface_t *fa); +void R_PolygonCalculateGradients (void); + +extern void R_PolyChooseSpanletRoutine( float alpha, qboolean isturbulent ); + +extern vec5_t r_clip_verts[2][MAXWORKINGVERTS+2]; + +extern void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ); + +/* +** R_DrawSprite +** +** Draw currententity / currentmodel as a single texture +** mapped polygon +*/ +void R_DrawSprite (void) +{ + vec5_t *pverts; + vec3_t left, up, right, down; + dsprite_t *s_psprite; + dsprframe_t *s_psprframe; + + + s_psprite = (dsprite_t *)currentmodel->extradata; +#if 0 + if (currententity->frame >= s_psprite->numframes + || currententity->frame < 0) + { + ri.Con_Printf (PRINT_ALL, "No such sprite frame %i\n", + currententity->frame); + currententity->frame = 0; + } +#endif + currententity->frame %= s_psprite->numframes; + + s_psprframe = &s_psprite->frames[currententity->frame]; + + r_polydesc.pixels = currentmodel->skins[currententity->frame]->pixels[0]; + r_polydesc.pixel_width = s_psprframe->width; + r_polydesc.pixel_height = s_psprframe->height; + r_polydesc.dist = 0; + + // generate the sprite's axes, completely parallel to the viewplane. + VectorCopy (vup, r_polydesc.vup); + VectorCopy (vright, r_polydesc.vright); + VectorCopy (vpn, r_polydesc.vpn); + +// build the sprite poster in worldspace + VectorScale (r_polydesc.vright, + s_psprframe->width - s_psprframe->origin_x, right); + VectorScale (r_polydesc.vup, + s_psprframe->height - s_psprframe->origin_y, up); + VectorScale (r_polydesc.vright, + -s_psprframe->origin_x, left); + VectorScale (r_polydesc.vup, + -s_psprframe->origin_y, down); + + // invert UP vector for sprites + VectorInverse( r_polydesc.vup ); + + pverts = r_clip_verts[0]; + + pverts[0][0] = r_entorigin[0] + up[0] + left[0]; + pverts[0][1] = r_entorigin[1] + up[1] + left[1]; + pverts[0][2] = r_entorigin[2] + up[2] + left[2]; + pverts[0][3] = 0; + pverts[0][4] = 0; + + pverts[1][0] = r_entorigin[0] + up[0] + right[0]; + pverts[1][1] = r_entorigin[1] + up[1] + right[1]; + pverts[1][2] = r_entorigin[2] + up[2] + right[2]; + pverts[1][3] = s_psprframe->width; + pverts[1][4] = 0; + + pverts[2][0] = r_entorigin[0] + down[0] + right[0]; + pverts[2][1] = r_entorigin[1] + down[1] + right[1]; + pverts[2][2] = r_entorigin[2] + down[2] + right[2]; + pverts[2][3] = s_psprframe->width; + pverts[2][4] = s_psprframe->height; + + pverts[3][0] = r_entorigin[0] + down[0] + left[0]; + pverts[3][1] = r_entorigin[1] + down[1] + left[1]; + pverts[3][2] = r_entorigin[2] + down[2] + left[2]; + pverts[3][3] = 0; + pverts[3][4] = s_psprframe->height; + + r_polydesc.nump = 4; + r_polydesc.s_offset = ( r_polydesc.pixel_width >> 1); + r_polydesc.t_offset = ( r_polydesc.pixel_height >> 1); + VectorCopy( modelorg, r_polydesc.viewer_position ); + + r_polydesc.stipple_parity = 1; + if ( currententity->flags & RF_TRANSLUCENT ) + R_ClipAndDrawPoly ( currententity->alpha, false, true ); + else + R_ClipAndDrawPoly ( 1.0F, false, true ); + r_polydesc.stipple_parity = 0; +} + diff --git a/ref_soft/r_surf.c b/ref_soft/r_surf.c new file mode 100644 index 000000000..0f309d866 --- /dev/null +++ b/ref_soft/r_surf.c @@ -0,0 +1,651 @@ +/* +Copyright (C) 1997-2001 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_surf.c: surface-related refresh code + +#include "r_local.h" + +drawsurf_t r_drawsurf; + +int lightleft, sourcesstep, blocksize, sourcetstep; +int lightdelta, lightdeltastep; +int lightright, lightleftstep, lightrightstep, blockdivshift; +unsigned blockdivmask; +void *prowdestbase; +unsigned char *pbasesource; +int surfrowbytes; // used by ASM files +unsigned *r_lightptr; +int r_stepback; +int r_lightwidth; +int r_numhblocks, r_numvblocks; +unsigned char *r_source, *r_sourcemax; + +void R_DrawSurfaceBlock8_mip0 (void); +void R_DrawSurfaceBlock8_mip1 (void); +void R_DrawSurfaceBlock8_mip2 (void); +void R_DrawSurfaceBlock8_mip3 (void); + +static void (*surfmiptable[4])(void) = { + R_DrawSurfaceBlock8_mip0, + R_DrawSurfaceBlock8_mip1, + R_DrawSurfaceBlock8_mip2, + R_DrawSurfaceBlock8_mip3 +}; + +void R_BuildLightMap (void); +extern unsigned blocklights[1024]; // allow some very large lightmaps + +float surfscale; +qboolean r_cache_thrash; // set if surface cache is thrashing + +int sc_size; +surfcache_t *sc_rover, *sc_base; + +/* +=============== +R_TextureAnimation + +Returns the proper texture for a given time and base texture +=============== +*/ +image_t *R_TextureAnimation (mtexinfo_t *tex) +{ + int c; + + if (!tex->next) + return tex->image; + + c = currententity->frame % tex->numframes; + while (c) + { + tex = tex->next; + c--; + } + + return tex->image; +} + + +/* +=============== +R_DrawSurface +=============== +*/ +void R_DrawSurface (void) +{ + unsigned char *basetptr; + int smax, tmax, twidth; + int u; + int soffset, basetoffset, texwidth; + int horzblockstep; + unsigned char *pcolumndest; + void (*pblockdrawer)(void); + image_t *mt; + + surfrowbytes = r_drawsurf.rowbytes; + + mt = r_drawsurf.image; + + r_source = mt->pixels[r_drawsurf.surfmip]; + +// the fractional light values should range from 0 to (VID_GRADES - 1) << 16 +// from a source range of 0 - 255 + + texwidth = mt->width >> r_drawsurf.surfmip; + + blocksize = 16 >> r_drawsurf.surfmip; + blockdivshift = 4 - r_drawsurf.surfmip; + blockdivmask = (1 << blockdivshift) - 1; + + r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; + + r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; + r_numvblocks = r_drawsurf.surfheight >> blockdivshift; + +//============================== + + pblockdrawer = surfmiptable[r_drawsurf.surfmip]; +// TODO: only needs to be set when there is a display settings change + horzblockstep = blocksize; + + smax = mt->width >> r_drawsurf.surfmip; + twidth = texwidth; + tmax = mt->height >> r_drawsurf.surfmip; + sourcetstep = texwidth; + r_stepback = tmax * twidth; + + r_sourcemax = r_source + (tmax * smax); + + soffset = r_drawsurf.surf->texturemins[0]; + basetoffset = r_drawsurf.surf->texturemins[1]; + +// << 16 components are to guarantee positive values for % + soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; + basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth)]; + + pcolumndest = r_drawsurf.surfdat; + + for (u=0 ; u= smax) + soffset = 0; + + pcolumndest += horzblockstep; + } +} + + +//============================================================================= + +#if !id386 + +/* +================ +R_DrawSurfaceBlock8_mip0 +================ +*/ +void R_DrawSurfaceBlock8_mip0 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (i=0 ; i<16 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 4; + + light = lightright; + + for (b=15; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip1 +================ +*/ +void R_DrawSurfaceBlock8_mip1 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (i=0 ; i<8 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 3; + + light = lightright; + + for (b=7; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip2 +================ +*/ +void R_DrawSurfaceBlock8_mip2 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (i=0 ; i<4 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 2; + + light = lightright; + + for (b=3; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip3 +================ +*/ +void R_DrawSurfaceBlock8_mip3 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + for (i=0 ; i<2 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 1; + + light = lightright; + + for (b=1; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +#endif + + +//============================================================================ + + +/* +================ +R_InitCaches + +================ +*/ +void R_InitCaches (void) +{ + int size; + int pix; + + // calculate size to allocate + if (sw_surfcacheoverride->value) + { + size = sw_surfcacheoverride->value; + } + else + { + size = SURFCACHE_SIZE_AT_320X240; + + pix = vid.width*vid.height; + if (pix > 64000) + size += (pix-64000)*3; + } + + // round up to page size + size = (size + 8191) & ~8191; + + ri.Con_Printf (PRINT_ALL,"%ik surface cache\n", size/1024); + + sc_size = size; + sc_base = (surfcache_t *)malloc(size); + sc_rover = sc_base; + + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; +} + + +/* +================== +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)) + ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache width %d\n", width); + + if ((size <= 0) || (size > 0x10000)) + ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache size %d\n", size); + + size = (int)&((surfcache_t *)0)->data[size]; + size = (size + 3) & ~3; + if (size > sc_size) + ri.Sys_Error (ERR_FATAL,"D_SCAlloc: %i > cache size of %i",size, sc_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) + ri.Sys_Error (ERR_FATAL,"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; + } + + return new; +} + + +/* +================= +D_SCDump +================= +*/ +void D_SCDump (void) +{ + surfcache_t *test; + + for (test = sc_base ; test ; test = test->next) + { + if (test == sc_rover) + ri.Con_Printf (PRINT_ALL,"ROVER:\n"); + ri.Con_Printf (PRINT_ALL,"%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.image = R_TextureAnimation (surface->texinfo); + r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128; + r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128; + r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white*128; + r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white*128; + +// +// see if the cache holds apropriate data +// + cache = surface->cachespots[miplevel]; + + if (cache && !cache->dlight && surface->dlightframe != r_framecount + && cache->image == r_drawsurf.image + && 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<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->image = r_drawsurf.image; + 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++; + + // calculate the lightings + R_BuildLightMap (); + + // rasterize the surface into the cache + R_DrawSurface (); + + return cache; +} + + diff --git a/ref_soft/r_surf8.asm b/ref_soft/r_surf8.asm new file mode 100644 index 000000000..8987b971e --- /dev/null +++ b/ref_soft/r_surf8.asm @@ -0,0 +1,771 @@ + .386P + .model FLAT +; +; surf8.s +; x86 assembly-language 8 bpp surface block drawing code. +; + +include qasm.inc + +if id386 + +_DATA SEGMENT + +sb_v dd 0 + +_DATA ENDS +_TEXT SEGMENT + + align 4 + public _R_Surf8Start +_R_Surf8Start: + +;---------------------------------------------------------------------- +; Surface block drawer for mip level 0 +;---------------------------------------------------------------------- + + align 4 + public _R_DrawSurfaceBlock8_mip0 +_R_DrawSurfaceBlock8_mip0: + push ebp ; preserve caller's stack frame + push edi + push esi ; preserve register variables + push ebx + +; for (v=0 ; v> blockdivshift; +; lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +; 0xF0000000; + mov ecx,ds:dword ptr[4+ebx] ; lightptr[1] + mov ebx,ds:dword ptr[ebx] ; lightptr[0] + + sub ebx,eax + sub ecx,edx + + sar ecx,4 + or ebp,0F0000000h + + sar ebx,4 + mov ds:dword ptr[_lightrightstep],ecx + + sub ebx,ecx + and ebx,0FFFFFh + + or ebx,0F0000000h + sub ecx,ecx ; high word must be 0 in loop for addressing + + mov ds:dword ptr[_lightdeltastep],ebx + sub ebx,ebx ; high word must be 0 in loop for addressing + +Lblockloop8_mip0: + mov ds:dword ptr[_lightdelta],ebp + mov cl,ds:byte ptr[14+esi] + + sar ebp,4 + mov bh,dh + + mov bl,ds:byte ptr[15+esi] + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch0: + mov bl,ds:byte ptr[13+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch1: + mov cl,ds:byte ptr[12+esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + add edx,ebp + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch2: + + mov bl,ds:byte ptr[11+esi] + mov al,ds:byte ptr[12345678h+ecx] +LBPatch3: + + mov cl,ds:byte ptr[10+esi] + mov ds:dword ptr[12+edi],eax + + mov bh,dh + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch4: + mov bl,ds:byte ptr[9+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch5: + mov cl,ds:byte ptr[8+esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + add edx,ebp + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch6: + + mov bl,ds:byte ptr[7+esi] + mov al,ds:byte ptr[12345678h+ecx] +LBPatch7: + + mov cl,ds:byte ptr[6+esi] + mov ds:dword ptr[8+edi],eax + + mov bh,dh + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch8: + mov bl,ds:byte ptr[5+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch9: + mov cl,ds:byte ptr[4+esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + add edx,ebp + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch10: + + mov bl,ds:byte ptr[3+esi] + mov al,ds:byte ptr[12345678h+ecx] +LBPatch11: + + mov cl,ds:byte ptr[2+esi] + mov ds:dword ptr[4+edi],eax + + mov bh,dh + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch12: + mov bl,ds:byte ptr[1+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch13: + mov cl,ds:byte ptr[esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch14: + mov edx,ds:dword ptr[_lightright] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch15: + mov ebp,ds:dword ptr[_lightdelta] + + mov ds:dword ptr[edi],eax + + add esi,ds:dword ptr[_sourcetstep] + add edi,ds:dword ptr[_surfrowbytes] + + add edx,ds:dword ptr[_lightrightstep] + add ebp,ds:dword ptr[_lightdeltastep] + + mov ds:dword ptr[_lightright],edx + jc Lblockloop8_mip0 + +; if (pbasesource >= r_sourcemax) +; pbasesource -= stepback; + + cmp esi,ds:dword ptr[_r_sourcemax] + jb LSkip_mip0 + sub esi,ds:dword ptr[_r_stepback] +LSkip_mip0: + + mov ebx,ds:dword ptr[_r_lightptr] + dec ds:dword ptr[sb_v] + + jnz Lv_loop_mip0 + + pop ebx ; restore register variables + pop esi + pop edi + pop ebp ; restore the caller's stack frame + ret + + +;---------------------------------------------------------------------- +; Surface block drawer for mip level 1 +;---------------------------------------------------------------------- + + align 4 + public _R_DrawSurfaceBlock8_mip1 +_R_DrawSurfaceBlock8_mip1: + push ebp ; preserve caller's stack frame + push edi + push esi ; preserve register variables + push ebx + +; for (v=0 ; v> blockdivshift; +; lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +; 0xF0000000; + mov ecx,ds:dword ptr[4+ebx] ; lightptr[1] + mov ebx,ds:dword ptr[ebx] ; lightptr[0] + + sub ebx,eax + sub ecx,edx + + sar ecx,3 + or ebp,070000000h + + sar ebx,3 + mov ds:dword ptr[_lightrightstep],ecx + + sub ebx,ecx + and ebx,0FFFFFh + + or ebx,0F0000000h + sub ecx,ecx ; high word must be 0 in loop for addressing + + mov ds:dword ptr[_lightdeltastep],ebx + sub ebx,ebx ; high word must be 0 in loop for addressing + +Lblockloop8_mip1: + mov ds:dword ptr[_lightdelta],ebp + mov cl,ds:byte ptr[6+esi] + + sar ebp,3 + mov bh,dh + + mov bl,ds:byte ptr[7+esi] + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch22: + mov bl,ds:byte ptr[5+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch23: + mov cl,ds:byte ptr[4+esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + add edx,ebp + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch24: + + mov bl,ds:byte ptr[3+esi] + mov al,ds:byte ptr[12345678h+ecx] +LBPatch25: + + mov cl,ds:byte ptr[2+esi] + mov ds:dword ptr[4+edi],eax + + mov bh,dh + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch26: + mov bl,ds:byte ptr[1+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch27: + mov cl,ds:byte ptr[esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch28: + mov edx,ds:dword ptr[_lightright] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch29: + mov ebp,ds:dword ptr[_lightdelta] + + mov ds:dword ptr[edi],eax + mov eax,ds:dword ptr[_sourcetstep] + + add esi,eax + mov eax,ds:dword ptr[_surfrowbytes] + + add edi,eax + mov eax,ds:dword ptr[_lightrightstep] + + add edx,eax + mov eax,ds:dword ptr[_lightdeltastep] + + add ebp,eax + mov ds:dword ptr[_lightright],edx + + jc Lblockloop8_mip1 + +; if (pbasesource >= r_sourcemax) +; pbasesource -= stepback; + + cmp esi,ds:dword ptr[_r_sourcemax] + jb LSkip_mip1 + sub esi,ds:dword ptr[_r_stepback] +LSkip_mip1: + + mov ebx,ds:dword ptr[_r_lightptr] + dec ds:dword ptr[sb_v] + + jnz Lv_loop_mip1 + + pop ebx ; restore register variables + pop esi + pop edi + pop ebp ; restore the caller's stack frame + ret + + +;---------------------------------------------------------------------- +; Surface block drawer for mip level 2 +;---------------------------------------------------------------------- + + align 4 + public _R_DrawSurfaceBlock8_mip2 +_R_DrawSurfaceBlock8_mip2: + push ebp ; preserve caller's stack frame + push edi + push esi ; preserve register variables + push ebx + +; for (v=0 ; v> blockdivshift; +; lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +; 0xF0000000; + mov ecx,ds:dword ptr[4+ebx] ; lightptr[1] + mov ebx,ds:dword ptr[ebx] ; lightptr[0] + + sub ebx,eax + sub ecx,edx + + sar ecx,2 + or ebp,030000000h + + sar ebx,2 + mov ds:dword ptr[_lightrightstep],ecx + + sub ebx,ecx + + and ebx,0FFFFFh + + or ebx,0F0000000h + sub ecx,ecx ; high word must be 0 in loop for addressing + + mov ds:dword ptr[_lightdeltastep],ebx + sub ebx,ebx ; high word must be 0 in loop for addressing + +Lblockloop8_mip2: + mov ds:dword ptr[_lightdelta],ebp + mov cl,ds:byte ptr[2+esi] + + sar ebp,2 + mov bh,dh + + mov bl,ds:byte ptr[3+esi] + add edx,ebp + + mov ch,dh + add edx,ebp + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch18: + mov bl,ds:byte ptr[1+esi] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch19: + mov cl,ds:byte ptr[esi] + + mov bh,dh + add edx,ebp + + ror eax,16 + mov ch,dh + + mov ah,ds:byte ptr[12345678h+ebx] +LBPatch20: + mov edx,ds:dword ptr[_lightright] + + mov al,ds:byte ptr[12345678h+ecx] +LBPatch21: + mov ebp,ds:dword ptr[_lightdelta] + + mov ds:dword ptr[edi],eax + mov eax,ds:dword ptr[_sourcetstep] + + add esi,eax + mov eax,ds:dword ptr[_surfrowbytes] + + add edi,eax + mov eax,ds:dword ptr[_lightrightstep] + + add edx,eax + mov eax,ds:dword ptr[_lightdeltastep] + + add ebp,eax + mov ds:dword ptr[_lightright],edx + + jc Lblockloop8_mip2 + +; if (pbasesource >= r_sourcemax) +; pbasesource -= stepback; + + cmp esi,ds:dword ptr[_r_sourcemax] + jb LSkip_mip2 + sub esi,ds:dword ptr[_r_stepback] +LSkip_mip2: + + mov ebx,ds:dword ptr[_r_lightptr] + dec ds:dword ptr[sb_v] + + jnz Lv_loop_mip2 + + pop ebx ; restore register variables + pop esi + pop edi + pop ebp ; restore the caller's stack frame + ret + + +;---------------------------------------------------------------------- +; Surface block drawer for mip level 3 +;---------------------------------------------------------------------- + + align 4 + public _R_DrawSurfaceBlock8_mip3 +_R_DrawSurfaceBlock8_mip3: + push ebp ; preserve caller's stack frame + push edi + push esi ; preserve register variables + push ebx + +; for (v=0 ; v> blockdivshift; +; lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +; 0xF0000000; + mov ecx,ds:dword ptr[4+ebx] ; lightptr[1] + mov ebx,ds:dword ptr[ebx] ; lightptr[0] + + sub ebx,eax + sub ecx,edx + + sar ecx,1 + + sar ebx,1 + mov ds:dword ptr[_lightrightstep],ecx + + sub ebx,ecx + and ebx,0FFFFFh + + sar ebp,1 + or ebx,0F0000000h + + mov ds:dword ptr[_lightdeltastep],ebx + sub ebx,ebx ; high word must be 0 in loop for addressing + + mov bl,ds:byte ptr[1+esi] + sub ecx,ecx ; high word must be 0 in loop for addressing + + mov bh,dh + mov cl,ds:byte ptr[esi] + + add edx,ebp + mov ch,dh + + mov al,ds:byte ptr[12345678h+ebx] +LBPatch16: + mov edx,ds:dword ptr[_lightright] + + mov ds:byte ptr[1+edi],al + mov al,ds:byte ptr[12345678h+ecx] +LBPatch17: + + mov ds:byte ptr[edi],al + mov eax,ds:dword ptr[_sourcetstep] + + add esi,eax + mov eax,ds:dword ptr[_surfrowbytes] + + add edi,eax + mov eax,ds:dword ptr[_lightdeltastep] + + mov ebp,ds:dword ptr[_lightdelta] + mov cl,ds:byte ptr[esi] + + add ebp,eax + mov eax,ds:dword ptr[_lightrightstep] + + sar ebp,1 + add edx,eax + + mov bh,dh + mov bl,ds:byte ptr[1+esi] + + add edx,ebp + mov ch,dh + + mov al,ds:byte ptr[12345678h+ebx] +LBPatch30: + mov edx,ds:dword ptr[_sourcetstep] + + mov ds:byte ptr[1+edi],al + mov al,ds:byte ptr[12345678h+ecx] +LBPatch31: + + mov ds:byte ptr[edi],al + mov ebp,ds:dword ptr[_surfrowbytes] + + add esi,edx + add edi,ebp + +; if (pbasesource >= r_sourcemax) +; pbasesource -= stepback; + + cmp esi,ds:dword ptr[_r_sourcemax] + jb LSkip_mip3 + sub esi,ds:dword ptr[_r_stepback] +LSkip_mip3: + + mov ebx,ds:dword ptr[_r_lightptr] + dec ds:dword ptr[sb_v] + + jnz Lv_loop_mip3 + + pop ebx ; restore register variables + pop esi + pop edi + pop ebp ; restore the caller's stack frame + ret + + + public _R_Surf8End +_R_Surf8End: + +;---------------------------------------------------------------------- +; Code patching routines +;---------------------------------------------------------------------- +_TEXT ENDS +_DATA SEGMENT + + align 4 +LPatchTable8: + dd LBPatch0-4 + dd LBPatch1-4 + dd LBPatch2-4 + dd LBPatch3-4 + dd LBPatch4-4 + dd LBPatch5-4 + dd LBPatch6-4 + dd LBPatch7-4 + dd LBPatch8-4 + dd LBPatch9-4 + dd LBPatch10-4 + dd LBPatch11-4 + dd LBPatch12-4 + dd LBPatch13-4 + dd LBPatch14-4 + dd LBPatch15-4 + dd LBPatch16-4 + dd LBPatch17-4 + dd LBPatch18-4 + dd LBPatch19-4 + dd LBPatch20-4 + dd LBPatch21-4 + dd LBPatch22-4 + dd LBPatch23-4 + dd LBPatch24-4 + dd LBPatch25-4 + dd LBPatch26-4 + dd LBPatch27-4 + dd LBPatch28-4 + dd LBPatch29-4 + dd LBPatch30-4 + dd LBPatch31-4 + +_DATA ENDS +_TEXT SEGMENT + + align 4 + public _R_Surf8Patch +_R_Surf8Patch: + push ebx + + mov eax,ds:dword ptr[_colormap] + mov ebx,offset LPatchTable8 + mov ecx,32 +LPatchLoop8: + mov edx,ds:dword ptr[ebx] + add ebx,4 + mov ds:dword ptr[edx],eax + dec ecx + jnz LPatchLoop8 + + pop ebx + + ret + +_TEXT ENDS +endif ;id386 + + END + diff --git a/ref_soft/r_varsa.asm b/ref_soft/r_varsa.asm new file mode 100644 index 000000000..ac2f79e81 --- /dev/null +++ b/ref_soft/r_varsa.asm @@ -0,0 +1,220 @@ + .386P + .model FLAT +; +; d_varsa.s +; + +include qasm.inc +include d_if.inc + +if id386 + +_DATA SEGMENT + +;------------------------------------------------------- +; ASM-only variables +;------------------------------------------------------- + public float_1, float_particle_z_clip, float_point5 + public float_minus_1, float_0 +float_0 dd 0.0 +float_1 dd 1.0 +float_minus_1 dd -1.0 +float_particle_z_clip dd PARTICLE_Z_CLIP +float_point5 dd 0.5 + + public fp_16, fp_64k, fp_1m, fp_64kx64k + public fp_1m_minus_1 + public fp_8 +fp_1m dd 1048576.0 +fp_1m_minus_1 dd 1048575.0 +fp_64k dd 65536.0 +fp_8 dd 8.0 +fp_16 dd 16.0 +fp_64kx64k dd 04f000000h ; (float)0x8000*0x10000 + + + public FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd +FloatZero dd 0 +Float2ToThe31nd dd 04f000000h +FloatMinus2ToThe31nd dd 0cf000000h + + public _r_bmodelactive +_r_bmodelactive dd 0 + + +;------------------------------------------------------- +; global refresh variables +;------------------------------------------------------- + +; FIXME: put all refresh variables into one contiguous block. Make into one +; big structure, like cl or sv? + + align 4 + public _d_sdivzstepu + public _d_tdivzstepu + public _d_zistepu + public _d_sdivzstepv + public _d_tdivzstepv + public _d_zistepv + public _d_sdivzorigin + public _d_tdivzorigin + public _d_ziorigin +_d_sdivzstepu dd 0 +_d_tdivzstepu dd 0 +_d_zistepu dd 0 +_d_sdivzstepv dd 0 +_d_tdivzstepv dd 0 +_d_zistepv dd 0 +_d_sdivzorigin dd 0 +_d_tdivzorigin dd 0 +_d_ziorigin dd 0 + + public _sadjust + public _tadjust + public _bbextents + public _bbextentt +_sadjust dd 0 +_tadjust dd 0 +_bbextents dd 0 +_bbextentt dd 0 + + public _cacheblock + public _d_viewbuffer + public _cachewidth + public _d_pzbuffer + public _d_zrowbytes + public _d_zwidth +_cacheblock dd 0 +_cachewidth dd 0 +_d_viewbuffer dd 0 +_d_pzbuffer dd 0 +_d_zrowbytes dd 0 +_d_zwidth dd 0 + + +;------------------------------------------------------- +; ASM-only variables +;------------------------------------------------------- + public izi +izi dd 0 + + public pbase, s, t, sfracf, tfracf, snext, tnext + public spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu + public zi8stepu, sdivz8stepu, tdivz8stepu, pz +s dd 0 +t dd 0 +snext dd 0 +tnext dd 0 +sfracf dd 0 +tfracf dd 0 +pbase dd 0 +zi8stepu dd 0 +sdivz8stepu dd 0 +tdivz8stepu dd 0 +zi16stepu dd 0 +sdivz16stepu dd 0 +tdivz16stepu dd 0 +spancountminus1 dd 0 +pz dd 0 + + public izistep +izistep dd 0 + +;------------------------------------------------------- +; local variables for d_draw16.s +;------------------------------------------------------- + + public reciprocal_table_16, entryvec_table_16 +; 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, +; 1/14, and 1/15 in 0.32 form +reciprocal_table_16 dd 040000000h, 02aaaaaaah, 020000000h + dd 019999999h, 015555555h, 012492492h + dd 010000000h, 0e38e38eh, 0ccccccch, 0ba2e8bah + dd 0aaaaaaah, 09d89d89h, 09249249h, 08888888h + + externdef Entry2_16:dword + externdef Entry3_16:dword + externdef Entry4_16:dword + externdef Entry5_16:dword + externdef Entry6_16:dword + externdef Entry7_16:dword + externdef Entry8_16:dword + externdef Entry9_16:dword + externdef Entry10_16:dword + externdef Entry11_16:dword + externdef Entry12_16:dword + externdef Entry13_16:dword + externdef Entry14_16:dword + externdef Entry15_16:dword + externdef Entry16_16:dword + +entryvec_table_16 dd 0, Entry2_16, Entry3_16, Entry4_16 + dd Entry5_16, Entry6_16, Entry7_16, Entry8_16 + dd Entry9_16, Entry10_16, Entry11_16, Entry12_16 + dd Entry13_16, Entry14_16, Entry15_16, Entry16_16 + +;------------------------------------------------------- +; local variables for d_parta.s +;------------------------------------------------------- + public DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix +DP_Count dd 0 +DP_u dd 0 +DP_v dd 0 +DP_32768 dd 32768.0 +DP_Color dd 0 +DP_Pix dd 0 + + +;externdef DP_1x1:dword +;externdef DP_2x2:dword +;externdef DP_3x3:dword +;externdef DP_4x4:dword + +;DP_EntryTable dd DP_1x1, DP_2x2, DP_3x3, DP_4x4 + +; +; advancetable is 8 bytes, but points to the middle of that range so negative +; offsets will work +; + public advancetable, sstep, tstep, pspantemp, counttemp, jumptemp +advancetable dd 0, 0 +sstep dd 0 +tstep dd 0 + +pspantemp dd 0 +counttemp dd 0 +jumptemp dd 0 + +; 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form +; public reciprocal_table, entryvec_table +reciprocal_table dd 040000000h, 02aaaaaaah, 020000000h + dd 019999999h, 015555555h, 012492492h + + +; externdef Entry2_8:dword +; externdef Entry3_8:dword +; externdef Entry4_8:dword +; externdef Entry5_8:dword +; externdef Entry6_8:dword +; externdef Entry7_8:dword +; externdef Entry8_8:dword + +;entryvec_table dd 0, Entry2_8, Entry3_8, Entry4_8 +; dd Entry5_8, Entry6_8, Entry7_8, Entry8_8 + + externdef Spr8Entry2_8:dword + externdef Spr8Entry3_8:dword + externdef Spr8Entry4_8:dword + externdef Spr8Entry5_8:dword + externdef Spr8Entry6_8:dword + externdef Spr8Entry7_8:dword + externdef Spr8Entry8_8:dword + + public spr8entryvec_table +spr8entryvec_table dd 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8 + dd Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8 + + +_DATA ENDS +endif ; id386 + END diff --git a/ref_soft/rand1k.h b/ref_soft/rand1k.h new file mode 100644 index 000000000..41a54f736 --- /dev/null +++ b/ref_soft/rand1k.h @@ -0,0 +1,123 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// 1K random numbers in the range 0-255 +0, 144, 49, 207, 149, 122, 89, 229, 210, 191, +44, 219, 181, 131, 77, 3, 23, 93, 37, 42, +253, 114, 30, 1, 2, 96, 136, 146, 154, 155, +42, 169, 115, 90, 14, 155, 200, 205, 133, 77, +224, 186, 244, 236, 138, 36, 118, 60, 220, 53, +199, 215, 255, 255, 156, 100, 68, 76, 215, 6, +96, 23, 173, 14, 2, 235, 70, 69, 150, 176, +214, 185, 124, 52, 190, 119, 117, 242, 190, 27, +153, 98, 188, 155, 146, 92, 38, 57, 108, 205, +132, 253, 192, 88, 43, 168, 125, 16, 179, 129, +37, 243, 36, 231, 177, 77, 109, 18, 247, 174, +39, 224, 210, 149, 48, 45, 209, 121, 39, 129, +187, 103, 71, 145, 174, 193, 184, 121, 31, 94, +213, 8, 132, 169, 109, 26, 243, 235, 140, 88, +120, 95, 216, 81, 116, 69, 251, 76, 189, 145, +50, 194, 214, 101, 128, 227, 7, 254, 146, 12, +136, 49, 215, 160, 168, 50, 215, 31, 28, 190, +80, 240, 73, 86, 35, 187, 213, 181, 153, 191, +64, 36, 0, 15, 206, 218, 53, 29, 141, 3, +29, 116, 192, 175, 139, 18, 111, 51, 178, 74, +111, 59, 147, 136, 160, 41, 129, 246, 178, 236, +48, 86, 45, 254, 117, 255, 24, 160, 24, 112, +238, 12, 229, 74, 58, 196, 105, 51, 160, 154, +115, 119, 153, 162, 218, 212, 159, 184, 144, 96, +47, 188, 142, 231, 62, 48, 154, 178, 149, 89, +126, 20, 189, 156, 158, 176, 205, 38, 147, 222, +233, 157, 186, 11, 170, 249, 80, 145, 78, 44, +27, 222, 217, 190, 39, 83, 20, 19, 164, 209, +139, 114, 104, 76, 119, 128, 39, 82, 188, 80, +211, 245, 223, 185, 76, 241, 32, 16, 200, 134, +156, 244, 18, 224, 167, 82, 26, 129, 58, 74, +235, 141, 169, 29, 126, 97, 127, 203, 130, 97, +176, 136, 155, 101, 1, 181, 25, 159, 220, 125, +191, 127, 97, 201, 141, 91, 244, 161, 45, 95, +33, 190, 243, 156, 7, 84, 14, 163, 33, 216, +221, 152, 184, 218, 3, 32, 181, 157, 55, 16, +43, 159, 87, 81, 94, 169, 205, 206, 134, 156, +204, 230, 37, 161, 103, 64, 34, 218, 16, 109, +146, 77, 140, 57, 79, 28, 206, 34, 72, 201, +229, 202, 190, 157, 92, 219, 58, 221, 58, 63, +138, 252, 13, 20, 134, 109, 24, 66, 228, 59, +37, 32, 238, 20, 12, 15, 86, 234, 102, 110, +242, 214, 136, 215, 177, 101, 66, 1, 134, 244, +102, 61, 149, 65, 175, 241, 111, 227, 1, 240, +153, 201, 147, 36, 56, 98, 1, 106, 21, 168, +218, 16, 207, 169, 177, 205, 135, 175, 36, 176, +186, 199, 7, 222, 164, 180, 21, 141, 242, 15, +70, 37, 251, 158, 74, 236, 94, 177, 55, 39, +61, 133, 230, 27, 231, 113, 20, 200, 43, 249, +198, 222, 53, 116, 0, 192, 29, 103, 79, 254, +9, 64, 48, 63, 39, 158, 226, 240, 50, 199, +165, 168, 232, 116, 235, 170, 38, 162, 145, 108, +241, 138, 148, 137, 65, 101, 89, 9, 203, 50, +17, 99, 151, 18, 50, 39, 164, 116, 154, 178, +112, 175, 101, 213, 151, 51, 243, 224, 100, 252, +47, 229, 147, 113, 160, 181, 12, 73, 66, 104, +229, 181, 186, 229, 100, 101, 231, 79, 99, 146, +90, 187, 190, 188, 189, 35, 51, 69, 174, 233, +94, 132, 28, 232, 51, 132, 167, 112, 176, 23, +20, 19, 7, 90, 78, 178, 36, 101, 17, 172, +185, 50, 177, 157, 167, 139, 25, 139, 12, 249, +118, 248, 186, 135, 174, 177, 95, 99, 12, 207, +43, 15, 79, 200, 54, 82, 124, 2, 112, 130, +155, 194, 102, 89, 215, 241, 159, 255, 13, 144, +221, 99, 78, 72, 6, 156, 100, 4, 7, 116, +219, 239, 102, 186, 156, 206, 224, 149, 152, 20, +203, 118, 151, 150, 145, 208, 172, 87, 2, 68, +87, 59, 197, 95, 222, 29, 185, 161, 228, 46, +137, 230, 199, 247, 50, 230, 204, 244, 217, 227, +160, 47, 157, 67, 64, 187, 201, 43, 182, 123, +20, 206, 218, 31, 78, 146, 121, 195, 49, 186, +254, 3, 165, 177, 44, 18, 70, 173, 214, 142, +95, 199, 59, 163, 59, 52, 248, 72, 5, 196, +38, 12, 2, 89, 164, 87, 106, 106, 23, 139, +179, 86, 168, 224, 137, 145, 13, 119, 66, 109, +221, 124, 22, 144, 181, 199, 221, 217, 75, 221, +165, 191, 212, 195, 223, 232, 233, 133, 112, 27, +90, 210, 109, 43, 0, 168, 198, 16, 22, 98, +175, 206, 39, 36, 12, 88, 4, 250, 165, 13, +234, 163, 110, 5, 62, 100, 167, 200, 5, 211, +35, 162, 140, 251, 118, 54, 76, 200, 87, 123, +155, 26, 252, 193, 38, 116, 182, 255, 198, 164, +159, 242, 176, 74, 145, 74, 140, 182, 63, 139, +126, 243, 171, 195, 159, 114, 204, 190, 253, 52, +161, 232, 151, 235, 129, 125, 115, 227, 240, 46, +64, 51, 187, 240, 160, 10, 164, 8, 142, 139, +114, 15, 254, 32, 153, 12, 44, 169, 85, 80, +167, 105, 109, 56, 173, 42, 127, 129, 205, 111, +1, 86, 96, 32, 211, 187, 228, 164, 166, 131, +187, 188, 245, 119, 92, 28, 231, 210, 116, 27, +222, 194, 10, 106, 239, 17, 42, 54, 29, 151, +30, 158, 148, 176, 187, 234, 171, 76, 207, 96, +255, 197, 52, 43, 99, 46, 148, 50, 245, 48, +97, 77, 30, 50, 11, 197, 194, 225, 0, 114, +109, 205, 118, 126, 191, 61, 143, 23, 236, 228, +219, 15, 125, 161, 191, 193, 65, 232, 202, 51, +141, 13, 133, 202, 180, 6, 187, 141, 234, 224, +204, 78, 101, 123, 13, 166, 0, 196, 193, 56, +39, 14, 171, 8, 88, 178, 204, 111, 251, 162, +75, 122, 223, 20, 25, 36, 36, 235, 79, 95, +208, 11, 208, 61, 229, 65, 68, 53, 58, 216, +223, 227, 216, 155, 10, 44, 47, 91, 115, 47, +228, 159, 139, 233 diff --git a/ref_soft/ref_soft.001 b/ref_soft/ref_soft.001 new file mode 100644 index 000000000..5afafe002 --- /dev/null +++ b/ref_soft/ref_soft.001 @@ -0,0 +1,1498 @@ +# Microsoft Developer Studio Project File - Name="ref_soft" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=ref_soft - Win32 Debug Alpha +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ref_soft.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ref_soft.mak" CFG="ref_soft - Win32 Debug Alpha" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ref_soft - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ref_soft - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ref_soft - Win32 Debug Alpha" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "ref_soft - Win32 Release Alpha" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\ref_soft" +# PROP BASE Intermediate_Dir ".\ref_soft" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\release" +# PROP Intermediate_Dir ".\release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386 +# SUBTRACT LINK32 /debug + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ref_soft" +# PROP BASE Intermediate_Dir ".\ref_soft" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\debug" +# PROP Intermediate_Dir ".\debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /nodefaultlib:"libc" +# SUBTRACT LINK32 /profile /nodefaultlib + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug Alpha" +# PROP BASE Intermediate_Dir "Debug Alpha" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\DebugAxp" +# PROP Intermediate_Dir ".\DebugAxp" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MTd /Gt0 /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA /nodefaultlib:"libc" +# SUBTRACT BASE LINK32 /nodefaultlib +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA /nodefaultlib:"libc" +# SUBTRACT LINK32 /nodefaultlib + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ref_soft" +# PROP BASE Intermediate_Dir "ref_soft" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\ReleaseAXP" +# PROP Intermediate_Dir ".\ReleaseAXP" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c +# SUBTRACT CPP /Z /Fr +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:ALPHA +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:ALPHA +# SUBTRACT LINK32 /debug + +!ENDIF + +# Begin Target + +# Name "ref_soft - Win32 Release" +# Name "ref_soft - Win32 Debug" +# Name "ref_soft - Win32 Debug Alpha" +# Name "ref_soft - Win32 Release Alpha" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\game\q_shared.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_Q_SHA=\ + "..\game\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_Q_SHA=\ + "..\game\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_Q_SHA=\ + "..\game\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\q_shwin.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_Q_SHW=\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\winquake.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_Q_SHW=\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\winquake.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_Q_SHW=\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\winquake.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_aclip.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_ACL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_ACL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_ACL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_aclipa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_aclipa.asm +InputName=r_aclipa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_aclipa.asm +InputName=r_aclipa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_alias.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_ALI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\anorms.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_ALI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\anorms.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_ALI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\anorms.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_bsp.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_BSP=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_BSP=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_BSP=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_draw.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_DRA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_DRA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_DRA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_draw16.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_draw16.asm +InputName=r_draw16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_draw16.asm +InputName=r_draw16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_drawa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_drawa.asm +InputName=r_drawa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_drawa.asm +InputName=r_drawa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_edge.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_EDG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_EDG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_EDG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_edgea.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_edgea.asm +InputName=r_edgea + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_edgea.asm +InputName=r_edgea + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_image.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_IMA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_IMA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_IMA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_light.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_LIG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_LIG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_LIG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_main.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_MAI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_MAI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_MAI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_misc.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_MIS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_MIS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_MIS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_model.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_MOD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_MOD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_MOD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_part.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_PAR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_PAR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_PAR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_poly.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_POL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_POL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_POL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_polysa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_polysa.asm +InputName=r_polysa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_polysa.asm +InputName=r_polysa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_polyse.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_POLY=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\adivtab.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + ".\rand1k.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_POLY=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\adivtab.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + ".\rand1k.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_POLY=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\adivtab.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + ".\rand1k.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_rast.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_RAS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_RAS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_RAS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_scan.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_SCA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_SCA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_SCA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_scana.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_scana.asm +InputName=r_scana + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_scana.asm +InputName=r_scana + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_spr8.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_spr8.asm +InputName=r_spr8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_spr8.asm +InputName=r_spr8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_sprite.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_SPR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_SPR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_SPR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_surf.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_SUR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_SUR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_SUR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_surf8.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_surf8.asm +InputName=r_surf8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_surf8.asm +InputName=r_surf8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_varsa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_varsa.asm +InputName=r_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_varsa.asm +InputName=r_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_ddraw.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_RW_DD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_RW_DD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_RW_DD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_dib.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_RW_DI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_RW_DI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_RW_DI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_imp.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_RW_IM=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + "..\win32\winquake.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_RW_IM=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + "..\win32\winquake.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_RW_IM=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + "..\win32\winquake.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\adivtab.h +# End Source File +# Begin Source File + +SOURCE=.\anorms.h +# End Source File +# Begin Source File + +SOURCE=..\game\q_shared.h +# End Source File +# Begin Source File + +SOURCE=..\qcommon\qcommon.h +# End Source File +# Begin Source File + +SOURCE=..\qcommon\qfiles.h +# End Source File +# Begin Source File + +SOURCE=.\r_local.h +# End Source File +# Begin Source File + +SOURCE=.\r_model.h +# End Source File +# Begin Source File + +SOURCE=.\rand1k.h +# End Source File +# Begin Source File + +SOURCE=..\client\ref.h +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_win.h +# End Source File +# Begin Source File + +SOURCE=..\win32\winquake.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\ref_soft.def +# End Source File +# End Group +# End Target +# End Project diff --git a/ref_soft/ref_soft.def b/ref_soft/ref_soft.def new file mode 100644 index 000000000..cfbb47133 --- /dev/null +++ b/ref_soft/ref_soft.def @@ -0,0 +1,2 @@ +EXPORTS + GetRefAPI diff --git a/ref_soft/ref_soft.dsp b/ref_soft/ref_soft.dsp new file mode 100644 index 000000000..799b0e68c --- /dev/null +++ b/ref_soft/ref_soft.dsp @@ -0,0 +1,1496 @@ +# Microsoft Developer Studio Project File - Name="ref_soft" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=ref_soft - Win32 Debug Alpha +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ref_soft.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ref_soft.mak" CFG="ref_soft - Win32 Debug Alpha" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ref_soft - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ref_soft - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ref_soft - Win32 Debug Alpha" (based on "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "ref_soft - Win32 Release Alpha" (based on "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\ref_soft" +# PROP BASE Intermediate_Dir ".\ref_soft" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\release" +# PROP Intermediate_Dir ".\release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386 +# SUBTRACT LINK32 /debug + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ref_soft" +# PROP BASE Intermediate_Dir ".\ref_soft" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\debug" +# PROP Intermediate_Dir ".\debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /nodefaultlib:"libc" +# SUBTRACT LINK32 /profile /nodefaultlib + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug Alpha" +# PROP BASE Intermediate_Dir "Debug Alpha" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\DebugAxp" +# PROP Intermediate_Dir ".\DebugAxp" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MTd /Gt0 /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA /nodefaultlib:"libc" +# SUBTRACT BASE LINK32 /nodefaultlib +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA /nodefaultlib:"libc" +# SUBTRACT LINK32 /nodefaultlib + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ref_soft" +# PROP BASE Intermediate_Dir "ref_soft" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\ReleaseAXP" +# PROP Intermediate_Dir ".\ReleaseAXP" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c +# SUBTRACT CPP /Z /Fr +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:ALPHA +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:ALPHA +# SUBTRACT LINK32 /debug + +!ENDIF + +# Begin Target + +# Name "ref_soft - Win32 Release" +# Name "ref_soft - Win32 Debug" +# Name "ref_soft - Win32 Debug Alpha" +# Name "ref_soft - Win32 Release Alpha" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\game\q_shared.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_Q_SHA=\ + "..\game\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_Q_SHA=\ + "..\game\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_Q_SHA=\ + "..\game\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\q_shwin.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_Q_SHW=\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\winquake.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_Q_SHW=\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\winquake.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_Q_SHW=\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\winquake.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_aclip.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_ACL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_ACL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_ACL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_aclipa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_aclipa.asm +InputName=r_aclipa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_aclipa.asm +InputName=r_aclipa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_alias.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_ALI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\anorms.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_ALI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\anorms.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_ALI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\anorms.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_bsp.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_BSP=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_BSP=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_BSP=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_draw.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_DRA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_DRA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_DRA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_draw16.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_draw16.asm +InputName=r_draw16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_draw16.asm +InputName=r_draw16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_drawa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_drawa.asm +InputName=r_drawa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_drawa.asm +InputName=r_drawa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_edge.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_EDG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_EDG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_EDG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_edgea.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_edgea.asm +InputName=r_edgea + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_edgea.asm +InputName=r_edgea + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_image.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_IMA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_IMA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_IMA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_light.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_LIG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_LIG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_LIG=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_main.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_MAI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_MAI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_MAI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_misc.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_MIS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_MIS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_MIS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_model.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_MOD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_MOD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_MOD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_part.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_PAR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_PAR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_PAR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_poly.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_POL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_POL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_POL=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_polysa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_polysa.asm +InputName=r_polysa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_polysa.asm +InputName=r_polysa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_polyse.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_POLY=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\adivtab.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + ".\rand1k.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_POLY=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\adivtab.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + ".\rand1k.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_POLY=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\adivtab.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + ".\rand1k.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_rast.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_RAS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_RAS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_RAS=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_scan.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_SCA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_SCA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_SCA=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_scana.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_scana.asm +InputName=r_scana + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_scana.asm +InputName=r_scana + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_spr8.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_spr8.asm +InputName=r_spr8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_spr8.asm +InputName=r_spr8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_sprite.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_SPR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_SPR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_SPR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_surf.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_R_SUR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_R_SUR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_R_SUR=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_surf8.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_surf8.asm +InputName=r_surf8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_surf8.asm +InputName=r_surf8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_varsa.asm + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +# Begin Custom Build +OutDir=.\..\release +InputPath=.\r_varsa.asm +InputName=r_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +# Begin Custom Build +OutDir=.\..\debug +InputPath=.\r_varsa.asm +InputName=r_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_ddraw.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_RW_DD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_RW_DD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_RW_DD=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_dib.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_RW_DI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_RW_DI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_RW_DI=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_imp.c + +!IF "$(CFG)" == "ref_soft - Win32 Release" + +DEP_CPP_RW_IM=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + "..\win32\winquake.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug" + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Debug Alpha" + +DEP_CPP_RW_IM=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + "..\win32\winquake.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ELSEIF "$(CFG)" == "ref_soft - Win32 Release Alpha" + +DEP_CPP_RW_IM=\ + "..\client\ref.h"\ + "..\game\q_shared.h"\ + "..\qcommon\qcommon.h"\ + "..\qcommon\qfiles.h"\ + "..\win32\rw_win.h"\ + "..\win32\winquake.h"\ + ".\r_local.h"\ + ".\r_model.h"\ + + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\adivtab.h +# End Source File +# Begin Source File + +SOURCE=.\anorms.h +# End Source File +# Begin Source File + +SOURCE=..\game\q_shared.h +# End Source File +# Begin Source File + +SOURCE=..\qcommon\qcommon.h +# End Source File +# Begin Source File + +SOURCE=..\qcommon\qfiles.h +# End Source File +# Begin Source File + +SOURCE=.\r_local.h +# End Source File +# Begin Source File + +SOURCE=.\r_model.h +# End Source File +# Begin Source File + +SOURCE=.\rand1k.h +# End Source File +# Begin Source File + +SOURCE=..\client\ref.h +# End Source File +# Begin Source File + +SOURCE=..\win32\rw_win.h +# End Source File +# Begin Source File + +SOURCE=..\win32\winquake.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\ref_soft.def +# End Source File +# End Group +# End Target +# End Project diff --git a/ref_soft/ref_soft.plg b/ref_soft/ref_soft.plg new file mode 100644 index 000000000..b651f0bbb --- /dev/null +++ b/ref_soft/ref_soft.plg @@ -0,0 +1,17 @@ +--------------------Configuration: ref_soft - Win32 Release Alpha-------------------- +Begining build with project "G:\quake2\code\ref_soft\ref_soft.dsp", at root. +Active configuration is Win32 (ALPHA) Dynamic-Link Library (based on Win32 (ALPHA) Dynamic-Link Library) + +Project's tools are: + "OLE Type Library Maker" with flags "/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 " + "C/C++ Compiler for Alpha" with flags "/nologo /QA21164 /MT /Gt0 /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /Fp".\ReleaseAXP/ref_soft.pch" /YX /Fo".\ReleaseAXP/" /Fd".\ReleaseAXP/" /FD /QAieee1 /c " + "Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" " + "Browser Database Maker" with flags "/nologo /o"..\ReleaseAXP/ref_soft.bsc" " + "COFF Linker for Alpha" with flags "kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\ReleaseAXP/ref_soft.pdb" /debug /machine:ALPHA /def:".\ref_soft.def" /out:"..\ReleaseAXP/ref_soft.dll" /implib:"..\ReleaseAXP/ref_soft.lib" " + "Custom Build" with flags "" + "" with flags "" + + + + +ref_soft.dll - 0 error(s), 0 warning(s) diff --git a/rhapsody/in_next.m b/rhapsody/in_next.m new file mode 100644 index 000000000..97022bd08 --- /dev/null +++ b/rhapsody/in_next.m @@ -0,0 +1,332 @@ +// in_next.m + +#import +#import +#include "../client/client.h" + +float mousex, mousey; + +float mouse_center_x = 160; +float mouse_center_y = 100; + +void PSsetmouse (float x, float y); +void PSshowcursor (void); +void PShidecursor (void); +void PScurrentmouse (int win, float *x, float *y); + +extern NSView *vid_view_i; +extern NSWindow *vid_window_i; + +qboolean mlooking; +qboolean mouseinitialized; +int mouse_buttons; +int mouse_oldbuttonstate; +int mouseactive; +int mousereset; +int mx_accum, my_accum; +int window_center_x, window_center_y; +int old_mouse_x, old_mouse_y; + +cvar_t in_mouse = {"in_mouse", "0", CVAR_ARCHIVE}; +cvar_t m_filter = {"m_filter", "0", CVAR_ARCHIVE}; +cvar_t freelook = {"in_freelook", "0", CVAR_ARCHIVE}; + + +/* +=========== +IN_ActivateMouse + +Called when the window gains focus or changes in some way +=========== +*/ +void IN_ActivateMouse (void) +{ + NSRect r; + + if (!mouseinitialized) + return; + if (!in_mouse.value) + return; + + r = [vid_window_i frame]; + window_center_x = r.size.width / 2; + window_center_y = r.size.height / 2; + + if (!mouseactive) + PShidecursor (); + + mouseactive = true; + mousereset = true; +} + + +/* +=========== +IN_DeactivateMouse + +Called when the window loses focus +=========== +*/ +void IN_DeactivateMouse (void) +{ + if (!mouseinitialized) + return; + + if (mouseactive) + PSshowcursor (); + + mouseactive = false; +} + + +/* +=========== +IN_StartupMouse +=========== +*/ +void IN_StartupMouse (void) +{ + if ( COM_CheckParm ("-nomouse") ) + return; + + mouseinitialized = true; + + mouse_buttons = 3; + + IN_ActivateMouse (); +} + +/* +=========== +IN_MouseEvent +=========== +*/ +void IN_MouseEvent (int mstate) +{ + int i; + + if (!mouseactive) + return; + +// perform button actions + for (i=0 ; isidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + + if ( (mlooking || freelook.value) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } + else + { + cmd->forwardmove -= m_forward.value * mouse_y; + } + +} + +void IN_ShowMouse (void) +{ + PSshowcursor (); +} + +void IN_HideMouse (void) +{ + PShidecursor (); +} + +NXEventHandle eventhandle; +NXMouseScaling oldscaling, newscaling; +NXMouseButton oldbutton; + +/* + ============= + IN_Init + ============= + */ +void IN_Init (void) +{ + Cvar_RegisterVariable (&in_mouse); + Cvar_RegisterVariable (&m_filter); + Cvar_RegisterVariable (&freelook); + + Cmd_AddCommand ("showmouse", IN_ShowMouse); + Cmd_AddCommand ("hidemouse", IN_HideMouse); + + IN_StartupMouse (); + + // open the event status driver + eventhandle = NXOpenEventStatus(); + NXGetMouseScaling (eventhandle, &oldscaling); + NXSetMouseScaling (eventhandle, &newscaling); + oldbutton = NXMouseButtonEnabled (eventhandle); + NXEnableMouseButton (eventhandle, 2); +} + +/* + ============= + IN_Shutdown + ============= + */ +void IN_Shutdown (void) +{ + IN_DeactivateMouse (); + + // put mouse scaling back the way it was + NXSetMouseScaling (eventhandle, &oldscaling); + NXEnableMouseButton (eventhandle, oldbutton); + NXCloseEventStatus (eventhandle); +} + +void IN_Move (usercmd_t *cmd) +{ + IN_MouseMove (cmd); +} + +void IN_Commands (void) +{ +} + + +/* +========================================================================= + +VIEW CENTERING + +========================================================================= +*/ + +void V_StopPitchDrift (void) +{ + cl.laststop = cl.time; + cl.nodrift = true; + cl.pitchvel = 0; +} diff --git a/rhapsody/makefile.bak b/rhapsody/makefile.bak new file mode 100644 index 000000000..213fde301 --- /dev/null +++ b/rhapsody/makefile.bak @@ -0,0 +1,63 @@ + +CFLAGS = -O -g -DGAME_HARD_LINKED -DREF_HARD_LINKED +LDFLAGS = -sectcreate __ICON __header quake2.iconheader -segprot __ICON r r -sectcreate __ICON app quake2.tiff -framework AppKit -framework Foundation +EXE = quake2 +TARGETS = $(EXE) + +all: $(TARGETS) + +#---------------------------------------------------------------------- + +SERVERFILES = sv_ccmds.o sv_ents.o sv_game.o sv_init.o sv_main.o sv_send.o sv_user.o sv_world.o + +GAMEFILES = g_ai.o g_cmds.o g_combat.o g_func.o g_items.o g_main.o g_misc.o g_monster.o g_phys.o g_save.o g_spawn.o g_target.o g_trigger.o g_utils.o g_weapon.o g_turret.o m_actor.o m_berserk.o m_boss2.o m_boss3.o m_boss31.o m_boss32.o m_brain.o m_chick.o m_flipper.o m_float.o m_flyer.o m_gladiator.o m_gunner.o m_hover.o m_infantry.o m_insane.o m_medic.o m_move.o m_mutant.o m_parasite.o m_soldier.o m_supertank.o m_tank.o p_client.o p_hud.o p_trail.o p_view.o p_weapon.o + +CLIENTFILES = cl_ents.o cl_fx.o cl_input.o cl_inv.o cl_main.o cl_parse.o cl_pred.o cl_scrn.o cl_cin.o cl_tent.o cl_view.o console.o keys.o menu.o qmenu.o snd_dma.o snd_mem.o snd_mix.o + +# commonfiles are used by both client and server +COMMONFILES = m_flash.o cmd.o cmodel.o common.o cvar.o files.o md4.o net_chan.o net_udp.o pmove.o + +REFGLFILES = gl_draw.o gl_light.o gl_mesh.o gl_model.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_warp.o gl_image.o + +REFSOFTFILES = r_aclip.o r_alias.o r_bsp.o r_draw.o r_edge.o r_image.o r_light.o r_main.o r_misc.o r_model.o r_part.o r_polyse.o r_poly.o r_rast.o r_scan.o r_sprite.o r_surf.o + +# sharedfiles are included in EVERY dll +SHAREDFILES = q_shared.o + +IRIXFILES = cd_sgi.o glx_imp.o qgl_sgi.o sys_sgi.o vid_sgi.o in_sgi.o snddma_null.o + +RHAPFILES = cd_null.o in_null.o snddma_null.o sys_rhap.o vid_null.o swimp_rhap.o + +NULLFILES = cd_null.o in_null.o snddma_null.o sys_null.o vid_null.o swimp_null.o + +#---------------------------------------------------------------------- + +FILES = $(SERVERFILES) $(GAMEFILES) $(COMMONFILES) $(CLIENTFILES) $(REFSOFTFILES) $(SHAREDFILES) $(RHAPFILES) + +$(EXE) : $(FILES) + cc -o $(EXE) $(FILES) $(LDFLAGS) + +clean: + rm -f $(EXE) $(FILES) + +#---------------------------------------------------------------------- + +# gnumake pattern rules are so cool! + +%.o : ../game/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../qcommon/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../client/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../server/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../ref_soft/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../ref_gl/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../null/%.c + cc $(CFLAGS) -c -o $@ $? +%.o : ../rhapsody/%.m + cc $(CFLAGS) -c -o $@ $? + diff --git a/rhapsody/notes.txt b/rhapsody/notes.txt new file mode 100644 index 000000000..ef2b5e61c --- /dev/null +++ b/rhapsody/notes.txt @@ -0,0 +1,34 @@ +f1 + +not calling back to set vid size after sw_mode change? + +do vid_xpos / ypos creep because of frames? + +fix fullscreen fallback bug + +nsping + +icon + +don't make sys_error varargs + +cvar_stvalue in ref???? + +subframe event timing information + +swimp init / swimp_initgraphics? + +SWimp_SetMode shouldn't call + R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table ); + +subclass window instead of view? + +/* +** SWimp_SetPalette +** +** System specific palette setting routine. A NULL palette means +** to use the existing palette. The palette is expected to be in +** a padded 4-byte xRGB format. +*/ + +do we ever pass a NULL palette? diff --git a/rhapsody/pb.project b/rhapsody/pb.project new file mode 100644 index 000000000..92fc86ff4 --- /dev/null +++ b/rhapsody/pb.project @@ -0,0 +1,17 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (Foundation.framework); + OTHER_LINKED = (QuakeWorld_main.m); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(NEXT_ROOT)/NextDeveloper/Makefiles/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/NextDeveloper/bin/make; + PROJECTNAME = QuakeWorld; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.6; + WINDOWS_BUILDTOOL = $NEXT_ROOT/NextDeveloper/Executables/make; +} diff --git a/rhapsody/quake2.iconheader b/rhapsody/quake2.iconheader new file mode 100644 index 000000000..91b84515b --- /dev/null +++ b/rhapsody/quake2.iconheader @@ -0,0 +1,2 @@ +F test.app test app +F test test app diff --git a/rhapsody/quake2.tiff b/rhapsody/quake2.tiff new file mode 100644 index 000000000..2b8de5466 Binary files /dev/null and b/rhapsody/quake2.tiff differ diff --git a/rhapsody/r_next.m b/rhapsody/r_next.m new file mode 100644 index 000000000..902cbd6ca --- /dev/null +++ b/rhapsody/r_next.m @@ -0,0 +1,735 @@ + +#import +#include "../ref_soft/r_local.h" + +/* +==================================================================== + + OPENSTEP specific stuff + +==================================================================== +*/ + +@interface QuakeView : NSView +@end + +NSWindow *vid_window_i; +QuakeView *vid_view_i; + +unsigned *buffernative; + +//=========================================================== + + +int Draw_SetResolution (void); + +#define TYPE_FULLSCREEN 0 +#define TYPE_WINDOWED 1 +#define TYPE_STRETCHED 2 + +#define NUM_RESOLUTIONS 7 +int resolutions[NUM_RESOLUTIONS][2] = { + {320,200}, {320,240}, {400,300}, {512,384}, {640,480}, {800,600}, {1024,768} }; + +qboolean available[NUM_RESOLUTIONS][3]; +int mode_res = 0, mode_type = TYPE_WINDOWED; + +byte gammatable[256]; // palette is sent through this +unsigned current_palette[256]; +unsigned gamma_palette[256]; + +int cursor_res, cursor_type; + +cvar_t *vid_x; +cvar_t *vid_y; +cvar_t *vid_mode; +cvar_t *vid_stretched; +cvar_t *vid_fullscreen; +cvar_t *draw_gamma; + +void Draw_BuildGammaTable (void); + +/* +==================================================================== + +MENU INTERACTION + +==================================================================== +*/ + +void FindModes (void) +{ + if (mode_res < 0 || mode_res >= NUM_RESOLUTIONS) + mode_res = 0; + if (mode_type < 0 || mode_type > 3) + mode_type = 1; + +} + +void RM_Print (int x, int y, char *s) +{ + while (*s) + { + Draw_Char (x, y, (*s)+128); + s++; + x += 8; + } +} + +/* +================ +Draw_MenuDraw +================ +*/ +void Draw_MenuDraw (void) +{ + int i, j; + int y; + char string[32]; + + Draw_Pic ( 4, 4, "vidmodes"); + + RM_Print (80, 32, "fullscreen windowed stretched"); + RM_Print (80, 40, "---------- -------- ---------"); + y = 50; + + // draw background behind selected mode + Draw_Fill ( (mode_type+1)*80, y+(mode_res)*10, 40,10, 8); + + // draw available grid + for (i=0 ; i 2) + cursor_type = 0; + break; + + case K_UPARROW: + cursor_res--; + if (cursor_res < 0) + cursor_res = NUM_RESOLUTIONS-1; + break; + + case K_DOWNARROW: + cursor_res++; + if (cursor_res >= NUM_RESOLUTIONS) + cursor_res = 0; + break; + + case K_ENTER: + ri.Cmd_ExecuteText (EXEC_NOW, va("vid_mode %i", cursor_res)); + switch (cursor_type) + { + case TYPE_FULLSCREEN: + ri.Cmd_ExecuteText (EXEC_NOW, "vid_fullscreen 1"); + ri.Cmd_ExecuteText (EXEC_NOW, "vid_stretched 0"); + break; + case TYPE_WINDOWED: + ri.Cmd_ExecuteText (EXEC_NOW, "vid_fullscreen 0"); + ri.Cmd_ExecuteText (EXEC_NOW, "vid_stretched 0"); + break; + case TYPE_STRETCHED: + ri.Cmd_ExecuteText (EXEC_NOW, "vid_fullscreen 0"); + ri.Cmd_ExecuteText (EXEC_NOW, "vid_stretched 1"); + break; + } + + mode_res = cursor_res; + mode_type = cursor_type; + Draw_SetResolution (); + break; + + default: + break; + } +} + +//=========================================================== + + +/* +================ +Draw_SetResolution + +The vid structure will be filled in on return +Also allocates the z buffer and surface cache +================ +*/ +int Draw_SetResolution (void) +{ + NSRect content; + + if (vid_mode->value < 0) + ri.Cmd_ExecuteText (EXEC_NOW, "vid_mode 0"); + if (vid_mode->value >= NUM_RESOLUTIONS) + ri.Cmd_ExecuteText (EXEC_NOW, va("vid_mode %i", NUM_RESOLUTIONS-1)); + + vid_mode->modified = false; + vid_fullscreen->modified = false; + vid_stretched->modified = false; + + // free nativebuffer + if (buffernative) + { + free (buffernative); + buffernative = NULL; + } + + // free z buffer + if (d_pzbuffer) + { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // free surface cache + if (sc_base) + { + D_FlushCaches (); + free (sc_base); + sc_base = NULL; + } + + vid.width = resolutions[(int)(vid_mode->value)][0]; + vid.height = resolutions[(int)(vid_mode->value)][1]; + + vid.win_width = vid.width; + vid.win_height = vid.height; + if (vid_stretched->value) + { + vid.win_width <<= 1; + vid.win_height <<= 1; + } + + vid.aspect = 1; + vid.buffer = malloc (vid.width*vid.height); + vid.rowbytes = vid.width; + d_pzbuffer = malloc(vid.width*vid.height*2); + buffernative = malloc(vid.width*vid.height*4); + + D_InitCaches (); + + Sys_SetPalette ((byte *)d_8to24table); + + if (vid_view_i) + [vid_view_i unlockFocus]; + if (vid_window_i) + [vid_window_i close]; +// +// open a window +// + content = NSMakeRect (vid_x->value,vid_y->value,vid.win_width, vid.win_height); + vid_window_i = [[NSWindow alloc] + initWithContentRect: content + styleMask: NSTitledWindowMask + backing: NSBackingStoreRetained + defer: NO + ]; + + [vid_window_i setDelegate: vid_window_i]; + [vid_window_i display]; + [NSApp activateIgnoringOtherApps: YES]; + [vid_window_i makeKeyAndOrderFront: nil]; + +// NSPing (); + + content.origin.x = content.origin.y = 0; + vid_view_i = [[QuakeView alloc] initWithFrame: content]; + [vid_window_i setContentView: vid_view_i]; + [vid_window_i makeFirstResponder: vid_view_i]; + [vid_window_i setDelegate: vid_view_i]; + +// [vid_window_i addToEventMask: NS_FLAGSCHANGEDMASK]; + [vid_window_i setTitle: @"Bitmap Quake Console"]; + [vid_window_i makeKeyAndOrderFront: nil]; + + // leave focus locked forever + [vid_view_i lockFocus]; + + ri.VID_SetSize (vid.width, vid.height); + + return 0; +} + +/* +@@@@@@@@@@@@@@@@@@@@@ +Draw_Init + +@@@@@@@@@@@@@@@@@@@@@ +*/ +int Draw_Init (void *window) +{ + [NSApplication sharedApplication]; + [NSApp finishLaunching]; + + ri.Con_Printf (PRINT_ALL, "refresh version: "REF_VERSION"\n"); + + vid_x = ri.Cvar_Get ("vid_x", "0", CVAR_ARCHIVE); + vid_y = ri.Cvar_Get ("vid_y", "0", CVAR_ARCHIVE); + vid_mode = ri.Cvar_Get ("vid_mode", "0", CVAR_ARCHIVE); + vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE); + vid_stretched = ri.Cvar_Get ("vid_stretched", "0", CVAR_ARCHIVE); + draw_gamma = ri.Cvar_Get ("gamma", "1", CVAR_ARCHIVE); + + Draw_GetPalette (); + + Draw_BuildGammaTable (); + + // get the lighting colormap + ri.FS_LoadFile ("gfx/colormap.lmp", (void **)&vid.colormap); + if (!vid.colormap) + { + ri.Con_Printf (PRINT_ALL, "ERROR: Couldn't load gfx/colormap.lmp"); + return -1; + } + + Draw_SetResolution (); + + R_Init (); + + return 0; +} + + +/* +@@@@@@@@@@@@@@@@@@@@@ +Draw_Shutdown + +@@@@@@@@@@@@@@@@@@@@@ +*/ +void Draw_Shutdown (void) +{ + R_Shutdown (); +} + + +/* +@@@@@@@@@@@@@@@@@@@@@ +Draw_BuildGammaTable + +@@@@@@@@@@@@@@@@@@@@@ +*/ +void Draw_BuildGammaTable (void) +{ + int i, inf; + float g; + + draw_gamma->modified = false; + g = draw_gamma->value; + + if (g == 1.0) + { + for (i=0 ; i<256 ; i++) + gammatable[i] = i; + return; + } + + for (i=0 ; i<256 ; i++) + { + inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + gammatable[i] = inf; + } +} + + +/* +@@@@@@@@@@@@@@@@@@@@@ +Draw_BeginFram + +@@@@@@@@@@@@@@@@@@@@@ +*/ +void Draw_BeginFrame (void) +{ + if (vid_mode->modified || vid_fullscreen->modified + || vid_stretched->modified) + Draw_SetResolution (); + + if (draw_gamma->modified) + { + Draw_BuildGammaTable (); + Sys_SetPalette ((byte *)current_palette); + } + +// MGL_beginDirectAccess(); +// vid.buffer = mgldc->surface; +// vid.rowbytes = mgldc->mi.bytesPerLine; +} + + +/* +@@@@@@@@@@@@@@@@@@@@@ +Draw_EndFrame + +@@@@@@@@@@@@@@@@@@@@@ +*/ +void Draw_EndFrame (void) +{ + int i, c; + int bps, spp, bpp, bpr; + unsigned char *planes[5]; + NSRect bounds; + + // translate to 24 bit color + c = vid.width*vid.height; + for (i=0 ; imagic = HUNK_MAGIC; + membase->length = maxsize; + cursize = 32; + return (void *)((byte *)membase + cursize); +} + +void *Hunk_Alloc (int size) +{ + // round to cacheline + size = (size+31)&~31; + + cursize += size; + + if (cursize > maxsize) + ri.Sys_Error (ERR_DROP, "Hunk_Alloc overflow"); + + memset ((byte *)membase+cursize-size,0,size); + + return (void *)((byte *)membase+cursize-size); +} + +int Hunk_End (void) +{ + kern_return_t r; + + // round to pagesize + cursize = (cursize+vm_page_size)&~(vm_page_size-1); + membase->length = cursize; + r = vm_deallocate(task_self(), + (vm_address_t)((byte *)membase + cursize), + maxsize - cursize); + if ( r != KERN_SUCCESS ) + ri.Sys_Error (ERR_DROP, "vm_deallocate failed"); + return cursize; +} + +void Hunk_Free (void *base) +{ + hunkheader_t *h; + kern_return_t r; + + h = ((hunkheader_t *)base) - 1; + if (h->magic != HUNK_MAGIC) + ri.Sys_Error (ERR_FATAL, "Hunk_Free: bad magic"); + + r = vm_deallocate(task_self(), (vm_address_t)h, h->length); + if ( r != KERN_SUCCESS ) + ri.Sys_Error (ERR_DROP, "vm_deallocate failed"); +} + + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ +} + + +/* +================ +Sys_SetPalette +================ +*/ +void Sys_SetPalette (byte *palette) +{ + byte *p; + int i; + + memcpy (current_palette, palette, sizeof(current_palette)); + p = (byte *)gamma_palette; + // gamma correct and byte swap + for (i=0 ; i<256 ; i++, p+=4, palette+=4) + { + p[0] = gammatable[palette[0]]; + p[1] = gammatable[palette[1]]; + p[2] = gammatable[palette[2]]; + p[3] = 0xff; + } + +} + + +/* + ========================================================================== + + NEXTSTEP VIEW CLASS + + ========================================================================== + */ +#include "../client/keys.h" + +void IN_ActivateMouse (void); +void IN_DeactivateMouse (void); + +@implementation QuakeView + +-(BOOL) acceptsFirstResponder +{ + return YES; +} + +- (void)windowDidMove: (NSNotification *)note +{ + NSRect r; + + r = [vid_window_i frame]; + ri.Cmd_ExecuteText (EXEC_NOW, va("vid_x %i", (int)r.origin.x+1)); + ri.Cmd_ExecuteText (EXEC_NOW, va("vid_y %i", (int)r.origin.y+1)); +} + +- (void)becomeKeyWindow +{ + IN_ActivateMouse (); +} + +- (void)resignKeyWindow +{ + IN_DeactivateMouse (); +} + + +typedef struct +{ + int source, dest; +} keymap_t; + +keymap_t keymaps[] = +{ + {103, K_RIGHTARROW}, + {102, K_LEFTARROW}, + {100, K_UPARROW}, + {101, K_DOWNARROW}, + + {59, K_F1}, + {60, K_F2}, + {61, K_F3}, + {62, K_F4}, + {63, K_F5}, + {64, K_F6}, + {65, K_F7}, + {66, K_F8}, + {67, K_F9}, + {68, K_F10}, + {87, K_F11}, + {88, K_F12}, + + {-1,-1} +}; + +keymap_t flagmaps[] = +{ + {NSShiftKeyMask, K_SHIFT}, + {NSControlKeyMask, K_CTRL}, + {NSAlternateKeyMask, K_ALT}, + {NSCommandKeyMask, K_ALT}, + + {-1,-1} +}; + +- (void)mouseDown:(NSEvent *)theEvent +{ + Key_Event (K_MOUSE1, true); +} +- (void)mouseUp:(NSEvent *)theEvent +{ + Key_Event (K_MOUSE1, false); +} +- (void)rightMouseDown:(NSEvent *)theEvent +{ + Key_Event (K_MOUSE2, true); +} +- (void)rightMouseUp:(NSEvent *)theEvent +{ + Key_Event (K_MOUSE2, false); +} + + +/* + =================== + keyboard methods + =================== + */ +- (void)keyDown:(NSEvent *)theEvent +{ + int ch; + keymap_t *km; + +// PSobscurecursor (); + +// check for non-ascii first + ch = [theEvent keyCode]; + for (km=keymaps;km->source!=-1;km++) + if (ch == km->source) + { + Key_Event (km->dest, true); + return; + } + + ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + if (ch>=256) + return; + + Key_Event (ch, true); +} + +- (void)flagsChanged:(NSEvent *)theEvent +{ + static int oldflags; + int newflags; + int delta; + keymap_t *km; + int i; + +// PSobscurecursor (); + newflags = [theEvent modifierFlags]; + delta = newflags ^ oldflags; + for (i=0 ; i<32 ; i++) + { + if ( !(delta & (1<source!=-1;km++) + if ( (1<source) + { + if (newflags & (1<dest, true); + else + Key_Event (km->dest, false); + } + + } + + oldflags = newflags; +} + + +- (void)keyUp:(NSEvent *)theEvent +{ + int ch; + keymap_t *km; + + // check for non-ascii first + ch = [theEvent keyCode]; + for (km=keymaps;km->source!=-1;km++) + if (ch == km->source) + { + Key_Event (km->dest, false); + return; + } + + ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + if (ch>=256) + return; + Key_Event (ch, false); +} + +@end + + diff --git a/rhapsody/rhapqw.txt b/rhapsody/rhapqw.txt new file mode 100644 index 000000000..980381513 --- /dev/null +++ b/rhapsody/rhapqw.txt @@ -0,0 +1,36 @@ +Put this QuakeWorld executable in a directory with the registered quake and QuakeWorld files. You should be able to launch it from the workspace or the command line. + +The sound is a bit lagged and will likely drift on longer games, because I am using the system timer to calculate sample position. This will need to be fixed at some point. + +There is no assembly language in yet, and it is still just using DPS to draw, so it isn't real fast yet. Run it on a ppro with a write combining video driver. + +If you ever lose your mouse cursor inapropriately due to the game messing up, if you can restart QuakeWorld, you can type "showmouse" to bump the visibility counter by one. + +You should eb able to connect to any QuakeWorld server, but you will have to do it with manual connect commands at the console, because we don't have either qspy or a browser plugin (yet) for openstep to find servers. + +Because the configuration ranges are different than windows, things like sensitivity and volume will need to be specified at the console. + +Some typical values (all of these should be saved automatically in the config file): + +vid_mode 1 +Sets 320*240 resolution. 320*200 (vid_mode 0) is somewhat faster, but looks scrunched at some desktop resolutions. + +vid_stretched 1 +Sets pixel doubling. Slower, of cource. + +snd_mixahead 0.2 +Because this isn't very fast yet, you probably want to increase the mixahead from 0.1 so the sound doesn't break up. + +volume 0.15 +The default 0.7 is VERY loud on my system. I don't know what it will be like on other systems. + +gamma 1.4 +Because openstep desktops are typically gamma corrected, the game will look washed out with default settings. Geater than 1.0 gets darker, less than gets brighter. + +sensitivity 20 +The normal slider range probably doesn't give enough speed for most people. + +in_mouse 0 +The mouse is normally grabbed for controlling the game. Setting this to 0 will give the mouse back to the desktop. + + diff --git a/rhapsody/snd_next.m b/rhapsody/snd_next.m new file mode 100644 index 000000000..8ee7ea025 --- /dev/null +++ b/rhapsody/snd_next.m @@ -0,0 +1,2151 @@ + +#import +#import + +#include "../client/client.h" + +double snd_basetime; +port_t devPort; + +extern port_t task_self_; +#define task_self() task_self_ + +//======================================================================== + +#ifndef _ntsoundNTSound +#define _ntsoundNTSound + +/* Module NTSound */ + +#include +#include +#include + +#ifndef mig_external +#define mig_external extern +#endif + +#include +#include +typedef short *sound_data_t; + +#define NTSOUNDNAME "NEXTIME_Sound" + +/* Routine ntsoundAcquire */ +mig_external kern_return_t ntsoundAcquire ( + port_t kern_serv_port, + port_t owner_port, + vm_offset_t *dmaAddress, + int *dmaSize, + int *success); + +/* Routine ntsoundRelease */ +mig_external kern_return_t ntsoundRelease ( + port_t kern_serv_port, + port_t owner_port); + +/* Routine ntsoundStart */ +mig_external kern_return_t ntsoundStart ( + port_t kern_serv_port, + port_t owner_port); + +/* Routine ntsoundStop */ +mig_external kern_return_t ntsoundStop ( + port_t kern_serv_port, + port_t owner_port); + +/* Routine ntsoundConfig */ +mig_external kern_return_t ntsoundConfig ( + port_t kern_serv_port, + port_t owner_port, + int channelCount, + int samplingRate, + int encoding, + int useInterrupts); + +/* Routine ntsoundBytesProcessed */ +mig_external kern_return_t ntsoundBytesProcessed ( + port_t kern_serv_port, + port_t owner_port, + int *byte_count); + +/* Routine ntsoundDMACount */ +mig_external kern_return_t ntsoundDMACount ( + port_t kern_serv_port, + port_t owner_port, + int *dma_count); + +/* Routine ntsoundInterruptCount */ +mig_external kern_return_t ntsoundInterruptCount ( + port_t kern_serv_port, + port_t owner_port, + int *irq_count); + +/* Routine ntsoundWrite */ +mig_external kern_return_t ntsoundWrite ( + port_t kern_serv_port, + port_t owner_port, + sound_data_t data, + unsigned int dataCnt, + int *actual_count); + +/* Routine ntsoundSetVolume */ +mig_external kern_return_t ntsoundSetVolume ( + port_t kern_serv_port, + port_t owner_port, + int value); + +/* Routine ntsoundWireRange */ +mig_external kern_return_t ntsoundWireRange ( + port_t device_port, + port_t token, + port_t task, + vm_offset_t addr, + vm_size_t size, + boolean_t wire); + +#endif _ntsoundNTSound + +//======================================================================== + +extern port_t name_server_port; + +#define NX_SoundDeviceParameterKeyBase 0 +#define NX_SoundDeviceParameterValueBase 200 +#define NX_SoundStreamParameterKeyBase 400 +#define NX_SoundStreamParameterValueBase 600 +#define NX_SoundParameterTagMax 799 + +typedef enum _NXSoundParameterTag { + NX_SoundDeviceBufferSize = NX_SoundDeviceParameterKeyBase, + NX_SoundDeviceBufferCount, + NX_SoundDeviceDetectPeaks, + NX_SoundDeviceRampUp, + NX_SoundDeviceRampDown, + NX_SoundDeviceInsertZeros, + NX_SoundDeviceDeemphasize, + NX_SoundDeviceMuteSpeaker, + NX_SoundDeviceMuteHeadphone, + NX_SoundDeviceMuteLineOut, + NX_SoundDeviceOutputLoudness, + NX_SoundDeviceOutputAttenuationStereo, + NX_SoundDeviceOutputAttenuationLeft, + NX_SoundDeviceOutputAttenuationRight, + NX_SoundDeviceAnalogInputSource, + NX_SoundDeviceMonitorAttenuation, + NX_SoundDeviceInputGainStereo, + NX_SoundDeviceInputGainLeft, + NX_SoundDeviceInputGainRight, + + NX_SoundDeviceAnalogInputSource_Microphone + = NX_SoundDeviceParameterValueBase, + NX_SoundDeviceAnalogInputSource_LineIn, + + NX_SoundStreamDataEncoding = NX_SoundStreamParameterKeyBase, + NX_SoundStreamSamplingRate, + NX_SoundStreamChannelCount, + NX_SoundStreamHighWaterMark, + NX_SoundStreamLowWaterMark, + NX_SoundStreamSource, + NX_SoundStreamSink, + NX_SoundStreamDetectPeaks, + NX_SoundStreamGainStereo, + NX_SoundStreamGainLeft, + NX_SoundStreamGainRight, + + NX_SoundStreamDataEncoding_Linear16 = NX_SoundStreamParameterValueBase, + NX_SoundStreamDataEncoding_Linear8, + NX_SoundStreamDataEncoding_Mulaw8, + NX_SoundStreamDataEncoding_Alaw8, + NX_SoundStreamDataEncoding_AES, + NX_SoundStreamSource_Analog, + NX_SoundStreamSource_AES, + NX_SoundStreamSink_Analog, + NX_SoundStreamSink_AES +} NXSoundParameterTag; + +//======================================================================== + +//#include "NTSound.h" +#include +#include +#include +#include +#if !defined(KERNEL) && !defined(MIG_NO_STRINGS) +#include +#endif +/* LINTLIBRARY */ + +extern port_t mig_get_reply_port(); +extern void mig_dealloc_reply_port(); + +#ifndef mig_internal +#define mig_internal static +#endif + +#ifndef TypeCheck +#define TypeCheck 1 +#endif + +#ifndef UseExternRCSId +#ifdef hc +#define UseExternRCSId 1 +#endif +#endif + +#ifndef UseStaticMsgType +#if !defined(hc) || defined(__STDC__) +#define UseStaticMsgType 1 +#endif +#endif + +#define msg_request_port msg_remote_port +#define msg_reply_port msg_local_port + + +/* Routine Acquire */ +mig_external kern_return_t ntsoundAcquire ( + port_t kern_serv_port, + port_t owner_port, + vm_offset_t *dmaAddress, + int *dmaSize, + int *success) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + msg_type_t dmaAddressType; + vm_offset_t dmaAddress; + msg_type_t dmaSizeType; + int dmaSize; + msg_type_t successType; + int success; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t dmaAddressCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t dmaSizeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t successCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1008; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1108) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 56) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->dmaAddressType != * (int *) &dmaAddressCheck) +#else UseStaticMsgType + if ((OutP->dmaAddressType.msg_type_inline != TRUE) || + (OutP->dmaAddressType.msg_type_longform != FALSE) || + (OutP->dmaAddressType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->dmaAddressType.msg_type_number != 1) || + (OutP->dmaAddressType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *dmaAddress /* dmaAddress */ = /* *dmaAddress */ OutP->dmaAddress; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->dmaSizeType != * (int *) &dmaSizeCheck) +#else UseStaticMsgType + if ((OutP->dmaSizeType.msg_type_inline != TRUE) || + (OutP->dmaSizeType.msg_type_longform != FALSE) || + (OutP->dmaSizeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->dmaSizeType.msg_type_number != 1) || + (OutP->dmaSizeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *dmaSize /* dmaSize */ = /* *dmaSize */ OutP->dmaSize; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->successType != * (int *) &successCheck) +#else UseStaticMsgType + if ((OutP->successType.msg_type_inline != TRUE) || + (OutP->successType.msg_type_longform != FALSE) || + (OutP->successType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->successType.msg_type_number != 1) || + (OutP->successType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *success /* success */ = /* *success */ OutP->success; + + return OutP->RetCode; +} + +/* Routine Release */ +mig_external kern_return_t ntsoundRelease ( + port_t kern_serv_port, + port_t owner_port) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1009; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1109) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 32) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + + return OutP->RetCode; +} + +/* Routine Start */ +mig_external kern_return_t ntsoundStart ( + port_t kern_serv_port, + port_t owner_port) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1010; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1110) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 32) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + + return OutP->RetCode; +} + +/* Routine Stop */ +mig_external kern_return_t ntsoundStop ( + port_t kern_serv_port, + port_t owner_port) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1011; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1111) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 32) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + + return OutP->RetCode; +} + +/* Routine Config */ +mig_external kern_return_t ntsoundConfig ( + port_t kern_serv_port, + port_t owner_port, + int channelCount, + int samplingRate, + int encoding, + int useInterrupts) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + msg_type_t channelCountType; + int channelCount; + msg_type_t samplingRateType; + int samplingRate; + msg_type_t encodingType; + int encoding; + msg_type_t useInterruptsType; + int useInterrupts; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 64; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t channelCountType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t samplingRateType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t encodingType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t useInterruptsType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + +#if UseStaticMsgType + InP->channelCountType = channelCountType; +#else UseStaticMsgType + InP->channelCountType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->channelCountType.msg_type_size = 32; + InP->channelCountType.msg_type_number = 1; + InP->channelCountType.msg_type_inline = TRUE; + InP->channelCountType.msg_type_longform = FALSE; + InP->channelCountType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->channelCount /* channelCount */ = /* channelCount */ channelCount; + +#if UseStaticMsgType + InP->samplingRateType = samplingRateType; +#else UseStaticMsgType + InP->samplingRateType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->samplingRateType.msg_type_size = 32; + InP->samplingRateType.msg_type_number = 1; + InP->samplingRateType.msg_type_inline = TRUE; + InP->samplingRateType.msg_type_longform = FALSE; + InP->samplingRateType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->samplingRate /* samplingRate */ = /* samplingRate */ samplingRate; + +#if UseStaticMsgType + InP->encodingType = encodingType; +#else UseStaticMsgType + InP->encodingType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->encodingType.msg_type_size = 32; + InP->encodingType.msg_type_number = 1; + InP->encodingType.msg_type_inline = TRUE; + InP->encodingType.msg_type_longform = FALSE; + InP->encodingType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->encoding /* encoding */ = /* encoding */ encoding; + +#if UseStaticMsgType + InP->useInterruptsType = useInterruptsType; +#else UseStaticMsgType + InP->useInterruptsType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->useInterruptsType.msg_type_size = 32; + InP->useInterruptsType.msg_type_number = 1; + InP->useInterruptsType.msg_type_inline = TRUE; + InP->useInterruptsType.msg_type_longform = FALSE; + InP->useInterruptsType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->useInterrupts /* useInterrupts */ = /* useInterrupts */ useInterrupts; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1012; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1112) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 32) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + + return OutP->RetCode; +} + +/* Routine BytesProcessed */ +mig_external kern_return_t ntsoundBytesProcessed ( + port_t kern_serv_port, + port_t owner_port, + int *byte_count) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + msg_type_t byte_countType; + int byte_count; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t byte_countCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1013; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1113) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 40) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->byte_countType != * (int *) &byte_countCheck) +#else UseStaticMsgType + if ((OutP->byte_countType.msg_type_inline != TRUE) || + (OutP->byte_countType.msg_type_longform != FALSE) || + (OutP->byte_countType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->byte_countType.msg_type_number != 1) || + (OutP->byte_countType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *byte_count /* byte_count */ = /* *byte_count */ OutP->byte_count; + + return OutP->RetCode; +} + +/* Routine DMACount */ +mig_external kern_return_t ntsoundDMACount ( + port_t kern_serv_port, + port_t owner_port, + int *dma_count) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + msg_type_t dma_countType; + int dma_count; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t dma_countCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1014; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1114) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 40) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->dma_countType != * (int *) &dma_countCheck) +#else UseStaticMsgType + if ((OutP->dma_countType.msg_type_inline != TRUE) || + (OutP->dma_countType.msg_type_longform != FALSE) || + (OutP->dma_countType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->dma_countType.msg_type_number != 1) || + (OutP->dma_countType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *dma_count /* dma_count */ = /* *dma_count */ OutP->dma_count; + + return OutP->RetCode; +} + +/* Routine InterruptCount */ +mig_external kern_return_t ntsoundInterruptCount ( + port_t kern_serv_port, + port_t owner_port, + int *irq_count) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + msg_type_t irq_countType; + int irq_count; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 32; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t irq_countCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1015; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1115) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 40) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->irq_countType != * (int *) &irq_countCheck) +#else UseStaticMsgType + if ((OutP->irq_countType.msg_type_inline != TRUE) || + (OutP->irq_countType.msg_type_longform != FALSE) || + (OutP->irq_countType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->irq_countType.msg_type_number != 1) || + (OutP->irq_countType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *irq_count /* irq_count */ = /* *irq_count */ OutP->irq_count; + + return OutP->RetCode; +} + +/* Routine Write */ +mig_external kern_return_t ntsoundWrite ( + port_t kern_serv_port, + port_t owner_port, + sound_data_t data, + unsigned int dataCnt, + int *actual_count) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + msg_type_long_t dataType; + short data[7000]; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + msg_type_t actual_countType; + int actual_count; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 44; + /* Maximum request size 14044 */ + unsigned int msg_size_delta; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_long_t dataType = { + { + /* msg_type_name = */ 0, + /* msg_type_size = */ 0, + /* msg_type_number = */ 0, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ TRUE, + /* msg_type_deallocate = */ FALSE, + }, + /* msg_type_long_name = */ MSG_TYPE_INTEGER_16, + /* msg_type_long_size = */ 16, + /* msg_type_long_number = */ 7000, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t actual_countCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + +#if UseStaticMsgType + InP->dataType = dataType; +#else UseStaticMsgType + InP->dataType.msg_type_long_name = MSG_TYPE_INTEGER_16; + InP->dataType.msg_type_long_size = 16; + InP->dataType.msg_type_header.msg_type_inline = TRUE; + InP->dataType.msg_type_header.msg_type_longform = TRUE; + InP->dataType.msg_type_header.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + if (dataCnt > 7000) + return MIG_ARRAY_TOO_LARGE; + bcopy((char *) data, (char *) InP->data, 2 * dataCnt); + + InP->dataType.msg_type_long_number /* dataCnt */ = /* dataType.msg_type_long_number */ dataCnt; + + msg_size_delta = (2 * dataCnt + 3) & ~3; + msg_size += msg_size_delta; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1016; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1116) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 40) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->actual_countType != * (int *) &actual_countCheck) +#else UseStaticMsgType + if ((OutP->actual_countType.msg_type_inline != TRUE) || + (OutP->actual_countType.msg_type_longform != FALSE) || + (OutP->actual_countType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->actual_countType.msg_type_number != 1) || + (OutP->actual_countType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + *actual_count /* actual_count */ = /* *actual_count */ OutP->actual_count; + + return OutP->RetCode; +} + +/* Routine SetVolume */ +mig_external kern_return_t ntsoundSetVolume ( + port_t kern_serv_port, + port_t owner_port, + int value) +{ + typedef struct { + msg_header_t Head; + msg_type_t owner_portType; + port_t owner_port; + msg_type_t valueType; + int value; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 40; + +#if UseStaticMsgType + static const msg_type_t owner_portType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t valueType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->owner_portType = owner_portType; +#else UseStaticMsgType + InP->owner_portType.msg_type_name = MSG_TYPE_PORT; + InP->owner_portType.msg_type_size = 32; + InP->owner_portType.msg_type_number = 1; + InP->owner_portType.msg_type_inline = TRUE; + InP->owner_portType.msg_type_longform = FALSE; + InP->owner_portType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->owner_port /* owner_port */ = /* owner_port */ owner_port; + +#if UseStaticMsgType + InP->valueType = valueType; +#else UseStaticMsgType + InP->valueType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->valueType.msg_type_size = 32; + InP->valueType.msg_type_number = 1; + InP->valueType.msg_type_inline = TRUE; + InP->valueType.msg_type_longform = FALSE; + InP->valueType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->value /* value */ = /* value */ value; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = kern_serv_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1017; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1117) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 32) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + + return OutP->RetCode; +} + +/* Routine WireRange */ +mig_external kern_return_t ntsoundWireRange ( + port_t device_port, + port_t token, + port_t task, + vm_offset_t addr, + vm_size_t size, + boolean_t wire) +{ + typedef struct { + msg_header_t Head; + msg_type_t tokenType; + port_t token; + msg_type_t taskType; + port_t task; + msg_type_t addrType; + vm_offset_t addr; + msg_type_t sizeType; + vm_size_t size; + msg_type_t wireType; + boolean_t wire; + } Request; + + typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; + } Reply; + + union { + Request In; + Reply Out; + } Mess; + + register Request *InP = &Mess.In; + register Reply *OutP = &Mess.Out; + + msg_return_t msg_result; + +#if TypeCheck + boolean_t msg_simple; +#endif TypeCheck + + unsigned int msg_size = 64; + +#if UseStaticMsgType + static const msg_type_t tokenType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t taskType = { + /* msg_type_name = */ MSG_TYPE_PORT, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t addrType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t sizeType = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t wireType = { + /* msg_type_name = */ MSG_TYPE_BOOLEAN, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0, + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + static const msg_type_t RetCodeCheck = { + /* msg_type_name = */ MSG_TYPE_INTEGER_32, + /* msg_type_size = */ 32, + /* msg_type_number = */ 1, + /* msg_type_inline = */ TRUE, + /* msg_type_longform = */ FALSE, + /* msg_type_deallocate = */ FALSE, + /* msg_type_unused = */ 0 + }; +#endif UseStaticMsgType + +#if UseStaticMsgType + InP->tokenType = tokenType; +#else UseStaticMsgType + InP->tokenType.msg_type_name = MSG_TYPE_PORT; + InP->tokenType.msg_type_size = 32; + InP->tokenType.msg_type_number = 1; + InP->tokenType.msg_type_inline = TRUE; + InP->tokenType.msg_type_longform = FALSE; + InP->tokenType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->token /* token */ = /* token */ token; + +#if UseStaticMsgType + InP->taskType = taskType; +#else UseStaticMsgType + InP->taskType.msg_type_name = MSG_TYPE_PORT; + InP->taskType.msg_type_size = 32; + InP->taskType.msg_type_number = 1; + InP->taskType.msg_type_inline = TRUE; + InP->taskType.msg_type_longform = FALSE; + InP->taskType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->task /* task */ = /* task */ task; + +#if UseStaticMsgType + InP->addrType = addrType; +#else UseStaticMsgType + InP->addrType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->addrType.msg_type_size = 32; + InP->addrType.msg_type_number = 1; + InP->addrType.msg_type_inline = TRUE; + InP->addrType.msg_type_longform = FALSE; + InP->addrType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->addr /* addr */ = /* addr */ addr; + +#if UseStaticMsgType + InP->sizeType = sizeType; +#else UseStaticMsgType + InP->sizeType.msg_type_name = MSG_TYPE_INTEGER_32; + InP->sizeType.msg_type_size = 32; + InP->sizeType.msg_type_number = 1; + InP->sizeType.msg_type_inline = TRUE; + InP->sizeType.msg_type_longform = FALSE; + InP->sizeType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->size /* size */ = /* size */ size; + +#if UseStaticMsgType + InP->wireType = wireType; +#else UseStaticMsgType + InP->wireType.msg_type_name = MSG_TYPE_BOOLEAN; + InP->wireType.msg_type_size = 32; + InP->wireType.msg_type_number = 1; + InP->wireType.msg_type_inline = TRUE; + InP->wireType.msg_type_longform = FALSE; + InP->wireType.msg_type_deallocate = FALSE; +#endif UseStaticMsgType + + InP->wire /* wire */ = /* wire */ wire; + + InP->Head.msg_simple = FALSE; + InP->Head.msg_size = msg_size; + InP->Head.msg_type = MSG_TYPE_NORMAL | MSG_TYPE_RPC; + InP->Head.msg_request_port = device_port; + InP->Head.msg_reply_port = mig_get_reply_port(); + InP->Head.msg_id = 1018; + + msg_result = msg_rpc(&InP->Head, MSG_OPTION_NONE, sizeof(Reply), 0, 0); + if (msg_result != RPC_SUCCESS) { + if (msg_result == RCV_INVALID_PORT) + mig_dealloc_reply_port(); + return msg_result; + } + +#if TypeCheck + msg_size = OutP->Head.msg_size; + msg_simple = OutP->Head.msg_simple; +#endif TypeCheck + + if (OutP->Head.msg_id != 1118) + return MIG_REPLY_MISMATCH; + +#if TypeCheck + if (((msg_size != 32) || (msg_simple != TRUE)) && + ((msg_size != sizeof(death_pill_t)) || + (msg_simple != TRUE) || + (OutP->RetCode == KERN_SUCCESS))) + return MIG_TYPE_ERROR; +#endif TypeCheck + +#if TypeCheck +#if UseStaticMsgType + if (* (int *) &OutP->RetCodeType != * (int *) &RetCodeCheck) +#else UseStaticMsgType + if ((OutP->RetCodeType.msg_type_inline != TRUE) || + (OutP->RetCodeType.msg_type_longform != FALSE) || + (OutP->RetCodeType.msg_type_name != MSG_TYPE_INTEGER_32) || + (OutP->RetCodeType.msg_type_number != 1) || + (OutP->RetCodeType.msg_type_size != 32)) +#endif UseStaticMsgType + return MIG_TYPE_ERROR; +#endif TypeCheck + + if (OutP->RetCode != KERN_SUCCESS) + return OutP->RetCode; + + return OutP->RetCode; +} + + +//======================================================================== + +/* +================== +SNDDMA_Init + +Try to find a sound device to mix for. +Returns false if nothing is found. +================== +*/ +qboolean SNDDMA_Init(void) +{ + int err; + int i; + byte *buf; + int bufsize; + int progress, oldprogress; + + shm = &sn; + shm->channels = 2; + shm->samplebits = 16; + shm->speed = 11025; + + err = netname_look_up(name_server_port,"", NTSOUNDNAME,&devPort); + if (err) + { + Com_Printf("SNDDMA_Init: Cannot access theater driver\n"); + return false; + } + + err = ntsoundAcquire(devPort,task_self(),(vm_offset_t *)&buf,&bufsize,&i); + if (err || !i) + { + Com_Printf("SNDDMA_Init: Sound driver is busy or messed up\n"); + return false; + } + + err = ntsoundConfig(devPort,task_self(),shm->channels,(int)shm->speed, + NX_SoundStreamDataEncoding_Linear16, 1); + if (err) + { + Com_Printf("SNDDMA_Init: ntsoundConfig error: %d\n",err); + return false; + } + else + Com_Printf("SNDDMA_Init: Configured for %d Hz, %d channels\n" + ,(int)shm->speed,shm->channels); + // printf ("buf: 0x%x\n", buf); + // printf ("bufsize: %d\n", bufsize); + + bzero(buf,bufsize); + +// ntsoundSetVolume(devPort,task_self(),5); + ntsoundStart(devPort,task_self()); + + shm->soundalive = true; + shm->splitbuffer = false; + shm->samples = bufsize/(shm->samplebits/8); + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = buf; + + // + // find a buffer crossing point for pos testing + // + + ntsoundBytesProcessed(devPort,task_self(),&oldprogress); + do + { + ntsoundBytesProcessed(devPort,task_self(),&progress); + } while (progress == oldprogress); + snd_basetime = Sys_DoubleTime() - progress/(11025*2); + + return true; +} + +/* +============== +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) +{ + int progress; + +#if 0 + ntsoundBytesProcessed(devPort,task_self(),&progress); +// ntsoundDMACount(devPort,task_self(),&progress); + +//printf ("(%i / %f) ", progress, (float)(Sys_DoubleTime ())); + progress += 2048; + progress >>= 1; +#else + + progress = (Sys_DoubleTime() - snd_basetime)*11025*2; + progress += 8192; + progress &= ~1; +#endif + + progress &= (shm->samples-1); + + return progress; +} + + +/* +============== +SNDDMA_Submit + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Submit(void) +{ +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown(void) +{ + ntsoundStop(devPort,task_self()); + ntsoundRelease(devPort,task_self()); +} + diff --git a/rhapsody/swimp_rhap.m b/rhapsody/swimp_rhap.m new file mode 100644 index 000000000..aeb77dc46 --- /dev/null +++ b/rhapsody/swimp_rhap.m @@ -0,0 +1,580 @@ +#import +#import +#import +#include "../ref_soft/r_local.h" + +@interface QuakeView : NSView +@end + +NSWindow *vid_window_i; +QuakeView *vid_view_i; +NSDirectScreen *vid_screen; +byte *vid_buffer; // real framebuffer +int vid_rowbytes; // framebuffer rowbytes + +unsigned *buffernative; // 24 bit off-screen back buffer for window +unsigned swimp_palette[256]; + +typedef enum { + rhap_shutdown, + rhap_windowed, + rhap_fullscreen +} rhapMode_t; + +rhapMode_t rhap_mode; + +/* +======================================================================= + +FULLSCREEN + +======================================================================= +*/ + +/* +** InitFullscreen +*/ +rserr_t InitFullscreen (int width, int height) +{ + NSDictionary *mode, *bestMode; + int modeWidth, bestWidth; + int modeHeight, bestHeight; + NSArray *modes; + int i; + NSString *string; + + + vid_screen = [[NSDirectScreen alloc] initWithScreen:[NSScreen mainScreen]]; + + // search for an apropriate mode + modes = [vid_screen availableDisplayModes]; + bestMode = NULL; + bestWidth = 99999; + bestHeight = 99999; + for (i=0 ; i<[modes count] ; i++) { + mode = [modes objectAtIndex: i]; + string = [mode objectForKey: @"NSDirectScreenPixelEncoding"]; + if ( ![string isEqualToString: @"PPPPPPPP"] ) + continue; // only look at paletted modes + modeWidth = [[mode objectForKey: @"NSDirectScreenWidth"] intValue]; + modeHeight = [[mode objectForKey: @"NSDirectScreenHeight"] intValue]; + if (modeWidth < width || modeHeight < height) + continue; + if (modeWidth < bestWidth) { + bestWidth = modeWidth; + bestHeight = modeHeight; + bestMode = mode; + } + } + + // if there wasn't any paletted mode of that res or greater, fail + if (!bestMode) + return rserr_invalid_fullscreen; + + ri.Con_Printf (PRINT_ALL, "SheildDisplay\n"); + [vid_screen shieldDisplay]; + + // hide the cursor in all fullscreen modes + [NSCursor hide]; + + vid_window_i = [vid_screen shieldingWindow]; + + ri.Con_Printf (PRINT_ALL, "switchToDisplayMode\n"); + [vid_screen switchToDisplayMode:bestMode]; +// [vid_screen fadeDisplayOutToColor:[NSColor blackColor]]; +// [vid_screen fadeDisplayInFromColor:[NSColor blackColor]]; + + vid_buffer = [vid_screen data]; + vid_rowbytes = [vid_screen bytesPerRow]; + + return rserr_ok; +} + +void ShutdownFullscreen (void) +{ + [vid_screen dealloc]; + [NSCursor unhide]; +} + +void SetPaletteFullscreen (const unsigned char *palette) { +#if 0 + byte *p; + int i; + NSDirectPalette *pal; + + pal = [NSDirectPalette init]; + for (i=0 ; i<256 ; i++) + [pal setRed: palette[0]*(1.0/255) + green: palette[1]*(1.0/255) + blue: palette[2]*(1.0/255) + atIndex: i]; + [vid_screen setPalette: pal]; + [pal release]; +#endif +} + + + +void BlitFullscreen (void) +{ + int i, j; + int w; + int *dest, *source; + + w = vid.width>>2; + + source = (int *)vid.buffer; // off-screen buffer + dest = (int *)vid_buffer; // directly on screen + for (j=0 ; j>2), dest += (vid_rowbytes>>2) ) { + for (i=0 ; ivalue,vid_ypos->value, width, height); + vid_window_i = [[NSWindow alloc] + initWithContentRect: content + styleMask: NSTitledWindowMask + backing: NSBackingStoreRetained + defer: NO + ]; + +// [vid_window_i addToEventMask: NS_FLAGSCHANGEDMASK]; + [vid_window_i setTitle: @"Quake2"]; + + buffernative = malloc(width * height * 4); + + return retval; +} + +void ShutdownWindowed (void) +{ + if (vid_window_i) + { + [vid_window_i release]; + vid_window_i = NULL; + } + if (buffernative) + { + free (buffernative); + buffernative = NULL; + } +} + +void SetPaletteWindowed (const unsigned char *palette) { + byte *p; + int i; + + p = (byte *)swimp_palette; + for (i=0 ; i<256 ; i++, p+=4, palette+=4) + { + p[0] = palette[0]; + p[1] = palette[1]; + p[2] = palette[2]; + p[3] = 0xff; + } +} + + +void BlitWindowed (void) +{ + int i, c; + int bps, spp, bpp, bpr; + unsigned char *planes[5]; + NSRect bounds; + + if (!vid_view_i) + return; + + // translate to 24 bit color + c = vid.width*vid.height; + for (i=0 ; isource!=-1;km++) + if (ch == km->source) + { + Key_Event (km->dest, true, 0); + return; + } + + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + if (ch>=256) + return; + + Key_Event (ch, true, 0); +} + +- (void)flagsChanged:(NSEvent *)theEvent +{ + static int oldflags; + int newflags; + int delta; + keymap_t *km; + int i; + +// PSobscurecursor (); + newflags = [theEvent modifierFlags]; + delta = newflags ^ oldflags; + for (i=0 ; i<32 ; i++) + { + if ( !(delta & (1<source!=-1;km++) + if ( (1<source) + { + if (newflags & (1<dest, true, 0); + else + Key_Event (km->dest, false, 0); + } + + } + + oldflags = newflags; +} + + +- (void)keyUp:(NSEvent *)theEvent +{ + int ch; + keymap_t *km; + + ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + + // check for non-ascii first + for (km=keymaps;km->source!=-1;km++) + if (ch == km->source) + { + Key_Event (km->dest, false, 0); + return; + } + + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + if (ch>=256) + return; + Key_Event (ch, false, 0); +} + +@end + + diff --git a/rhapsody/sys_rhap.m b/rhapsody/sys_rhap.m new file mode 100644 index 000000000..ad0507d95 --- /dev/null +++ b/rhapsody/sys_rhap.m @@ -0,0 +1,338 @@ +#include +#import +#include "../qcommon/qcommon.h" + +int curtime; +int sys_frame_time; + +void Sys_UnloadGame (void) +{ +} + +void *GetGameAPI (void *import); + +void *Sys_GetGameAPI (void *parms) +{ + // we are hard-linked in, so no need to load anything + return GetGameAPI (parms); +} + +void Sys_CopyProtect (void) +{ +} + +char *Sys_GetClipboardData( void ) +{ + return NULL; +} + + +//=========================================================================== + +int hunkcount; + +byte *membase; +int hunkmaxsize; +int cursize; + +//#define VIRTUAL_ALLOC + +void *Hunk_Begin (int maxsize) +{ + // reserve a huge chunk of memory, but don't commit any yet + cursize = 0; + hunkmaxsize = maxsize; +#ifdef VIRTUAL_ALLOC + membase = VirtualAlloc (NULL, maxsize, MEM_RESERVE, PAGE_NOACCESS); +#else + membase = malloc (maxsize); + memset (membase, 0, maxsize); +#endif + if (!membase) + Sys_Error ("VirtualAlloc reserve failed"); + return (void *)membase; +} + +void *Hunk_Alloc (int size) +{ + void *buf; + + // round to cacheline + size = (size+31)&~31; + +#ifdef VIRTUAL_ALLOC + // commit pages as needed +// buf = VirtualAlloc (membase+cursize, size, MEM_COMMIT, PAGE_READWRITE); + buf = VirtualAlloc (membase, cursize+size, MEM_COMMIT, PAGE_READWRITE); + if (!buf) + { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buf, 0, NULL); + Sys_Error ("VirtualAlloc commit failed.\n%s", buf); + } +#endif + cursize += size; + if (cursize > hunkmaxsize) + Sys_Error ("Hunk_Alloc overflow"); + + return (void *)(membase+cursize-size); +} + +int Hunk_End (void) +{ + + // free the remaining unused virtual memory +#if 0 + void *buf; + + // write protect it + buf = VirtualAlloc (membase, cursize, MEM_COMMIT, PAGE_READONLY); + if (!buf) + Sys_Error ("VirtualAlloc commit failed"); +#endif + + hunkcount++; +//Com_Printf ("hunkcount: %i\n", hunkcount); + return cursize; +} + +void Hunk_Free (void *base) +{ + if ( base ) +#ifdef VIRTUAL_ALLOC + VirtualFree (base, 0, MEM_RELEASE); +#else + free (base); +#endif + + hunkcount--; +} + + +//=========================================================================== + + +void Sys_Mkdir (char *path) +{ + if (mkdir (path, 0777) != -1) + return; + if (errno != EEXIST) + Com_Error (ERR_FATAL, "mkdir %s: %s",path, strerror(errno)); +} + +char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave) +{ + return NULL; +} + +char *Sys_FindNext (unsigned musthave, unsigned canthave) +{ + return NULL; +} + +void Sys_FindClose (void) +{ +} + +/* +================ +Sys_Milliseconds +================ +*/ +int Sys_Milliseconds (void) +{ + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000; + } + + curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000; + + return curtime; +} + +/* +================ +Sys_Error +================ +*/ +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); + printf ("Fatal error: %s\n",string); + + if (!NSApp) + { // appkit isn't running, so don't try to pop up a panel + exit (1); + } + NSRunAlertPanel (@"Fatal error",[NSString stringWithCString: string] + ,@"exit",NULL,NULL); + [NSApp terminate: NULL]; + exit(1); +} + +/* +================ +Sys_Printf +================ +*/ +void Sys_ConsoleOutput (char *text) +{ + char *t_p; + int l, r; + + 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; + } + } +} + +/* +================ +Sys_Quit +================ +*/ +void Sys_Quit (void) +{ +// change stdin to blocking + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + + if (!NSApp) + exit (0); // appkit isn't running + + [NSApp terminate:nil]; +} + + +/* +================ +Sys_Init +================ +*/ +void Sys_Init(void) +{ + moncontrol(0); // turn off profiling except during real Quake work + +// change stdin to non blocking + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); +} + + +extern NSWindow *vid_window_i; + +void Sys_AppActivate (void) +{ + [vid_window_i makeKeyAndOrderFront: nil]; +} + + +/* +================ +Sys_SendKeyEvents + +service any pending appkit events +================ +*/ +void Sys_SendKeyEvents (void) +{ + NSEvent *event; + NSDate *date; + + date = [NSDate date]; + do + { + event = [NSApp + nextEventMatchingMask: 0xffffffff + untilDate: date + inMode: @"NSDefaultRunLoopMode" + dequeue: YES]; + if (event) + [NSApp sendEvent: event]; + } while (event); + + // grab frame time + sys_frame_time = Sys_Milliseconds(); +} + + +/* +================ +Sys_ConsoleInput + +Checks for a complete line of text typed in at the console, then forwards +it to the host command processor +================ +*/ +char *Sys_ConsoleInput (void) +{ + static char text[256]; + int len; + + len = read (0, text, sizeof(text)); + if (len < 1) + return NULL; + text[len-1] = 0; // rip off the /n and terminate + + return text; +} + + +/* +============= +main +============= +*/ +void main (int argc, char **argv) +{ + int frame; + NSAutoreleasePool *pool; + int oldtime, t; + + pool = [[NSAutoreleasePool alloc] init]; + + Qcommon_Init (argc, argv); + + [pool release]; + + oldtime = Sys_Milliseconds (); + while (1) + { + pool =[[NSAutoreleasePool alloc] init]; + + if (++frame > 10) + moncontrol(1);// profile only while we do each Quake frame + + t = Sys_Milliseconds (); + Qcommon_Frame (t - oldtime); + oldtime = t; + moncontrol(0); + + [pool release]; + } +} + diff --git a/rhapsody/vid_next.m b/rhapsody/vid_next.m new file mode 100644 index 000000000..f840f58c1 --- /dev/null +++ b/rhapsody/vid_next.m @@ -0,0 +1,1789 @@ +// vid_next.m -- NEXTSTEP video driver + +#define INTERCEPTOR + +#import +#import +#import "intercep.h" +#include "quakedef.h" +#include "d_local.h" + +int BASEWIDTH = 320; +int BASEHEIGHT = 200; + +void SetupBitmap (void); +void SetupFramebuffer (void); +void UpdateBitmap (void); +void UpdateFramebuffer (vrect_t *vrect); +void SetVideoEncoding (char *encoding); +void Update8_1 (pixel_t *src, byte *dest, int width, + int height, int destrowbytes); +void Update16_1 (pixel_t *src, unsigned short *dest, int width, + int height, int destrowbytes); +void Update32_1 (pixel_t *src, unsigned *dest, int width, + int height, int destrowbytes); + + +@interface QuakeView : View +@end + +@interface FrameWindow:Window +@end + +unsigned short d_8to16table[256]; // not used in 8 bpp mode +unsigned d_8to24table[256]; // not used in 8 bpp mode + + +/* +========================================================================== + + API FUNCTIONS + +========================================================================== +*/ + +typedef enum {disp_bitmap, disp_framebuffer} display_t; + +pixel_t *vid_buffer; +pixel_t *buffernative; +unsigned pcolormap[4][256]; // map from quake pixels to native pixels +unsigned pixbytesnative; +unsigned rowbytesnative; +int dither; + +int drawdirect = 0; + +int d_con_indirect = 0; + +display_t vid_display; + +byte vid_palette[768]; // saved for restarting vid system + +id vid_window_i; +id vid_view_i; +#ifdef INTERCEPTOR +NXDirectBitmap *vid_dbitmap_i; +NXFramebuffer *vid_framebuffer_i; +#endif + +NXRect screenBounds; // only valid in framebuffer mode + +int vid_scale; + +char *vid_encodingstring; + +int vid_fullscreen; +int vid_screen; + +int vid_high_hunk_mark; + +typedef enum +{ + enc_24_rgba, + enc_24_0rgb, + enc_24_rgb0, + enc_12_rgba, + enc_12_rgb0, + enc_15_0rgb, + enc_564, + enc_8_gray, + enc_8_rgb +} vid_encoding_t; + +typedef struct +{ + char *string; + int pixelbytes; + void (*colormap) (void); + vid_encoding_t name; +} vidtype_t; + +vid_encoding_t vid_encoding; + +void Table8 (void); +void Table15 (void); +void Table12 (void); +void Table12Swap (void); +void Table24 (void); +void Table24Swap (void); + +vidtype_t vid_encodingtable[]= +{ +{"RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA",4, Table24Swap, enc_24_rgba}, +{"--------RRRRRRRRGGGGGGGGBBBBBBBB",4, Table24, enc_24_0rgb}, +{"RRRRRRRRGGGGGGGGBBBBBBBB--------",4, Table24Swap, enc_24_rgb0}, +{"RRRRGGGGBBBBAAAA",2, Table12Swap, enc_12_rgba}, +{"RRRRGGGGBBBB----",2, Table12, enc_12_rgb0}, +{"-RRRRRGGGGGBBBBB",2, Table15, enc_15_0rgb}, +{"WWWWWWWW",1, Table8, enc_8_gray}, +{"PPPPPPPP",1, Table8, enc_8_rgb}, +{NULL,0, 0, 0} +}; + +vidtype_t *vid_type; +void InitNS8Bit (void); + +/* +================ +D_BeginDirectRect +================ +*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Nextstep +} + + +/* +================ +D_EndDirectRect +================ +*/ +void D_EndDirectRect (int x, int y, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Nextstep +} + + +/* +============== +VID_Restart + +internal call only +=============== +*/ +void VID_Restart (display_t mode, int scale) +{ + vid_display = mode; + vid_scale = scale; + + [NXApp activateSelf:YES]; + + if (vid_display == disp_framebuffer) + SetupFramebuffer (); + else + SetupBitmap (); + + vid.recalc_refdef = 1; +} + + +/* +================= +VID_Scale_f + +Keybinding command +================= +*/ +void VID_Scale_f (void) +{ + int scale; + + if (Cmd_Argc () != 2) + return; + + scale = atoi (Cmd_Argv(1)); + if (scale != 1 && scale != 2) + { + Con_Printf ("scale must be 1 or 2\n"); + return; + } + VID_Shutdown (); + VID_Restart (vid_display, scale); +} + +/* +================= +VID_Mode_f + +Keybinding command +================= +*/ +void VID_Mode_f (void) +{ + int mode; + + if (Cmd_Argc () != 2) + return; + + mode = atoi (Cmd_Argv(1)); + + VID_Shutdown (); + if (mode == 0) + { + drawdirect = 0; + VID_Restart (disp_bitmap, vid_scale); + } + else if (mode == 1) + { + drawdirect = 0; + VID_Restart (disp_framebuffer, vid_scale); + } + else + { + drawdirect = 1; + VID_Restart (disp_framebuffer, vid_scale); + } +} + +/* +================= +VID_Size_f + +Keybinding command +================= +*/ +void VID_Size_f (void) +{ + if (Cmd_Argc () != 3) + return; + + VID_Shutdown (); + + BASEWIDTH = atoi (Cmd_Argv(1)); + BASEHEIGHT = atoi (Cmd_Argv(2)); + + VID_Restart (vid_display, vid_scale); +} + +/* +================ +VID_Init +================ +*/ +void VID_Init (unsigned char *palette) +{ + InitNS8Bit (); // fixed palette lookups + + Q_memcpy (vid_palette, palette, sizeof(vid_palette)); + + if (COM_CheckParm ("-bitmap")) + vid_display = disp_bitmap; + else + vid_display = disp_framebuffer; + + if (COM_CheckParm ("-screen2")) + vid_screen = 1; + else + vid_screen = 0; + + if (COM_CheckParm ("-direct")) + drawdirect = 1; + + Cmd_AddCommand ("vid_scale", VID_Scale_f); + Cmd_AddCommand ("vid_mode", VID_Mode_f); + Cmd_AddCommand ("vid_size", VID_Size_f); + + vid.width = BASEWIDTH; + vid.height = BASEHEIGHT; + vid.aspect = 1.0; + vid.numpages = 1; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + + if (COM_CheckParm ("-scale2")) + vid_scale = 2; + else + vid_scale = 1; + + [Application new]; + + VID_Restart (vid_display, vid_scale); +} + + +/* +================ +VID_Shutdown +================ +*/ +void VID_Shutdown (void) +{ +#ifdef INTERCEPTOR + if (vid_dbitmap_i) + { + [vid_dbitmap_i free]; + vid_dbitmap_i = 0; + } + if (vid_framebuffer_i) + { + [vid_framebuffer_i free]; + vid_framebuffer_i = 0; + } +#endif + [vid_window_i close]; + [vid_window_i free]; +} + + +/* +================ +VID_Update +================ +*/ +void VID_Update (vrect_t *rects) +{ + if (drawdirect) + return; + + while (rects) + { + UpdateFramebuffer (rects); + rects = rects->pnext; + } + + if (vid_display == disp_bitmap) + UpdateBitmap (); +} + + +/* +================ +VID_SetPalette +================ +*/ +void VID_SetPalette (unsigned char *palette) +{ + Q_memcpy (vid_palette, palette, sizeof(vid_palette)); + vid_type->colormap (); +} + + +/* +================ +VID_ShiftPalette +================ +*/ +void VID_ShiftPalette (unsigned char *palette) +{ + + VID_SetPalette (palette); +} + + +/* +========================================================================== + + NS STUFF + +========================================================================== +*/ + + +/* +================= +SetVideoEncoding +================= +*/ +void SetVideoEncoding (char *encoding) +{ + vidtype_t *type; + + Sys_Printf ("SetVideoEncoding: %s\n",encoding); + vid_encodingstring = encoding; + + for (type = vid_encodingtable ; type->string ; type++) + { + if (strcmp(type->string, encoding) == 0) + { + pixbytesnative = type->pixelbytes; + vid_encoding = type->name; + type->colormap (); + vid_type = type; + return; + } + } + + Sys_Error ("Unsupported video encoding: %s\n",encoding); +} + +/* +================= +AllocBuffers +================= +*/ +void AllocBuffers (qboolean withnative) +{ + int surfcachesize; + void *surfcache; + int pixels; + int pixbytes; + int vid_buffersize; + + if (vid_buffer) + { + D_FlushCaches (); + Hunk_FreeToHighMark (vid_high_hunk_mark); + vid_high_hunk_mark = 0; + vid_buffer = NULL; + } + + pixels = vid.width * vid.height; + + pixbytes = 1 +sizeof (*d_pzbuffer); + if (withnative) + pixbytes += pixbytesnative; + + surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height); + vid_buffersize = pixels * pixbytes + surfcachesize; + + vid_high_hunk_mark = Hunk_HighMark (); + vid_buffer = Hunk_HighAllocName (vid_buffersize, "video"); + if (!vid_buffer) + Sys_Error ("Couldn't alloc video buffers"); + + vid.buffer = vid_buffer; + + d_pzbuffer = (unsigned short *)((byte *)vid_buffer + pixels); + surfcache = (byte *)d_pzbuffer + pixels * sizeof (*d_pzbuffer); + if (withnative) + buffernative = (byte *)surfcache + surfcachesize; + + D_InitCaches (surfcache, surfcachesize); +} + +/* +================= +SetupFramebuffer +================= +*/ +void SetupFramebuffer (void) +{ +#ifdef INTERCEPTOR + int windowNum; + NXRect cont; + NXScreen const *screens; + int screencount; + +// +// get the screen list +// + [NXApp getScreens:&screens count:&screencount]; + +// +// create vid_framebuffer_i +// + vid_framebuffer_i = [[NXFramebuffer alloc] + initFromScreen:screens[vid_screen].screenNumber andMapIfPossible:YES]; + [vid_framebuffer_i screenBounds:&screenBounds]; + + SetVideoEncoding ([vid_framebuffer_i pixelEncoding]); + + buffernative = [vid_framebuffer_i data]; + rowbytesnative = [vid_framebuffer_i bytesPerRow]; + +// +// create window +// + if (vid_fullscreen) + { + vid.height = screenBounds.size.height / vid_scale; + vid.width = screenBounds.size.width / vid_scale; + cont.origin.x = 0; + cont.origin.y = 0; + cont.size.width = screenBounds.size.width; + cont.size.height = screenBounds.size.height; + } + else + { + buffernative = (unsigned char *)buffernative + 8 * rowbytesnative + + 8 * pixbytesnative; + vid.width = BASEWIDTH; + vid.height = BASEHEIGHT; + cont.origin.x = 8; + cont.origin.y = screenBounds.size.height - (vid.height*vid_scale) - 8; + cont.size.width = vid.width * vid_scale; + cont.size.height = vid.height * vid_scale; + } + + vid_window_i = [[FrameWindow alloc] + initContent: &cont + style: NX_PLAINSTYLE + backing: NX_NONRETAINED + buttonMask: 0 + defer: NO + screen: screens+vid_screen]; + windowNum = [vid_window_i windowNum]; + PSsetwindowlevel(40, windowNum); + PSsetautofill(YES, windowNum); + PSgsave(); + PSwindowdeviceround(windowNum); + PSsetgray(NX_BLACK); + PSsetexposurecolor(); + PSgrestore(); + +// +// create view +// + vid_view_i = [[QuakeView alloc] initFrame: &screenBounds]; + [[vid_window_i setContentView: vid_view_i] free]; + [vid_window_i makeFirstResponder: vid_view_i]; + [vid_window_i setDelegate: vid_view_i]; + [vid_window_i display]; + [vid_window_i makeKeyAndOrderFront: nil]; + NXPing (); + + AllocBuffers (false); // no native buffer + + if (drawdirect) + { // the direct drawing mode to NeXT colorspace + vid.buffer = buffernative; + vid.rowbytes = rowbytesnative; + } + else + vid.rowbytes = vid.width; + + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; +#endif +} + +/* +================= +SetupBitmap +================= +*/ +void SetupBitmap (void) +{ + int depth; + NXRect content; + +// +// open a window +// + NXSetRect (&content, 8,136, vid.width*vid_scale, vid.height*vid_scale); + vid_window_i = [[Window alloc] + initContent: &content + style: NX_RESIZEBARSTYLE + backing: NX_RETAINED + buttonMask: 0 + defer: NO + ]; + [vid_window_i display]; + [vid_window_i makeKeyAndOrderFront: nil]; + + NXPing (); + + content.origin.x = content.origin.y = 0; + vid_view_i = [[QuakeView alloc] initFrame: &content]; + [[vid_window_i setContentView: vid_view_i] free]; + [vid_window_i makeFirstResponder: vid_view_i]; + [vid_window_i setDelegate: vid_view_i]; + + [vid_window_i addToEventMask: NX_FLAGSCHANGEDMASK]; + +// +// find video info +// + depth = [Window defaultDepthLimit]; + switch (depth) { + case NX_EightBitGrayDepth: + SetVideoEncoding ("WWWWWWWW"); + break; + case NX_TwelveBitRGBDepth: + SetVideoEncoding ("RRRRGGGGBBBBAAAA"); + break; + default: + case NX_TwentyFourBitRGBDepth: + SetVideoEncoding ("RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"); + break; +// default: // 8 bit color shows up as an unknown... + Sys_Error ("Unsupported window depth"); + } + + [vid_window_i setTitle: "Bitmap Quake Console"]; + +// +// allocate memory for the back and translation buffers +// + vid.rowbytes = vid.width; + rowbytesnative = vid.width * pixbytesnative; + + AllocBuffers (true); + + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; +} + + +/* +================= +UpdateFramebuffer +================= +*/ +void UpdateFramebuffer (vrect_t *vrect) +{ + byte *psourcebase; + byte *pdestbase; + int scale; + + psourcebase = vid.buffer + vrect->x + vrect->y * vid.rowbytes; + + if (vid_display == disp_bitmap) + scale = 1; // let NS do the scaling + else + scale = vid_scale; + + pdestbase = buffernative + scale * + (vrect->x * pixbytesnative + vrect->y * rowbytesnative); + +// +// translate from ideal to native (except 8 bpp direct) and copy to screen +// + + if (pixbytesnative == 1) + Update8_1 (psourcebase, pdestbase, vrect->width, vrect->height, + rowbytesnative); + else if (pixbytesnative == 2) + Update16_1 (psourcebase, (unsigned short *)pdestbase, vrect->width, vrect->height, + rowbytesnative); + else + Update32_1 (psourcebase, (unsigned *)pdestbase, vrect->width, vrect->height, + rowbytesnative); +} + + +/* +================= +UpdateBitmap +================= +*/ +void UpdateBitmap (void) +{ + unsigned char *planes[5]; + NXRect bounds; + int bpp, spp, bps, bpr, colorspace; + +// +// flush the screen with an image call +// + if (pixbytesnative == 1) + { + bps = 8; + spp = 1; + bpp = 8; + bpr = vid.width; + colorspace = NX_OneIsWhiteColorSpace; + planes[0] = vid.buffer; + } + else if (pixbytesnative == 2) + { + bps = 4; + spp = 3; + bpp = 16; + bpr = vid.width * 2; + colorspace = NX_RGBColorSpace; + planes[0] = buffernative; + } + else + { + bps = 8; + spp = 3; + bpp = 32; + bpr = vid.width * 4; + colorspace = NX_RGBColorSpace; + planes[0] = buffernative; + } + + [vid_view_i getBounds: &bounds]; + [vid_view_i lockFocus]; + + NXDrawBitmap( + &bounds, + vid.width, + vid.height, + bps, + spp, + bpp, + bpr, + NO, + NO, + colorspace, + planes + ); + + [vid_view_i unlockFocus]; + NXPing (); +} + + + +/* +========================================================================== + + TRANSLATION TABLE BUILDING + +========================================================================== +*/ + +int redramp[] = {0, 19, 59, 113, 178, 255, 300}; +int greenramp[] = {0, 11, 34, 66, 104, 149, 199, 255, 300}; +int blueramp[] = {0, 28, 84, 161, 255, 300}; +int greyramp[] = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, + 221, 238, 255, 300}; + +byte greytable[256]; +byte redtable[256]; +byte greentable[256]; +byte bluetable[256]; + +void FillTable (byte *table, int *ramp, int base) +{ + int i, j, o; + + o = 0; + for (i=0 ; i<16 && o < 256; i++) + { + j = ramp[i]; + for ( ; o<=j ; o++) + table[o] = base + i; + } +} + +void InitNS8Bit (void) +{ + FillTable (greytable, greyramp, 240); + FillTable (redtable, redramp, 0); + FillTable (greentable, greenramp, 0); + FillTable (bluetable, blueramp, 0); +} + + +byte ns8trans[256] = // FIXME: dynamically calc this so palettes work +{ +0,241,242,243,244,244,245,246,247,248,249,250,251,252,253,254, +45,241,241,242,91,91,91,96,96,136,136,136,141,141,141,141, +241,46,242,243,243,97,97,97,245,246,143,143,143,143,148,148, +0,5,45,45,50,50,90,90,95,95,95,95,95,140,140,141, +0,40,40,40,40,80,80,80,80,80,120,120,120,120,120,120, +45,50,50,90,90,95,95,135,135,135,136,141,141,181,181,181, +45,90,91,91,131,131,136,136,136,176,181,181,186,226,231,236, +45,45,91,91,96,96,136,136,137,142,182,182,187,188,188,233, +188,249,248,247,246,137,137,137,244,243,243,91,242,241,241,45, +183,183,183,247,137,137,137,137,137,244,91,91,91,241,241,45, +252,251,188,188,248,248,142,142,142,244,244,243,91,242,241,45, +247,247,246,246,245,245,244,244,243,243,242,242,51,241,241,5, +236,231,231,191,186,185,185,140,140,135,135,95,90,90,45,45, +4,49,49,53,53,93,93,93,93,92,92,92,243,242,46,241, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, +239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,182 +}; + +/* +=================== +Table8 +=================== +*/ +void Table8 (void) +{ + byte *pal; + int r,g,b,v; + int i; + byte *table; + + pal = vid_palette; + table = (byte *)pcolormap[0]; + + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + +// use the grey ramp if all indexes are close + + if (r-g < 16 && r-g > -16 && r-b < 16 && r-b > -16) + { + v = (r+g+b)/3; + *table++ = greytable[v]; + continue; + } + + r = redtable[r]; + g = greentable[g]; + b = bluetable[b]; + +// otherwise use the color cube + *table++ = r*(8*5) + g*5 + b; + } +} + +/* +=================== +Table24 +=================== +*/ +void Table24 (void) +{ + byte *pal; + int r,g,b,v; + int i; + unsigned *table; + + +// +// 8 8 8 encoding +// + pal = vid_palette; + table = (unsigned *)pcolormap[0]; + + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + + v = (r<<16) + (g<<8) + b; + *table++ = v; + } +} + +/* +=================== +Table24Swap +=================== +*/ +void Table24Swap (void) +{ + byte *pal; + int r,g,b,v; + int i; + unsigned *table; + +// +// 8 8 8 encoding +// + pal = vid_palette; + table = (unsigned *)pcolormap[0]; + + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + + v = (r<<24) + (g<<16) + (b<<8) /*+ 255*/; + v = NXSwapBigLongToHost (v); + *table++ = v; + } +} + + +/* +=================== +Table15 +=================== +*/ +void Table15 (void) +{ + byte *pal; + int r,g,b,v; + int i, k; + unsigned char *palette; + unsigned short *table; + int dadj; + int ditheradjust[4] = {(1 << 9) * 3 / 8, + (1 << 9) * 5 / 8, + (1 << 9) * 7 / 8, + (1 << 9) * 1 / 8}; + + palette = vid_palette; + table = (unsigned short *)pcolormap; + +// +// 5 5 5 encoding +// + for (k=0 ; k<4 ; k++) + { + dadj = ditheradjust[k]; + + pal = vid_palette; + + for (i=0 ; i<256 ; i++) + { + // shift 6 bits to get back to 0-255, & 3 more for 5 bit color + // FIXME: scale intensity levels properly + r = (pal[0] + dadj) >> 3; + g = (pal[1] + dadj) >> 3; + b = (pal[2] + dadj) >> 3; + pal += 3; + + v = (r<<10) + (g<<5) + b; + + *table++ = v; + } + } +} + +/* +=================== +Table12 +=================== +*/ +void Table12 (void) +{ + byte *pal; + int r,g,b,v; + int i, k; + unsigned short *table; + int dadj; + static int ditheradjust[4] = {(1 << 9) * 3 / 8, + (1 << 9) * 5 / 8, + (1 << 9) * 7 / 8, + (1 << 9) * 1 / 8}; + + table = (unsigned short *)pcolormap; + +// +// 4 4 4 encoding +// + for (k=0 ; k<4 ; k++) + { + dadj = ditheradjust[k]; + + pal = vid_palette; + + for (i=0 ; i<256 ; i++) + { + // shift 5 bits to get back to 0-255, & 4 more for 4 bit color + // FIXME: scale intensity levels properly + r = (pal[0] + dadj) >> 4; + g = (pal[1] + dadj) >> 4; + b = (pal[2] + dadj) >> 4; + pal += 3; + + v = ((r<<12) + (g<<8) + (b<<4) /*+ 15*/); + + *table++ = v; + } + } +} + +/* +=================== +Table12Swap +=================== +*/ +void Table12Swap (void) +{ + byte *pal; + int r,g,b,v; + int i, k; + unsigned short *table; + int dadj; + static int ditheradjust[4] = {(1 << 9) * 3 / 8, + (1 << 9) * 5 / 8, + (1 << 9) * 7 / 8, + (1 << 9) * 1 / 8}; + + table = (unsigned short *)pcolormap; + +// +// 4 4 4 encoding +// + for (k=0 ; k<4 ; k++) + { + dadj = ditheradjust[k]; + + pal = vid_palette; + + for (i=0 ; i<256 ; i++) + { + // shift 5 bits to get back to 0-255, & 4 more for 4 bit color + // FIXME: scale intensity levels properly + r = (pal[0] + dadj) >> 4; + g = (pal[1] + dadj) >> 4; + b = (pal[2] + dadj) >> 4; + pal += 3; + + v = ((r<<12) + (g<<8) + (b<<4) /*+ 15*/); + v = NXSwapBigShortToHost (v); + + *table++ = v; + } + } +} + + +/* +========================================================================== + + GENERIC IMAGING FUNCTIONS + +========================================================================== +*/ + +/* +=================== +Update8_1 +=================== +*/ +void Update8_1 (pixel_t *src, byte *dest, int width, int height, + int destrowbytes) +{ + int x,y; + unsigned rowdelta, srcdelta; + unsigned xcount; + byte *pdest; + int xwidth; + + pdest = dest; + + xcount = width >> 3; + srcdelta = vid.width - width; + + xwidth = width - (xcount << 3); + if (xwidth) + Sys_Error ("Width not multiple of 8"); + + if ((vid_display == disp_framebuffer) && (vid_scale == 2)) + { + int nextrow = destrowbytes; + + rowdelta = destrowbytes - (width << 1) + destrowbytes; + + if (dither) + { + unsigned short *psrc; + + psrc = (unsigned short *)src; + + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + unsigned temp; + + temp = psrc[0]; + pdest[0] = ((byte *)pcolormap[0])[temp]; + pdest[1] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 1] = ((byte *)pcolormap[3])[temp]; + temp = psrc[1]; + pdest[2] = ((byte *)pcolormap[0])[temp]; + pdest[3] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 2] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 3] = ((byte *)pcolormap[3])[temp]; + temp = psrc[2]; + pdest[4] = ((byte *)pcolormap[0])[temp]; + pdest[5] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 4] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 5] = ((byte *)pcolormap[3])[temp]; + temp = psrc[3]; + pdest[6] = ((byte *)pcolormap[0])[temp]; + pdest[7] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 6] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 7] = ((byte *)pcolormap[3])[temp]; + temp = psrc[4]; + pdest[8] = ((byte *)pcolormap[0])[temp]; + pdest[9] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 8] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 9] = ((byte *)pcolormap[3])[temp]; + temp = psrc[5]; + pdest[10] = ((byte *)pcolormap[0])[temp]; + pdest[11] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 10] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 11] = ((byte *)pcolormap[3])[temp]; + temp = psrc[6]; + pdest[12] = ((byte *)pcolormap[0])[temp]; + pdest[13] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 12] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 13] = ((byte *)pcolormap[3])[temp]; + temp = psrc[7]; + pdest[14] = ((byte *)pcolormap[0])[temp]; + pdest[15] = ((byte *)pcolormap[1])[temp]; + pdest[nextrow + 14] = ((byte *)pcolormap[2])[temp]; + pdest[nextrow + 15] = ((byte *)pcolormap[3])[temp]; + pdest += 16; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + else + { + byte *psrc; + + psrc = (byte *)src; + + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + pdest[0] = pdest[1] = pdest[nextrow] = + pdest[nextrow + 1] = ((byte *)pcolormap[0])[psrc[0]]; + pdest[2] = pdest[3] = pdest[nextrow + 2] = + pdest[nextrow + 3] = ((byte *)pcolormap[0])[psrc[1]]; + pdest[4] = pdest[5] = pdest[nextrow + 4] = + pdest[nextrow + 5] = ((byte *)pcolormap[0])[psrc[2]]; + pdest[6] = pdest[7] = pdest[nextrow + 6] = + pdest[nextrow + 7] = ((byte *)pcolormap[0])[psrc[3]]; + pdest[8] = pdest[9] = pdest[nextrow + 8] = + pdest[nextrow + 9] = ((byte *)pcolormap[0])[psrc[4]]; + pdest[10] = pdest[11] = pdest[nextrow + 10] = + pdest[nextrow + 11] = ((byte *)pcolormap[0])[psrc[5]]; + pdest[12] = pdest[13] = pdest[nextrow + 12] = + pdest[nextrow + 13] = ((byte *)pcolormap[0])[psrc[6]]; + pdest[14] = pdest[15] = pdest[nextrow + 14] = + pdest[nextrow + 15] = ((byte *)pcolormap[0])[psrc[7]]; + pdest += 16; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + } + else + { + rowdelta = destrowbytes - width; + + if (dither) + { + unsigned short *psrc; + + psrc = (unsigned short *)src; + + for (y = height ; y>0 ; y -= 2) + { + for (x = xcount ; x ;x--) + { + pdest[0] = ((byte *)pcolormap[0])[psrc[0]]; + pdest[1] = ((byte *)pcolormap[1])[psrc[1]]; + pdest[2] = ((byte *)pcolormap[0])[psrc[2]]; + pdest[3] = ((byte *)pcolormap[1])[psrc[3]]; + pdest[4] = ((byte *)pcolormap[0])[psrc[4]]; + pdest[5] = ((byte *)pcolormap[1])[psrc[5]]; + pdest[6] = ((byte *)pcolormap[0])[psrc[6]]; + pdest[7] = ((byte *)pcolormap[1])[psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + + for (x = xcount ; x ;x--) + { + pdest[0] = ((byte *)pcolormap[2])[psrc[0]]; + pdest[1] = ((byte *)pcolormap[3])[psrc[1]]; + pdest[2] = ((byte *)pcolormap[2])[psrc[2]]; + pdest[3] = ((byte *)pcolormap[3])[psrc[3]]; + pdest[4] = ((byte *)pcolormap[2])[psrc[4]]; + pdest[5] = ((byte *)pcolormap[3])[psrc[5]]; + pdest[6] = ((byte *)pcolormap[2])[psrc[6]]; + pdest[7] = ((byte *)pcolormap[3])[psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + else + { + byte *psrc; + + psrc = (byte *)src; +// srcdelta += width; +// rowdelta += width; + + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + pdest[0] = ((byte *)pcolormap[0])[psrc[0]]; + pdest[1] = ((byte *)pcolormap[0])[psrc[1]]; + pdest[2] = ((byte *)pcolormap[0])[psrc[2]]; + pdest[3] = ((byte *)pcolormap[0])[psrc[3]]; + pdest[4] = ((byte *)pcolormap[0])[psrc[4]]; + pdest[5] = ((byte *)pcolormap[0])[psrc[5]]; + pdest[6] = ((byte *)pcolormap[0])[psrc[6]]; + pdest[7] = ((byte *)pcolormap[0])[psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + } +} + + +/* +=================== +Update16_1 +=================== +*/ +void Update16_1 (pixel_t *src, unsigned short *dest, int width, + int height, int destrowbytes) +{ + int x,y; + unsigned rowdelta, srcdelta; + unsigned xcount; + pixel_t *psrc; + unsigned short *pdest; + int xwidth; + + + psrc = src; + pdest = dest; + + xcount = width >> 3; + srcdelta = vid.width - width; + + xwidth = width - (xcount << 3); + if (xwidth) + Sys_Error ("Width not multiple of 8"); + + if ((vid_display == disp_framebuffer) && (vid_scale == 2)) + { + int nextrow = destrowbytes >> 1; + + rowdelta = (destrowbytes - ((width << 1) << 1) + destrowbytes) >> 1; + + if (dither) + { + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + unsigned temp; + + temp = psrc[0]; + pdest[0] = ((unsigned short *)pcolormap[0])[temp]; + pdest[1] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 1] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[1]; + pdest[2] = ((unsigned short *)pcolormap[0])[temp]; + pdest[3] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 2] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 3] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[2]; + pdest[4] = ((unsigned short *)pcolormap[0])[temp]; + pdest[5] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 4] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 5] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[3]; + pdest[6] = ((unsigned short *)pcolormap[0])[temp]; + pdest[7] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 6] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 7] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[4]; + pdest[8] = ((unsigned short *)pcolormap[0])[temp]; + pdest[9] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 8] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 9] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[5]; + pdest[10] = ((unsigned short *)pcolormap[0])[temp]; + pdest[11] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 10] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 11] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[6]; + pdest[12] = ((unsigned short *)pcolormap[0])[temp]; + pdest[13] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 12] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 13] = ((unsigned short *)pcolormap[3])[temp]; + temp = psrc[7]; + pdest[14] = ((unsigned short *)pcolormap[0])[temp]; + pdest[15] = ((unsigned short *)pcolormap[1])[temp]; + pdest[nextrow + 14] = ((unsigned short *)pcolormap[2])[temp]; + pdest[nextrow + 15] = ((unsigned short *)pcolormap[3])[temp]; + pdest += 16; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + else + { + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + pdest[0] = pdest[1] = pdest[nextrow] = + pdest[nextrow + 1] = pcolormap[0][psrc[0]]; + pdest[2] = pdest[3] = pdest[nextrow + 2] = + pdest[nextrow + 3] = pcolormap[0][psrc[1]]; + pdest[4] = pdest[5] = pdest[nextrow + 4] = + pdest[nextrow + 5] = pcolormap[0][psrc[2]]; + pdest[6] = pdest[7] = pdest[nextrow + 6] = + pdest[nextrow + 7] = pcolormap[0][psrc[3]]; + pdest[8] = pdest[9] = pdest[nextrow + 8] = + pdest[nextrow + 9] = pcolormap[0][psrc[4]]; + pdest[10] = pdest[11] = pdest[nextrow + 10] = + pdest[nextrow + 11] = pcolormap[0][psrc[5]]; + pdest[12] = pdest[13] = pdest[nextrow + 12] = + pdest[nextrow + 13] = pcolormap[0][psrc[6]]; + pdest[14] = pdest[15] = pdest[nextrow + 14] = + pdest[nextrow + 15] = pcolormap[0][psrc[7]]; + pdest += 16; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + } + else + { + rowdelta = (destrowbytes - (width<<1))>>1; + + if (dither) + { + for (y = height ; y>0 ; y -= 2) + { + for (x = xcount ; x ;x--) + { + pdest[0] = ((unsigned short *)pcolormap[0])[psrc[0]]; + pdest[1] = ((unsigned short *)pcolormap[1])[psrc[1]]; + pdest[2] = ((unsigned short *)pcolormap[0])[psrc[2]]; + pdest[3] = ((unsigned short *)pcolormap[1])[psrc[3]]; + pdest[4] = ((unsigned short *)pcolormap[0])[psrc[4]]; + pdest[5] = ((unsigned short *)pcolormap[1])[psrc[5]]; + pdest[6] = ((unsigned short *)pcolormap[0])[psrc[6]]; + pdest[7] = ((unsigned short *)pcolormap[1])[psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + + for (x = xcount ; x ;x--) + { + pdest[0] = ((unsigned short *)pcolormap[2])[psrc[0]]; + pdest[1] = ((unsigned short *)pcolormap[3])[psrc[1]]; + pdest[2] = ((unsigned short *)pcolormap[2])[psrc[2]]; + pdest[3] = ((unsigned short *)pcolormap[3])[psrc[3]]; + pdest[4] = ((unsigned short *)pcolormap[2])[psrc[4]]; + pdest[5] = ((unsigned short *)pcolormap[3])[psrc[5]]; + pdest[6] = ((unsigned short *)pcolormap[2])[psrc[6]]; + pdest[7] = ((unsigned short *)pcolormap[3])[psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + else + { + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + pdest[0] = pcolormap[0][psrc[0]]; + pdest[1] = pcolormap[0][psrc[1]]; + pdest[2] = pcolormap[0][psrc[2]]; + pdest[3] = pcolormap[0][psrc[3]]; + pdest[4] = pcolormap[0][psrc[4]]; + pdest[5] = pcolormap[0][psrc[5]]; + pdest[6] = pcolormap[0][psrc[6]]; + pdest[7] = pcolormap[0][psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + } +} + + +/* +=================== +Update32_1 +=================== +*/ +void Update32_1 (pixel_t *src, unsigned *dest, int width, int height, + int destrowbytes) +{ + int x,y; + unsigned rowdelta, srcdelta; + unsigned xcount; + pixel_t *psrc; + unsigned *pdest; + int xwidth; + + psrc = src; + pdest = dest; + + xcount = width >> 3; + srcdelta = vid.width - width; + + xwidth = width - (xcount << 3); + if (xwidth) + Sys_Error ("Width not multiple of 8"); + + if ((vid_display == disp_framebuffer) && (vid_scale == 2)) + { + int nextrow = destrowbytes >> 2; + + rowdelta = ((destrowbytes - ((width << 1) << 2)) >> 2) + + (destrowbytes >> 2); + + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + pdest[0] = pdest[1] = pdest[nextrow] = + pdest[nextrow + 1] = pcolormap[0][psrc[0]]; + pdest[2] = pdest[3] = pdest[nextrow + 2] = + pdest[nextrow + 3] = pcolormap[0][psrc[1]]; + pdest[4] = pdest[5] = pdest[nextrow + 4] = + pdest[nextrow + 5] = pcolormap[0][psrc[2]]; + pdest[6] = pdest[7] = pdest[nextrow + 6] = + pdest[nextrow + 7] = pcolormap[0][psrc[3]]; + pdest[8] = pdest[9] = pdest[nextrow + 8] = + pdest[nextrow + 9] = pcolormap[0][psrc[4]]; + pdest[10] = pdest[11] = pdest[nextrow + 10] = + pdest[nextrow + 11] = pcolormap[0][psrc[5]]; + pdest[12] = pdest[13] = pdest[nextrow + 12] = + pdest[nextrow + 13] = pcolormap[0][psrc[6]]; + pdest[14] = pdest[15] = pdest[nextrow + 14] = + pdest[nextrow + 15] = pcolormap[0][psrc[7]]; + pdest += 16; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } + else + { + rowdelta = (destrowbytes - (width<<2))>>2; + + for (y = height ; y ; y--) + { + for (x = xcount ; x ;x--) + { + pdest[0] = pcolormap[0][psrc[0]]; + pdest[1] = pcolormap[0][psrc[1]]; + pdest[2] = pcolormap[0][psrc[2]]; + pdest[3] = pcolormap[0][psrc[3]]; + pdest[4] = pcolormap[0][psrc[4]]; + pdest[5] = pcolormap[0][psrc[5]]; + pdest[6] = pcolormap[0][psrc[6]]; + pdest[7] = pcolormap[0][psrc[7]]; + pdest += 8; psrc += 8; + } + + psrc += srcdelta; + pdest += rowdelta; + } + } +} + + +/* +========================================================================== + + NEXTSTEP VIEW CLASS + +========================================================================== +*/ + + +@implementation QuakeView + +/* +================= +windowDidMove + +================= +*/ +- windowDidMove:sender +{ + NXPoint aPoint; + NXRect winframe; + + aPoint.x = aPoint.y = 0; + [self convertPoint:&aPoint toView:nil]; + [window convertBaseToScreen: &aPoint]; + [window getFrame: &winframe]; + + if ((int)aPoint.x & 7) + { + [window moveTo:winframe.origin.x - ((int)aPoint.x&7) + :winframe.origin.y]; + [window getFrame: &winframe]; + } + return self; +} + +- windowWillResize:sender toSize:(NXSize *)frameSize +{ + NXRect fr, cont; + + fr.origin.x = fr.origin.y = 0; + fr.size = *frameSize; + + [Window getContentRect:&cont forFrameRect: &fr style:[window style]]; + + cont.size.width = (int)cont.size.width & ~15; + if (cont.size.width < 128) + cont.size.width = 128; + cont.size.height = (int)cont.size.height & ~3; + if (cont.size.height < 32) + cont.size.height = 32; + + [Window getFrameRect:&fr forContentRect: &cont style:[window style]]; + + *frameSize = fr.size; + + return self; +} + +- windowDidResize:sender +{ + if (vid_display == disp_framebuffer) + Sys_Error ("How the heck are you resizing a framebuffer window?!?"); + + vid.width = bounds.size.width/vid_scale; + vid.height = bounds.size.height/vid_scale; + +// +// allocate memory for the back and translation buffers +// + vid.rowbytes = vid.width; + rowbytesnative = vid.width * pixbytesnative; + + AllocBuffers (true); + + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + + vid.recalc_refdef = 1; + + return self; +} + +-(BOOL) acceptsFirstResponder +{ + return YES; +} + + +typedef struct +{ + int source, dest; +} keymap_t; + +keymap_t keymaps[] = +{ + {103, K_RIGHTARROW}, + {102, K_LEFTARROW}, + {100, K_UPARROW}, + {101, K_DOWNARROW}, + {111, K_PAUSE}, + + {59, K_F1}, + {60, K_F2}, + {61, K_F3}, + {62, K_F4}, + {63, K_F5}, + {64, K_F6}, + {65, K_F7}, + {66, K_F8}, + {67, K_F9}, + {68, K_F10}, + {87, K_F11}, + {88, K_F12}, + + {-1,-1} +}; + +keymap_t flagmaps[] = +{ + {NX_SHIFTMASK, K_SHIFT}, + {NX_CONTROLMASK, K_CTRL}, + {NX_ALTERNATEMASK, K_ALT}, + {NX_COMMANDMASK, K_ALT}, + + {-1,-1} +}; + +/* +=================== +keyboard methods +=================== +*/ +- keyDown:(NXEvent *)theEvent +{ + int ch; + keymap_t *km; + + PSobscurecursor (); + +// check for non-ascii first + ch = theEvent->data.key.keyCode; + for (km=keymaps;km->source!=-1;km++) + if (ch == km->source) + { + Key_Event (km->dest, true); + return self; + } + + ch = theEvent->data.key.charCode; + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + if (ch>=256) + return self; + + Key_Event (ch, true); + return self; +} + +- flagsChanged:(NXEvent *)theEvent +{ + static int oldflags; + int newflags; + int delta; + keymap_t *km; + int i; + + PSobscurecursor (); + newflags = theEvent->flags; + delta = newflags ^ oldflags; + for (i=0 ; i<32 ; i++) + { + if ( !(delta & (1<source!=-1;km++) + if ( (1<source) + { + if (newflags & (1<dest, true); + else + Key_Event (km->dest, false); + } + + } + + oldflags = newflags; + + return self; +} + + +- keyUp:(NXEvent *)theEvent +{ + int ch; + keymap_t *km; + + // check for non-ascii first + ch = theEvent->data.key.keyCode; + for (km=keymaps;km->source!=-1;km++) + if (ch == km->source) + { + Key_Event (km->dest, false); + return self; + } + + ch = theEvent->data.key.charCode; + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + if (ch>=256) + return self; + Key_Event (ch, false); + return self; +} + + +- tiffShot +{ + id imagerep, image; + NXRect r; + NXStream *stream; + int fd; + int i; + char tiffname[80]; + + [vid_window_i getFrame: &r]; + r.origin.x = r.origin.y = 0; + image = [[NXImage alloc] initSize: &r.size]; + imagerep = [[NXCachedImageRep alloc] initFromWindow:vid_window_i rect:&r]; + + [image lockFocus]; + [imagerep draw]; + [image unlockFocus]; + +// +// find a file name to save it to +// + strcpy(tiffname,"quake00.tif"); + + for (i=0 ; i<=99 ; i++) + { + tiffname[5] = i/10 + '0'; + tiffname[6] = i%10 + '0'; + if (Sys_FileTime(tiffname) == -1) + break; // file doesn't exist + } + if (i==100) + Sys_Error ("SCR_ScreenShot_f: Couldn't create a tiff"); + + fd = open (tiffname, O_RDWR|O_CREAT|O_TRUNC, 0666); + stream = NXOpenFile (fd, NX_READWRITE); + [image writeTIFF: stream]; + NXClose (stream); + close (fd); + printf ("wrote %s\n", tiffname); + + [image free]; + [imagerep free]; + return self; + +} + +- screenShot: sender +{ + return [self tiffShot]; +} + +- setScaleFullScreen: sender +{ + VID_Shutdown (); + if (vid_fullscreen) + { + vid_fullscreen = 0; + VID_Restart (vid_display, vid_scale); + } + else + { + vid_fullscreen = 1; + VID_Restart (vid_display, vid_scale); + } + return self; +} + +@end + +//============================================================================ + +@implementation FrameWindow + +- windowExposed:(NXEvent *)theEvent +{ + return self; +} + +@end + + diff --git a/server/server.h b/server/server.h new file mode 100644 index 000000000..a8d30ca53 --- /dev/null +++ b/server/server.h @@ -0,0 +1,341 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// server.h + + +//define PARANOID // speed sapping error checking + +#include "../qcommon/qcommon.h" +#include "../game/game.h" + +//============================================================================= + +#define MAX_MASTERS 8 // max recipients for heartbeat packets + +typedef enum { + ss_dead, // no map loaded + ss_loading, // spawning level edicts + ss_game, // actively running + ss_cinematic, + ss_demo, + ss_pic +} server_state_t; +// some qc commands are only valid before the server has finished +// initializing (precache commands, static sounds / objects, etc) + +typedef struct +{ + server_state_t state; // precache commands are only valid during load + + qboolean attractloop; // running cinematics and demos for the local system only + qboolean loadgame; // client begins should reuse existing entity + + unsigned time; // always sv.framenum * 100 msec + int framenum; + + char name[MAX_QPATH]; // map name, or cinematic name + struct cmodel_s *models[MAX_MODELS]; + + char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]; + entity_state_t baselines[MAX_EDICTS]; + + // the multicast buffer is used to send a message to a set of clients + // it is only used to marshall data until SV_Multicast is called + sizebuf_t multicast; + byte multicast_buf[MAX_MSGLEN]; + + // demo server information + FILE *demofile; + qboolean timedemo; // don't time sync +} server_t; + +#define EDICT_NUM(n) ((edict_t *)((byte *)ge->edicts + ge->edict_size*(n))) +#define NUM_FOR_EDICT(e) ( ((byte *)(e)-(byte *)ge->edicts ) / ge->edict_size) + + +typedef enum +{ + cs_free, // can be reused for a new connection + cs_zombie, // client has been disconnected, but don't reuse + // connection for a couple seconds + cs_connected, // has been assigned to a client_t, but not in game yet + cs_spawned // client is fully in game +} client_state_t; + +typedef struct +{ + int areabytes; + byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits + player_state_t ps; + int num_entities; + int first_entity; // into the circular sv_packet_entities[] + int senttime; // for ping calculations +} client_frame_t; + +#define LATENCY_COUNTS 16 +#define RATE_MESSAGES 10 + +typedef struct client_s +{ + client_state_t state; + + char userinfo[MAX_INFO_STRING]; // name, etc + + int lastframe; // for delta compression + usercmd_t lastcmd; // for filling in big drops + + int commandMsec; // every seconds this is reset, if user + // commands exhaust it, assume time cheating + + int frame_latency[LATENCY_COUNTS]; + int ping; + + int message_size[RATE_MESSAGES]; // used to rate drop packets + int rate; + int surpressCount; // number of messages rate supressed + + edict_t *edict; // EDICT_NUM(clientnum+1) + char name[32]; // extracted from userinfo, high bits masked + int messagelevel; // for filtering printed messages + + // The datagram is written to by sound calls, prints, temp ents, etc. + // It can be harmlessly overflowed. + sizebuf_t datagram; + byte datagram_buf[MAX_MSGLEN]; + + client_frame_t frames[UPDATE_BACKUP]; // updates can be delta'd from here + + byte *download; // file being downloaded + int downloadsize; // total bytes (can't use EOF because of paks) + int downloadcount; // bytes sent + + int lastmessage; // sv.framenum when packet was last received + int lastconnect; + + int challenge; // challenge of this user, randomly generated + + netchan_t netchan; +} client_t; + +// a client can leave the server in one of four ways: +// dropping properly by quiting or disconnecting +// timing out if no valid messages are received for timeout.value seconds +// getting kicked off by the server operator +// a program error, like an overflowed reliable buffer + +//============================================================================= + +// MAX_CHALLENGES is made large to prevent a denial +// of service attack that could cycle all of them +// out before legitimate users connected +#define MAX_CHALLENGES 1024 + +typedef struct +{ + netadr_t adr; + int challenge; + int time; +} challenge_t; + + +typedef struct +{ + qboolean initialized; // sv_init has completed + int realtime; // always increasing, no clamping, etc + + char mapcmd[MAX_TOKEN_CHARS]; // ie: *intro.cin+base + + int spawncount; // incremented each server start + // used to check late spawns + + client_t *clients; // [maxclients->value]; + int num_client_entities; // maxclients->value*UPDATE_BACKUP*MAX_PACKET_ENTITIES + int next_client_entities; // next client_entity to use + entity_state_t *client_entities; // [num_client_entities] + + int last_heartbeat; + + challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting + + // serverrecord values + FILE *demofile; + sizebuf_t demo_multicast; + byte demo_multicast_buf[MAX_MSGLEN]; +} server_static_t; + +//============================================================================= + +extern netadr_t net_from; +extern sizebuf_t net_message; + +extern netadr_t master_adr[MAX_MASTERS]; // address of the master server + +extern server_static_t svs; // persistant server info +extern server_t sv; // local server + +extern cvar_t *sv_paused; +extern cvar_t *maxclients; +extern cvar_t *sv_noreload; // don't reload level state when reentering +extern cvar_t *sv_airaccelerate; // don't reload level state when reentering + // development tool +extern cvar_t *sv_enforcetime; + +extern client_t *sv_client; +extern edict_t *sv_player; + +//=========================================================== + +// +// sv_main.c +// +void SV_FinalMessage (char *message, qboolean reconnect); +void SV_DropClient (client_t *drop); + +int SV_ModelIndex (char *name); +int SV_SoundIndex (char *name); +int SV_ImageIndex (char *name); + +void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg); + +void SV_ExecuteUserCommand (char *s); +void SV_InitOperatorCommands (void); + +void SV_SendServerinfo (client_t *client); +void SV_UserinfoChanged (client_t *cl); + + +void Master_Heartbeat (void); +void Master_Packet (void); + +// +// sv_init.c +// +void SV_InitGame (void); +void SV_Map (qboolean attractloop, char *levelstring, qboolean loadgame); + + +// +// sv_phys.c +// +void SV_PrepWorldFrame (void); + +// +// sv_send.c +// +typedef enum {RD_NONE, RD_CLIENT, RD_PACKET} redirect_t; +#define SV_OUTPUTBUF_LENGTH (MAX_MSGLEN - 16) + +extern char sv_outputbuf[SV_OUTPUTBUF_LENGTH]; + +void SV_FlushRedirect (int sv_redirected, char *outputbuf); + +void SV_DemoCompleted (void); +void SV_SendClientMessages (void); + +void SV_Multicast (vec3_t origin, multicast_t to); +void SV_StartSound (vec3_t origin, edict_t *entity, int channel, + int soundindex, float volume, + float attenuation, float timeofs); +void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...); +void SV_BroadcastPrintf (int level, char *fmt, ...); +void SV_BroadcastCommand (char *fmt, ...); + +// +// sv_user.c +// +void SV_Nextserver (void); +void SV_ExecuteClientMessage (client_t *cl); + +// +// sv_ccmds.c +// +void SV_ReadLevelFile (void); +void SV_Status_f (void); + +// +// sv_ents.c +// +void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg); +void SV_RecordDemoMessage (void); +void SV_BuildClientFrame (client_t *client); + + +void SV_Error (char *error, ...); + +// +// sv_game.c +// +extern game_export_t *ge; + +void SV_InitGameProgs (void); +void SV_ShutdownGameProgs (void); +void SV_InitEdict (edict_t *e); + + + +//============================================================ + +// +// high level object sorting to reduce interaction tests +// + +void SV_ClearWorld (void); +// called after the world model has been loaded, before linking any entities + +void SV_UnlinkEdict (edict_t *ent); +// call before removing an entity, and before trying to move one, +// so it doesn't clip against itself + +void SV_LinkEdict (edict_t *ent); +// Needs to be called any time an entity changes origin, mins, maxs, +// or solid. Automatically unlinks if needed. +// sets ent->v.absmin and ent->v.absmax +// sets ent->leafnums[] for pvs determination even if the entity +// is not solid + +int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype); +// fills in a table of edict pointers with edicts that have bounding boxes +// that intersect the given area. It is possible for a non-axial bmodel +// to be returned that doesn't actually intersect the area on an exact +// test. +// returns the number of pointers filled in +// ??? does this always return the world? + +//=================================================================== + +// +// functions that interact with everything apropriate +// +int SV_PointContents (vec3_t p); +// returns the CONTENTS_* value from the world at the given point. +// Quake 2 extends this to also check entities, to allow moving liquids + + +trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask); +// mins and maxs are relative + +// if the entire move stays in a solid volume, trace.allsolid will be set, +// trace.startsolid will be set, and trace.fraction will be 0 + +// if the starting point is in a solid, it will be allowed to move out +// to an open area + +// passedict is explicitly excluded from clipping checks (normally NULL) + diff --git a/server/sv_ccmds.c b/server/sv_ccmds.c new file mode 100644 index 000000000..ebe6203fd --- /dev/null +++ b/server/sv_ccmds.c @@ -0,0 +1,1050 @@ +/* +Copyright (C) 1997-2001 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 "server.h" + +/* +=============================================================================== + +OPERATOR CONSOLE ONLY COMMANDS + +These commands can only be entered from stdin or by a remote operator datagram +=============================================================================== +*/ + +/* +==================== +SV_SetMaster_f + +Specify a list of master servers +==================== +*/ +void SV_SetMaster_f (void) +{ + int i, slot; + + // only dedicated servers send heartbeats + if (!dedicated->value) + { + Com_Printf ("Only dedicated servers use masters.\n"); + return; + } + + // make sure the server is listed public + Cvar_Set ("public", "1"); + + for (i=1 ; i= '0' && s[0] <= '9') + { + idnum = atoi(Cmd_Argv(1)); + if (idnum < 0 || idnum >= maxclients->value) + { + Com_Printf ("Bad client slot: %i\n", idnum); + return false; + } + + sv_client = &svs.clients[idnum]; + sv_player = sv_client->edict; + if (!sv_client->state) + { + Com_Printf ("Client %i is not active\n", idnum); + return false; + } + return true; + } + + // check for a name match + for (i=0,cl=svs.clients ; ivalue; i++,cl++) + { + if (!cl->state) + continue; + if (!strcmp(cl->name, s)) + { + sv_client = cl; + sv_player = sv_client->edict; + return true; + } + } + + Com_Printf ("Userid %s is not on the server\n", s); + return false; +} + + +/* +=============================================================================== + +SAVEGAME FILES + +=============================================================================== +*/ + +/* +===================== +SV_WipeSavegame + +Delete save// +===================== +*/ +void SV_WipeSavegame (char *savename) +{ + char name[MAX_OSPATH]; + char *s; + + Com_DPrintf("SV_WipeSaveGame(%s)\n", savename); + + Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir (), savename); + remove (name); + Com_sprintf (name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir (), savename); + remove (name); + + Com_sprintf (name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir (), savename); + s = Sys_FindFirst( name, 0, 0 ); + while (s) + { + remove (s); + s = Sys_FindNext( 0, 0 ); + } + Sys_FindClose (); + Com_sprintf (name, sizeof(name), "%s/save/%s/*.sv2", FS_Gamedir (), savename); + s = Sys_FindFirst(name, 0, 0 ); + while (s) + { + remove (s); + s = Sys_FindNext( 0, 0 ); + } + Sys_FindClose (); +} + + +/* +================ +CopyFile +================ +*/ +void CopyFile (char *src, char *dst) +{ + FILE *f1, *f2; + int l; + byte buffer[65536]; + + Com_DPrintf ("CopyFile (%s, %s)\n", src, dst); + + f1 = fopen (src, "rb"); + if (!f1) + return; + f2 = fopen (dst, "wb"); + if (!f2) + { + fclose (f1); + return; + } + + while (1) + { + l = fread (buffer, 1, sizeof(buffer), f1); + if (!l) + break; + fwrite (buffer, 1, l, f2); + } + + fclose (f1); + fclose (f2); +} + + +/* +================ +SV_CopySaveGame +================ +*/ +void SV_CopySaveGame (char *src, char *dst) +{ + char name[MAX_OSPATH], name2[MAX_OSPATH]; + int l, len; + char *found; + + Com_DPrintf("SV_CopySaveGame(%s, %s)\n", src, dst); + + SV_WipeSavegame (dst); + + // copy the savegame over + Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), src); + Com_sprintf (name2, sizeof(name2), "%s/save/%s/server.ssv", FS_Gamedir(), dst); + FS_CreatePath (name2); + CopyFile (name, name2); + + Com_sprintf (name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir(), src); + Com_sprintf (name2, sizeof(name2), "%s/save/%s/game.ssv", FS_Gamedir(), dst); + CopyFile (name, name2); + + Com_sprintf (name, sizeof(name), "%s/save/%s/", FS_Gamedir(), src); + len = strlen(name); + Com_sprintf (name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), src); + found = Sys_FindFirst(name, 0, 0 ); + while (found) + { + strcpy (name+len, found+len); + + Com_sprintf (name2, sizeof(name2), "%s/save/%s/%s", FS_Gamedir(), dst, found+len); + CopyFile (name, name2); + + // change sav to sv2 + l = strlen(name); + strcpy (name+l-3, "sv2"); + l = strlen(name2); + strcpy (name2+l-3, "sv2"); + CopyFile (name, name2); + + found = Sys_FindNext( 0, 0 ); + } + Sys_FindClose (); +} + + +/* +============== +SV_WriteLevelFile + +============== +*/ +void SV_WriteLevelFile (void) +{ + char name[MAX_OSPATH]; + FILE *f; + + Com_DPrintf("SV_WriteLevelFile()\n"); + + Com_sprintf (name, sizeof(name), "%s/save/current/%s.sv2", FS_Gamedir(), sv.name); + f = fopen(name, "wb"); + if (!f) + { + Com_Printf ("Failed to open %s\n", name); + return; + } + fwrite (sv.configstrings, sizeof(sv.configstrings), 1, f); + CM_WritePortalState (f); + fclose (f); + + Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name); + ge->WriteLevel (name); +} + +/* +============== +SV_ReadLevelFile + +============== +*/ +void SV_ReadLevelFile (void) +{ + char name[MAX_OSPATH]; + FILE *f; + + Com_DPrintf("SV_ReadLevelFile()\n"); + + Com_sprintf (name, sizeof(name), "%s/save/current/%s.sv2", FS_Gamedir(), sv.name); + f = fopen(name, "rb"); + if (!f) + { + Com_Printf ("Failed to open %s\n", name); + return; + } + FS_Read (sv.configstrings, sizeof(sv.configstrings), f); + CM_ReadPortalState (f); + fclose (f); + + Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name); + ge->ReadLevel (name); +} + +/* +============== +SV_WriteServerFile + +============== +*/ +void SV_WriteServerFile (qboolean autosave) +{ + FILE *f; + cvar_t *var; + char name[MAX_OSPATH], string[128]; + char comment[32]; + time_t aclock; + struct tm *newtime; + + Com_DPrintf("SV_WriteServerFile(%s)\n", autosave ? "true" : "false"); + + Com_sprintf (name, sizeof(name), "%s/save/current/server.ssv", FS_Gamedir()); + f = fopen (name, "wb"); + if (!f) + { + Com_Printf ("Couldn't write %s\n", name); + return; + } + // write the comment field + memset (comment, 0, sizeof(comment)); + + if (!autosave) + { + time (&aclock); + newtime = localtime (&aclock); + Com_sprintf (comment,sizeof(comment), "%2i:%i%i %2i/%2i ", newtime->tm_hour + , newtime->tm_min/10, newtime->tm_min%10, + newtime->tm_mon+1, newtime->tm_mday); + strncat (comment, sv.configstrings[CS_NAME], sizeof(comment)-1-strlen(comment) ); + } + else + { // autosaved + Com_sprintf (comment, sizeof(comment), "ENTERING %s", sv.configstrings[CS_NAME]); + } + + fwrite (comment, 1, sizeof(comment), f); + + // write the mapcmd + fwrite (svs.mapcmd, 1, sizeof(svs.mapcmd), f); + + // write all CVAR_LATCH cvars + // these will be things like coop, skill, deathmatch, etc + for (var = cvar_vars ; var ; var=var->next) + { + if (!(var->flags & CVAR_LATCH)) + continue; + if (strlen(var->name) >= sizeof(name)-1 + || strlen(var->string) >= sizeof(string)-1) + { + Com_Printf ("Cvar too long: %s = %s\n", var->name, var->string); + continue; + } + memset (name, 0, sizeof(name)); + memset (string, 0, sizeof(string)); + strcpy (name, var->name); + strcpy (string, var->string); + fwrite (name, 1, sizeof(name), f); + fwrite (string, 1, sizeof(string), f); + } + + fclose (f); + + // write game state + Com_sprintf (name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir()); + ge->WriteGame (name, autosave); +} + +/* +============== +SV_ReadServerFile + +============== +*/ +void SV_ReadServerFile (void) +{ + FILE *f; + char name[MAX_OSPATH], string[128]; + char comment[32]; + char mapcmd[MAX_TOKEN_CHARS]; + + Com_DPrintf("SV_ReadServerFile()\n"); + + Com_sprintf (name, sizeof(name), "%s/save/current/server.ssv", FS_Gamedir()); + f = fopen (name, "rb"); + if (!f) + { + Com_Printf ("Couldn't read %s\n", name); + return; + } + // read the comment field + FS_Read (comment, sizeof(comment), f); + + // read the mapcmd + FS_Read (mapcmd, sizeof(mapcmd), f); + + // read all CVAR_LATCH cvars + // these will be things like coop, skill, deathmatch, etc + while (1) + { + if (!fread (name, 1, sizeof(name), f)) + break; + FS_Read (string, sizeof(string), f); + Com_DPrintf ("Set %s = %s\n", name, string); + Cvar_ForceSet (name, string); + } + + fclose (f); + + // start a new game fresh with new cvars + SV_InitGame (); + + strcpy (svs.mapcmd, mapcmd); + + // read game state + Com_sprintf (name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir()); + ge->ReadGame (name); +} + + +//========================================================= + + + + +/* +================== +SV_DemoMap_f + +Puts the server in demo mode on a specific map/cinematic +================== +*/ +void SV_DemoMap_f (void) +{ + SV_Map (true, Cmd_Argv(1), false ); +} + +/* +================== +SV_GameMap_f + +Saves the state of the map just being exited and goes to a new map. + +If the initial character of the map string is '*', the next map is +in a new unit, so the current savegame directory is cleared of +map files. + +Example: + +*inter.cin+jail + +Clears the archived maps, plays the inter.cin cinematic, then +goes to map jail.bsp. +================== +*/ +void SV_GameMap_f (void) +{ + char *map; + int i; + client_t *cl; + qboolean *savedInuse; + + if (Cmd_Argc() != 2) + { + Com_Printf ("USAGE: gamemap \n"); + return; + } + + Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); + + FS_CreatePath (va("%s/save/current/", FS_Gamedir())); + + // check for clearing the current savegame + map = Cmd_Argv(1); + if (map[0] == '*') + { + // wipe all the *.sav files + SV_WipeSavegame ("current"); + } + else + { // save the map just exited + if (sv.state == ss_game) + { + // clear all the client inuse flags before saving so that + // when the level is re-entered, the clients will spawn + // at spawn points instead of occupying body shells + savedInuse = malloc(maxclients->value * sizeof(qboolean)); + for (i=0,cl=svs.clients ; ivalue; i++,cl++) + { + savedInuse[i] = cl->edict->inuse; + cl->edict->inuse = false; + } + + SV_WriteLevelFile (); + + // we must restore these for clients to transfer over correctly + for (i=0,cl=svs.clients ; ivalue; i++,cl++) + cl->edict->inuse = savedInuse[i]; + free (savedInuse); + } + } + + // start up the next map + SV_Map (false, Cmd_Argv(1), false ); + + // archive server state + strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1); + + // copy off the level to the autosave slot + if (!dedicated->value) + { + SV_WriteServerFile (true); + SV_CopySaveGame ("current", "save0"); + } +} + +/* +================== +SV_Map_f + +Goes directly to a given map without any savegame archiving. +For development work +================== +*/ +void SV_Map_f (void) +{ + char *map; + char expanded[MAX_QPATH]; + + // if not a pcx, demo, or cinematic, check to make sure the level exists + map = Cmd_Argv(1); + if (!strstr (map, ".")) + { + Com_sprintf (expanded, sizeof(expanded), "maps/%s.bsp", map); + if (FS_LoadFile (expanded, NULL) == -1) + { + Com_Printf ("Can't find %s\n", expanded); + return; + } + } + + sv.state = ss_dead; // don't save current level when changing + SV_WipeSavegame("current"); + SV_GameMap_f (); +} + +/* +===================================================================== + + SAVEGAMES + +===================================================================== +*/ + + +/* +============== +SV_Loadgame_f + +============== +*/ +void SV_Loadgame_f (void) +{ + char name[MAX_OSPATH]; + FILE *f; + char *dir; + + if (Cmd_Argc() != 2) + { + Com_Printf ("USAGE: loadgame \n"); + return; + } + + Com_Printf ("Loading game...\n"); + + dir = Cmd_Argv(1); + if (strstr (dir, "..") || strstr (dir, "/") || strstr (dir, "\\") ) + { + Com_Printf ("Bad savedir.\n"); + } + + // make sure the server.ssv file exists + Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), Cmd_Argv(1)); + f = fopen (name, "rb"); + if (!f) + { + Com_Printf ("No such savegame: %s\n", name); + return; + } + fclose (f); + + SV_CopySaveGame (Cmd_Argv(1), "current"); + + SV_ReadServerFile (); + + // go to the map + sv.state = ss_dead; // don't save current level when changing + SV_Map (false, svs.mapcmd, true); +} + + + +/* +============== +SV_Savegame_f + +============== +*/ +void SV_Savegame_f (void) +{ + char *dir; + + if (sv.state != ss_game) + { + Com_Printf ("You must be in a game to save.\n"); + return; + } + + if (Cmd_Argc() != 2) + { + Com_Printf ("USAGE: savegame \n"); + return; + } + + if (Cvar_VariableValue("deathmatch")) + { + Com_Printf ("Can't savegame in a deathmatch\n"); + return; + } + + if (!strcmp (Cmd_Argv(1), "current")) + { + Com_Printf ("Can't save to 'current'\n"); + return; + } + + if (maxclients->value == 1 && svs.clients[0].edict->client->ps.stats[STAT_HEALTH] <= 0) + { + Com_Printf ("\nCan't savegame while dead!\n"); + return; + } + + dir = Cmd_Argv(1); + if (strstr (dir, "..") || strstr (dir, "/") || strstr (dir, "\\") ) + { + Com_Printf ("Bad savedir.\n"); + } + + Com_Printf ("Saving game...\n"); + + // archive current level, including all client edicts. + // when the level is reloaded, they will be shells awaiting + // a connecting client + SV_WriteLevelFile (); + + // save server state + SV_WriteServerFile (false); + + // copy it off + SV_CopySaveGame ("current", dir); + + Com_Printf ("Done.\n"); +} + +//=============================================================== + +/* +================== +SV_Kick_f + +Kick a user off of the server +================== +*/ +void SV_Kick_f (void) +{ + if (!svs.initialized) + { + Com_Printf ("No server running.\n"); + return; + } + + if (Cmd_Argc() != 2) + { + Com_Printf ("Usage: kick \n"); + return; + } + + if (!SV_SetPlayer ()) + return; + + SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked\n", sv_client->name); + // print directly, because the dropped client won't get the + // SV_BroadcastPrintf message + SV_ClientPrintf (sv_client, PRINT_HIGH, "You were kicked from the game\n"); + SV_DropClient (sv_client); + sv_client->lastmessage = svs.realtime; // min case there is a funny zombie +} + + +/* +================ +SV_Status_f +================ +*/ +void SV_Status_f (void) +{ + int i, j, l; + client_t *cl; + char *s; + int ping; + if (!svs.clients) + { + Com_Printf ("No server running.\n"); + return; + } + Com_Printf ("map : %s\n", sv.name); + + Com_Printf ("num score ping name lastmsg address qport \n"); + Com_Printf ("--- ----- ---- --------------- ------- --------------------- ------\n"); + for (i=0,cl=svs.clients ; ivalue; i++,cl++) + { + if (!cl->state) + continue; + Com_Printf ("%3i ", i); + Com_Printf ("%5i ", cl->edict->client->ps.stats[STAT_FRAGS]); + + if (cl->state == cs_connected) + Com_Printf ("CNCT "); + else if (cl->state == cs_zombie) + Com_Printf ("ZMBI "); + else + { + ping = cl->ping < 9999 ? cl->ping : 9999; + Com_Printf ("%4i ", ping); + } + + Com_Printf ("%s", cl->name); + l = 16 - strlen(cl->name); + for (j=0 ; jlastmessage ); + + s = NET_AdrToString ( cl->netchan.remote_address); + Com_Printf ("%s", s); + l = 22 - strlen(s); + for (j=0 ; jnetchan.qport); + + Com_Printf ("\n"); + } + Com_Printf ("\n"); +} + +/* +================== +SV_ConSay_f +================== +*/ +void SV_ConSay_f(void) +{ + client_t *client; + int j; + char *p; + char text[1024]; + + if (Cmd_Argc () < 2) + return; + + strcpy (text, "console: "); + p = Cmd_Args(); + + if (*p == '"') + { + p++; + p[strlen(p)-1] = 0; + } + + strcat(text, p); + + for (j = 0, client = svs.clients; j < maxclients->value; j++, client++) + { + if (client->state != cs_spawned) + continue; + SV_ClientPrintf(client, PRINT_CHAT, "%s\n", text); + } +} + + +/* +================== +SV_Heartbeat_f +================== +*/ +void SV_Heartbeat_f (void) +{ + svs.last_heartbeat = -9999999; +} + + +/* +=========== +SV_Serverinfo_f + + Examine or change the serverinfo string +=========== +*/ +void SV_Serverinfo_f (void) +{ + Com_Printf ("Server info settings:\n"); + Info_Print (Cvar_Serverinfo()); +} + + +/* +=========== +SV_DumpUser_f + +Examine all a users info strings +=========== +*/ +void SV_DumpUser_f (void) +{ + if (Cmd_Argc() != 2) + { + Com_Printf ("Usage: info \n"); + return; + } + + if (!SV_SetPlayer ()) + return; + + Com_Printf ("userinfo\n"); + Com_Printf ("--------\n"); + Info_Print (sv_client->userinfo); + +} + + +/* +============== +SV_ServerRecord_f + +Begins server demo recording. Every entity and every message will be +recorded, but no playerinfo will be stored. Primarily for demo merging. +============== +*/ +void SV_ServerRecord_f (void) +{ + char name[MAX_OSPATH]; + char buf_data[32768]; + sizebuf_t buf; + int len; + int i; + + if (Cmd_Argc() != 2) + { + Com_Printf ("serverrecord \n"); + return; + } + + if (svs.demofile) + { + Com_Printf ("Already recording.\n"); + return; + } + + if (sv.state != ss_game) + { + Com_Printf ("You must be in a level to record.\n"); + return; + } + + // + // open the demo file + // + Com_sprintf (name, sizeof(name), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv(1)); + + Com_Printf ("recording to %s.\n", name); + FS_CreatePath (name); + svs.demofile = fopen (name, "wb"); + if (!svs.demofile) + { + Com_Printf ("ERROR: couldn't open.\n"); + return; + } + + // setup a buffer to catch all multicasts + SZ_Init (&svs.demo_multicast, svs.demo_multicast_buf, sizeof(svs.demo_multicast_buf)); + + // + // write a single giant fake message with all the startup info + // + SZ_Init (&buf, buf_data, sizeof(buf_data)); + + // + // serverdata needs to go over for all types of servers + // to make sure the protocol is right, and to set the gamedir + // + // send the serverdata + MSG_WriteByte (&buf, svc_serverdata); + MSG_WriteLong (&buf, PROTOCOL_VERSION); + MSG_WriteLong (&buf, svs.spawncount); + // 2 means server demo + MSG_WriteByte (&buf, 2); // demos are always attract loops + MSG_WriteString (&buf, Cvar_VariableString ("gamedir")); + MSG_WriteShort (&buf, -1); + // send full levelname + MSG_WriteString (&buf, sv.configstrings[CS_NAME]); + + for (i=0 ; iServerCommand(); +} + +//=========================================================== + +/* +================== +SV_InitOperatorCommands +================== +*/ +void SV_InitOperatorCommands (void) +{ + Cmd_AddCommand ("heartbeat", SV_Heartbeat_f); + Cmd_AddCommand ("kick", SV_Kick_f); + Cmd_AddCommand ("status", SV_Status_f); + Cmd_AddCommand ("serverinfo", SV_Serverinfo_f); + Cmd_AddCommand ("dumpuser", SV_DumpUser_f); + + Cmd_AddCommand ("map", SV_Map_f); + Cmd_AddCommand ("demomap", SV_DemoMap_f); + Cmd_AddCommand ("gamemap", SV_GameMap_f); + Cmd_AddCommand ("setmaster", SV_SetMaster_f); + + if ( dedicated->value ) + Cmd_AddCommand ("say", SV_ConSay_f); + + Cmd_AddCommand ("serverrecord", SV_ServerRecord_f); + Cmd_AddCommand ("serverstop", SV_ServerStop_f); + + Cmd_AddCommand ("save", SV_Savegame_f); + Cmd_AddCommand ("load", SV_Loadgame_f); + + Cmd_AddCommand ("killserver", SV_KillServer_f); + + Cmd_AddCommand ("sv", SV_ServerCommand_f); +} + diff --git a/server/sv_ents.c b/server/sv_ents.c new file mode 100644 index 000000000..276db134e --- /dev/null +++ b/server/sv_ents.c @@ -0,0 +1,727 @@ +/* +Copyright (C) 1997-2001 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 "server.h" + +/* +============================================================================= + +Encode a client frame onto the network channel + +============================================================================= +*/ + +#if 0 + +// because there can be a lot of projectiles, there is a special +// network protocol for them +#define MAX_PROJECTILES 64 +edict_t *projectiles[MAX_PROJECTILES]; +int numprojs; +cvar_t *sv_projectiles; + +qboolean SV_AddProjectileUpdate (edict_t *ent) +{ + if (!sv_projectiles) + sv_projectiles = Cvar_Get("sv_projectiles", "1", 0); + + if (!sv_projectiles->value) + return false; + + if (!(ent->svflags & SVF_PROJECTILE)) + return false; + if (numprojs == MAX_PROJECTILES) + return true; + + projectiles[numprojs++] = ent; + return true; +} + +void SV_EmitProjectileUpdate (sizebuf_t *msg) +{ + byte bits[16]; // [modelindex] [48 bits] xyz p y 12 12 12 8 8 [entitynum] [e2] + int n, i; + edict_t *ent; + int x, y, z, p, yaw; + int len; + + if (!numprojs) + return; + + MSG_WriteByte (msg, numprojs); + + for (n=0 ; ns.origin[0]+4096)>>1; + y = (int)(ent->s.origin[1]+4096)>>1; + z = (int)(ent->s.origin[2]+4096)>>1; + p = (int)(256*ent->s.angles[0]/360)&255; + yaw = (int)(256*ent->s.angles[1]/360)&255; + + len = 0; + bits[len++] = x; + bits[len++] = (x>>8) | (y<<4); + bits[len++] = (y>>4); + bits[len++] = z; + bits[len++] = (z>>8); + if (ent->s.effects & EF_BLASTER) + bits[len-1] |= 64; + + if (ent->s.old_origin[0] != ent->s.origin[0] || + ent->s.old_origin[1] != ent->s.origin[1] || + ent->s.old_origin[2] != ent->s.origin[2]) { + bits[len-1] |= 128; + x = (int)(ent->s.old_origin[0]+4096)>>1; + y = (int)(ent->s.old_origin[1]+4096)>>1; + z = (int)(ent->s.old_origin[2]+4096)>>1; + bits[len++] = x; + bits[len++] = (x>>8) | (y<<4); + bits[len++] = (y>>4); + bits[len++] = z; + bits[len++] = (z>>8); + } + + bits[len++] = p; + bits[len++] = yaw; + bits[len++] = ent->s.modelindex; + + bits[len++] = (ent->s.number & 0x7f); + if (ent->s.number > 255) { + bits[len-1] |= 128; + bits[len++] = (ent->s.number >> 7); + } + + for (i=0 ; inum_entities; + + newindex = 0; + oldindex = 0; + while (newindex < to->num_entities || oldindex < from_num_entities) + { + if (newindex >= to->num_entities) + newnum = 9999; + else + { + newent = &svs.client_entities[(to->first_entity+newindex)%svs.num_client_entities]; + newnum = newent->number; + } + + if (oldindex >= from_num_entities) + oldnum = 9999; + else + { + oldent = &svs.client_entities[(from->first_entity+oldindex)%svs.num_client_entities]; + oldnum = oldent->number; + } + + if (newnum == oldnum) + { // delta update from old position + // because the force parm is false, this will not result + // in any bytes being emited if the entity has not changed at all + // note that players are always 'newentities', this updates their oldorigin always + // and prevents warping + MSG_WriteDeltaEntity (oldent, newent, msg, false, newent->number <= maxclients->value); + oldindex++; + newindex++; + continue; + } + + if (newnum < oldnum) + { // this is a new entity, send it from the baseline + MSG_WriteDeltaEntity (&sv.baselines[newnum], newent, msg, true, true); + newindex++; + continue; + } + + if (newnum > oldnum) + { // the old entity isn't present in the new message + bits = U_REMOVE; + if (oldnum >= 256) + bits |= U_NUMBER16 | U_MOREBITS1; + + MSG_WriteByte (msg, bits&255 ); + if (bits & 0x0000ff00) + MSG_WriteByte (msg, (bits>>8)&255 ); + + if (bits & U_NUMBER16) + MSG_WriteShort (msg, oldnum); + else + MSG_WriteByte (msg, oldnum); + + oldindex++; + continue; + } + } + + MSG_WriteShort (msg, 0); // end of packetentities + +#if 0 + if (numprojs) + SV_EmitProjectileUpdate(msg); +#endif +} + + + +/* +============= +SV_WritePlayerstateToClient + +============= +*/ +void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, sizebuf_t *msg) +{ + int i; + int pflags; + player_state_t *ps, *ops; + player_state_t dummy; + int statbits; + + ps = &to->ps; + if (!from) + { + memset (&dummy, 0, sizeof(dummy)); + ops = &dummy; + } + else + ops = &from->ps; + + // + // determine what needs to be sent + // + pflags = 0; + + if (ps->pmove.pm_type != ops->pmove.pm_type) + pflags |= PS_M_TYPE; + + if (ps->pmove.origin[0] != ops->pmove.origin[0] + || ps->pmove.origin[1] != ops->pmove.origin[1] + || ps->pmove.origin[2] != ops->pmove.origin[2] ) + pflags |= PS_M_ORIGIN; + + if (ps->pmove.velocity[0] != ops->pmove.velocity[0] + || ps->pmove.velocity[1] != ops->pmove.velocity[1] + || ps->pmove.velocity[2] != ops->pmove.velocity[2] ) + pflags |= PS_M_VELOCITY; + + if (ps->pmove.pm_time != ops->pmove.pm_time) + pflags |= PS_M_TIME; + + if (ps->pmove.pm_flags != ops->pmove.pm_flags) + pflags |= PS_M_FLAGS; + + if (ps->pmove.gravity != ops->pmove.gravity) + pflags |= PS_M_GRAVITY; + + if (ps->pmove.delta_angles[0] != ops->pmove.delta_angles[0] + || ps->pmove.delta_angles[1] != ops->pmove.delta_angles[1] + || ps->pmove.delta_angles[2] != ops->pmove.delta_angles[2] ) + pflags |= PS_M_DELTA_ANGLES; + + + if (ps->viewoffset[0] != ops->viewoffset[0] + || ps->viewoffset[1] != ops->viewoffset[1] + || ps->viewoffset[2] != ops->viewoffset[2] ) + pflags |= PS_VIEWOFFSET; + + if (ps->viewangles[0] != ops->viewangles[0] + || ps->viewangles[1] != ops->viewangles[1] + || ps->viewangles[2] != ops->viewangles[2] ) + pflags |= PS_VIEWANGLES; + + if (ps->kick_angles[0] != ops->kick_angles[0] + || ps->kick_angles[1] != ops->kick_angles[1] + || ps->kick_angles[2] != ops->kick_angles[2] ) + pflags |= PS_KICKANGLES; + + if (ps->blend[0] != ops->blend[0] + || ps->blend[1] != ops->blend[1] + || ps->blend[2] != ops->blend[2] + || ps->blend[3] != ops->blend[3] ) + pflags |= PS_BLEND; + + if (ps->fov != ops->fov) + pflags |= PS_FOV; + + if (ps->rdflags != ops->rdflags) + pflags |= PS_RDFLAGS; + + if (ps->gunframe != ops->gunframe) + pflags |= PS_WEAPONFRAME; + + pflags |= PS_WEAPONINDEX; + + // + // write it + // + MSG_WriteByte (msg, svc_playerinfo); + MSG_WriteShort (msg, pflags); + + // + // write the pmove_state_t + // + if (pflags & PS_M_TYPE) + MSG_WriteByte (msg, ps->pmove.pm_type); + + if (pflags & PS_M_ORIGIN) + { + MSG_WriteShort (msg, ps->pmove.origin[0]); + MSG_WriteShort (msg, ps->pmove.origin[1]); + MSG_WriteShort (msg, ps->pmove.origin[2]); + } + + if (pflags & PS_M_VELOCITY) + { + MSG_WriteShort (msg, ps->pmove.velocity[0]); + MSG_WriteShort (msg, ps->pmove.velocity[1]); + MSG_WriteShort (msg, ps->pmove.velocity[2]); + } + + if (pflags & PS_M_TIME) + MSG_WriteByte (msg, ps->pmove.pm_time); + + if (pflags & PS_M_FLAGS) + MSG_WriteByte (msg, ps->pmove.pm_flags); + + if (pflags & PS_M_GRAVITY) + MSG_WriteShort (msg, ps->pmove.gravity); + + if (pflags & PS_M_DELTA_ANGLES) + { + MSG_WriteShort (msg, ps->pmove.delta_angles[0]); + MSG_WriteShort (msg, ps->pmove.delta_angles[1]); + MSG_WriteShort (msg, ps->pmove.delta_angles[2]); + } + + // + // write the rest of the player_state_t + // + if (pflags & PS_VIEWOFFSET) + { + MSG_WriteChar (msg, ps->viewoffset[0]*4); + MSG_WriteChar (msg, ps->viewoffset[1]*4); + MSG_WriteChar (msg, ps->viewoffset[2]*4); + } + + if (pflags & PS_VIEWANGLES) + { + MSG_WriteAngle16 (msg, ps->viewangles[0]); + MSG_WriteAngle16 (msg, ps->viewangles[1]); + MSG_WriteAngle16 (msg, ps->viewangles[2]); + } + + if (pflags & PS_KICKANGLES) + { + MSG_WriteChar (msg, ps->kick_angles[0]*4); + MSG_WriteChar (msg, ps->kick_angles[1]*4); + MSG_WriteChar (msg, ps->kick_angles[2]*4); + } + + if (pflags & PS_WEAPONINDEX) + { + MSG_WriteByte (msg, ps->gunindex); + } + + if (pflags & PS_WEAPONFRAME) + { + MSG_WriteByte (msg, ps->gunframe); + MSG_WriteChar (msg, ps->gunoffset[0]*4); + MSG_WriteChar (msg, ps->gunoffset[1]*4); + MSG_WriteChar (msg, ps->gunoffset[2]*4); + MSG_WriteChar (msg, ps->gunangles[0]*4); + MSG_WriteChar (msg, ps->gunangles[1]*4); + MSG_WriteChar (msg, ps->gunangles[2]*4); + } + + if (pflags & PS_BLEND) + { + MSG_WriteByte (msg, ps->blend[0]*255); + MSG_WriteByte (msg, ps->blend[1]*255); + MSG_WriteByte (msg, ps->blend[2]*255); + MSG_WriteByte (msg, ps->blend[3]*255); + } + if (pflags & PS_FOV) + MSG_WriteByte (msg, ps->fov); + if (pflags & PS_RDFLAGS) + MSG_WriteByte (msg, ps->rdflags); + + // send stats + statbits = 0; + for (i=0 ; istats[i] != ops->stats[i]) + statbits |= 1<stats[i]); +} + + +/* +================== +SV_WriteFrameToClient +================== +*/ +void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg) +{ + client_frame_t *frame, *oldframe; + int lastframe; + +//Com_Printf ("%i -> %i\n", client->lastframe, sv.framenum); + // this is the frame we are creating + frame = &client->frames[sv.framenum & UPDATE_MASK]; + + if (client->lastframe <= 0) + { // client is asking for a retransmit + oldframe = NULL; + lastframe = -1; + } + else if (sv.framenum - client->lastframe >= (UPDATE_BACKUP - 3) ) + { // client hasn't gotten a good message through in a long time +// Com_Printf ("%s: Delta request from out-of-date packet.\n", client->name); + oldframe = NULL; + lastframe = -1; + } + else + { // we have a valid message to delta from + oldframe = &client->frames[client->lastframe & UPDATE_MASK]; + lastframe = client->lastframe; + } + + MSG_WriteByte (msg, svc_frame); + MSG_WriteLong (msg, sv.framenum); + MSG_WriteLong (msg, lastframe); // what we are delta'ing from + MSG_WriteByte (msg, client->surpressCount); // rate dropped packets + client->surpressCount = 0; + + // send over the areabits + MSG_WriteByte (msg, frame->areabytes); + SZ_Write (msg, frame->areabits, frame->areabytes); + + // delta encode the playerstate + SV_WritePlayerstateToClient (oldframe, frame, msg); + + // delta encode the entities + SV_EmitPacketEntities (oldframe, frame, msg); +} + + +/* +============================================================================= + +Build a client frame structure + +============================================================================= +*/ + +byte fatpvs[65536/8]; // 32767 is MAX_MAP_LEAFS + +/* +============ +SV_FatPVS + +The client will interpolate the view position, +so we can't use a single PVS point +=========== +*/ +void SV_FatPVS (vec3_t org) +{ + int leafs[64]; + int i, j, count; + int longs; + byte *src; + vec3_t mins, maxs; + + for (i=0 ; i<3 ; i++) + { + mins[i] = org[i] - 8; + maxs[i] = org[i] + 8; + } + + count = CM_BoxLeafnums (mins, maxs, leafs, 64, NULL); + if (count < 1) + Com_Error (ERR_FATAL, "SV_FatPVS: count < 1"); + longs = (CM_NumClusters()+31)>>5; + + // convert leafs to clusters + for (i=0 ; iedict; + if (!clent->client) + return; // not in game yet + +#if 0 + numprojs = 0; // no projectiles yet +#endif + + // this is the frame we are creating + frame = &client->frames[sv.framenum & UPDATE_MASK]; + + frame->senttime = svs.realtime; // save it for ping calc later + + // find the client's PVS + for (i=0 ; i<3 ; i++) + org[i] = clent->client->ps.pmove.origin[i]*0.125 + clent->client->ps.viewoffset[i]; + + leafnum = CM_PointLeafnum (org); + clientarea = CM_LeafArea (leafnum); + clientcluster = CM_LeafCluster (leafnum); + + // calculate the visible areas + frame->areabytes = CM_WriteAreaBits (frame->areabits, clientarea); + + // grab the current player_state_t + frame->ps = clent->client->ps; + + + SV_FatPVS (org); + clientphs = CM_ClusterPHS (clientcluster); + + // build up the list of visible entities + frame->num_entities = 0; + frame->first_entity = svs.next_client_entities; + + c_fullsend = 0; + + for (e=1 ; enum_edicts ; e++) + { + ent = EDICT_NUM(e); + + // ignore ents without visible models + if (ent->svflags & SVF_NOCLIENT) + continue; + + // ignore ents without visible models unless they have an effect + if (!ent->s.modelindex && !ent->s.effects && !ent->s.sound + && !ent->s.event) + continue; + + // ignore if not touching a PV leaf + if (ent != clent) + { + // check area + if (!CM_AreasConnected (clientarea, ent->areanum)) + { // doors can legally straddle two areas, so + // we may need to check another one + if (!ent->areanum2 + || !CM_AreasConnected (clientarea, ent->areanum2)) + continue; // blocked by a door + } + + // beams just check one point for PHS + if (ent->s.renderfx & RF_BEAM) + { + l = ent->clusternums[0]; + if ( !(clientphs[l >> 3] & (1 << (l&7) )) ) + continue; + } + else + { + // FIXME: if an ent has a model and a sound, but isn't + // in the PVS, only the PHS, clear the model + if (ent->s.sound) + { + bitvector = fatpvs; //clientphs; + } + else + bitvector = fatpvs; + + if (ent->num_clusters == -1) + { // too many leafs for individual check, go by headnode + if (!CM_HeadnodeVisible (ent->headnode, bitvector)) + continue; + c_fullsend++; + } + else + { // check individual leafs + for (i=0 ; i < ent->num_clusters ; i++) + { + l = ent->clusternums[i]; + if (bitvector[l >> 3] & (1 << (l&7) )) + break; + } + if (i == ent->num_clusters) + continue; // not visible + } + + if (!ent->s.modelindex) + { // don't send sounds if they will be attenuated away + vec3_t delta; + float len; + + VectorSubtract (org, ent->s.origin, delta); + len = VectorLength (delta); + if (len > 400) + continue; + } + } + } + +#if 0 + if (SV_AddProjectileUpdate(ent)) + continue; // added as a special projectile +#endif + + // add it to the circular client_entities array + state = &svs.client_entities[svs.next_client_entities%svs.num_client_entities]; + if (ent->s.number != e) + { + Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n"); + ent->s.number = e; + } + *state = ent->s; + + // don't mark players missiles as solid + if (ent->owner == client->edict) + state->solid = 0; + + svs.next_client_entities++; + frame->num_entities++; + } +} + + +/* +================== +SV_RecordDemoMessage + +Save everything in the world out without deltas. +Used for recording footage for merged or assembled demos +================== +*/ +void SV_RecordDemoMessage (void) +{ + int e; + edict_t *ent; + entity_state_t nostate; + sizebuf_t buf; + byte buf_data[32768]; + int len; + + if (!svs.demofile) + return; + + memset (&nostate, 0, sizeof(nostate)); + SZ_Init (&buf, buf_data, sizeof(buf_data)); + + // write a frame message that doesn't contain a player_state_t + MSG_WriteByte (&buf, svc_frame); + MSG_WriteLong (&buf, sv.framenum); + + MSG_WriteByte (&buf, svc_packetentities); + + e = 1; + ent = EDICT_NUM(e); + while (e < ge->num_edicts) + { + // ignore ents without visible models unless they have an effect + if (ent->inuse && + ent->s.number && + (ent->s.modelindex || ent->s.effects || ent->s.sound || ent->s.event) && + !(ent->svflags & SVF_NOCLIENT)) + MSG_WriteDeltaEntity (&nostate, &ent->s, &buf, false, true); + + e++; + ent = EDICT_NUM(e); + } + + MSG_WriteShort (&buf, 0); // end of packetentities + + // now add the accumulated multicast information + SZ_Write (&buf, svs.demo_multicast.data, svs.demo_multicast.cursize); + SZ_Clear (&svs.demo_multicast); + + // now write the entire message to the file, prefixed by the length + len = LittleLong (buf.cursize); + fwrite (&len, 4, 1, svs.demofile); + fwrite (buf.data, buf.cursize, 1, svs.demofile); +} + diff --git a/server/sv_game.c b/server/sv_game.c new file mode 100644 index 000000000..201012280 --- /dev/null +++ b/server/sv_game.c @@ -0,0 +1,396 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// sv_game.c -- interface to the game dll + +#include "server.h" + +game_export_t *ge; + + +/* +=============== +PF_Unicast + +Sends the contents of the mutlicast buffer to a single client +=============== +*/ +void PF_Unicast (edict_t *ent, qboolean reliable) +{ + int p; + client_t *client; + + if (!ent) + return; + + p = NUM_FOR_EDICT(ent); + if (p < 1 || p > maxclients->value) + return; + + client = svs.clients + (p-1); + + if (reliable) + SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize); + else + SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize); + + SZ_Clear (&sv.multicast); +} + + +/* +=============== +PF_dprintf + +Debug print to server console +=============== +*/ +void PF_dprintf (char *fmt, ...) +{ + char msg[1024]; + va_list argptr; + + va_start (argptr,fmt); + vsprintf (msg, fmt, argptr); + va_end (argptr); + + Com_Printf ("%s", msg); +} + + +/* +=============== +PF_cprintf + +Print to a single client +=============== +*/ +void PF_cprintf (edict_t *ent, int level, char *fmt, ...) +{ + char msg[1024]; + va_list argptr; + int n; + + if (ent) + { + n = NUM_FOR_EDICT(ent); + if (n < 1 || n > maxclients->value) + Com_Error (ERR_DROP, "cprintf to a non-client"); + } + + va_start (argptr,fmt); + vsprintf (msg, fmt, argptr); + va_end (argptr); + + if (ent) + SV_ClientPrintf (svs.clients+(n-1), level, "%s", msg); + else + Com_Printf ("%s", msg); +} + + +/* +=============== +PF_centerprintf + +centerprint to a single client +=============== +*/ +void PF_centerprintf (edict_t *ent, char *fmt, ...) +{ + char msg[1024]; + va_list argptr; + int n; + + n = NUM_FOR_EDICT(ent); + if (n < 1 || n > maxclients->value) + return; // Com_Error (ERR_DROP, "centerprintf to a non-client"); + + va_start (argptr,fmt); + vsprintf (msg, fmt, argptr); + va_end (argptr); + + MSG_WriteByte (&sv.multicast,svc_centerprint); + MSG_WriteString (&sv.multicast,msg); + PF_Unicast (ent, true); +} + + +/* +=============== +PF_error + +Abort the server with a game error +=============== +*/ +void PF_error (char *fmt, ...) +{ + char msg[1024]; + va_list argptr; + + va_start (argptr,fmt); + vsprintf (msg, fmt, argptr); + va_end (argptr); + + Com_Error (ERR_DROP, "Game Error: %s", msg); +} + + +/* +================= +PF_setmodel + +Also sets mins and maxs for inline bmodels +================= +*/ +void PF_setmodel (edict_t *ent, char *name) +{ + int i; + cmodel_t *mod; + + if (!name) + Com_Error (ERR_DROP, "PF_setmodel: NULL"); + + i = SV_ModelIndex (name); + +// ent->model = name; + ent->s.modelindex = i; + +// if it is an inline model, get the size information for it + if (name[0] == '*') + { + mod = CM_InlineModel (name); + VectorCopy (mod->mins, ent->mins); + VectorCopy (mod->maxs, ent->maxs); + SV_LinkEdict (ent); + } + +} + +/* +=============== +PF_Configstring + +=============== +*/ +void PF_Configstring (int index, char *val) +{ + if (index < 0 || index >= MAX_CONFIGSTRINGS) + Com_Error (ERR_DROP, "configstring: bad index %i\n", index); + + if (!val) + val = ""; + + // change the string in sv + strcpy (sv.configstrings[index], val); + + if (sv.state != ss_loading) + { // send the update to everyone + SZ_Clear (&sv.multicast); + MSG_WriteChar (&sv.multicast, svc_configstring); + MSG_WriteShort (&sv.multicast, index); + MSG_WriteString (&sv.multicast, val); + + SV_Multicast (vec3_origin, MULTICAST_ALL_R); + } +} + + + +void PF_WriteChar (int c) {MSG_WriteChar (&sv.multicast, c);} +void PF_WriteByte (int c) {MSG_WriteByte (&sv.multicast, c);} +void PF_WriteShort (int c) {MSG_WriteShort (&sv.multicast, c);} +void PF_WriteLong (int c) {MSG_WriteLong (&sv.multicast, c);} +void PF_WriteFloat (float f) {MSG_WriteFloat (&sv.multicast, f);} +void PF_WriteString (char *s) {MSG_WriteString (&sv.multicast, s);} +void PF_WritePos (vec3_t pos) {MSG_WritePos (&sv.multicast, pos);} +void PF_WriteDir (vec3_t dir) {MSG_WriteDir (&sv.multicast, dir);} +void PF_WriteAngle (float f) {MSG_WriteAngle (&sv.multicast, f);} + + +/* +================= +PF_inPVS + +Also checks portalareas so that doors block sight +================= +*/ +qboolean PF_inPVS (vec3_t p1, vec3_t p2) +{ + int leafnum; + int cluster; + int area1, area2; + byte *mask; + + leafnum = CM_PointLeafnum (p1); + cluster = CM_LeafCluster (leafnum); + area1 = CM_LeafArea (leafnum); + mask = CM_ClusterPVS (cluster); + + leafnum = CM_PointLeafnum (p2); + cluster = CM_LeafCluster (leafnum); + area2 = CM_LeafArea (leafnum); + if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) ) + return false; + if (!CM_AreasConnected (area1, area2)) + return false; // a door blocks sight + return true; +} + + +/* +================= +PF_inPHS + +Also checks portalareas so that doors block sound +================= +*/ +qboolean PF_inPHS (vec3_t p1, vec3_t p2) +{ + int leafnum; + int cluster; + int area1, area2; + byte *mask; + + leafnum = CM_PointLeafnum (p1); + cluster = CM_LeafCluster (leafnum); + area1 = CM_LeafArea (leafnum); + mask = CM_ClusterPHS (cluster); + + leafnum = CM_PointLeafnum (p2); + cluster = CM_LeafCluster (leafnum); + area2 = CM_LeafArea (leafnum); + if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) ) + return false; // more than one bounce away + if (!CM_AreasConnected (area1, area2)) + return false; // a door blocks hearing + + return true; +} + +void PF_StartSound (edict_t *entity, int channel, int sound_num, float volume, + float attenuation, float timeofs) +{ + if (!entity) + return; + SV_StartSound (NULL, entity, channel, sound_num, volume, attenuation, timeofs); +} + +//============================================== + +/* +=============== +SV_ShutdownGameProgs + +Called when either the entire server is being killed, or +it is changing to a different game directory. +=============== +*/ +void SV_ShutdownGameProgs (void) +{ + if (!ge) + return; + ge->Shutdown (); + Sys_UnloadGame (); + ge = NULL; +} + +/* +=============== +SV_InitGameProgs + +Init the game subsystem for a new map +=============== +*/ +void SCR_DebugGraph (float value, int color); + +void SV_InitGameProgs (void) +{ + game_import_t import; + + // unload anything we have now + if (ge) + SV_ShutdownGameProgs (); + + + // load a new game dll + import.multicast = SV_Multicast; + import.unicast = PF_Unicast; + import.bprintf = SV_BroadcastPrintf; + import.dprintf = PF_dprintf; + import.cprintf = PF_cprintf; + import.centerprintf = PF_centerprintf; + import.error = PF_error; + + import.linkentity = SV_LinkEdict; + import.unlinkentity = SV_UnlinkEdict; + import.BoxEdicts = SV_AreaEdicts; + import.trace = SV_Trace; + import.pointcontents = SV_PointContents; + import.setmodel = PF_setmodel; + import.inPVS = PF_inPVS; + import.inPHS = PF_inPHS; + import.Pmove = Pmove; + + import.modelindex = SV_ModelIndex; + import.soundindex = SV_SoundIndex; + import.imageindex = SV_ImageIndex; + + import.configstring = PF_Configstring; + import.sound = PF_StartSound; + import.positioned_sound = SV_StartSound; + + import.WriteChar = PF_WriteChar; + import.WriteByte = PF_WriteByte; + import.WriteShort = PF_WriteShort; + import.WriteLong = PF_WriteLong; + import.WriteFloat = PF_WriteFloat; + import.WriteString = PF_WriteString; + import.WritePosition = PF_WritePos; + import.WriteDir = PF_WriteDir; + import.WriteAngle = PF_WriteAngle; + + import.TagMalloc = Z_TagMalloc; + import.TagFree = Z_Free; + import.FreeTags = Z_FreeTags; + + import.cvar = Cvar_Get; + import.cvar_set = Cvar_Set; + import.cvar_forceset = Cvar_ForceSet; + + import.argc = Cmd_Argc; + import.argv = Cmd_Argv; + import.args = Cmd_Args; + import.AddCommandString = Cbuf_AddText; + + import.DebugGraph = SCR_DebugGraph; + import.SetAreaPortalState = CM_SetAreaPortalState; + import.AreasConnected = CM_AreasConnected; + + ge = (game_export_t *)Sys_GetGameAPI (&import); + + if (!ge) + Com_Error (ERR_DROP, "failed to load game DLL"); + if (ge->apiversion != GAME_API_VERSION) + Com_Error (ERR_DROP, "game is version %i, not %i", ge->apiversion, + GAME_API_VERSION); + + ge->Init (); +} + diff --git a/server/sv_init.c b/server/sv_init.c new file mode 100644 index 000000000..c41382a17 --- /dev/null +++ b/server/sv_init.c @@ -0,0 +1,465 @@ +/* +Copyright (C) 1997-2001 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 "server.h" + +server_static_t svs; // persistant server info +server_t sv; // local server + +/* +================ +SV_FindIndex + +================ +*/ +int SV_FindIndex (char *name, int start, int max, qboolean create) +{ + int i; + + if (!name || !name[0]) + return 0; + + for (i=1 ; inum_edicts ; entnum++) + { + svent = EDICT_NUM(entnum); + if (!svent->inuse) + continue; + if (!svent->s.modelindex && !svent->s.sound && !svent->s.effects) + continue; + svent->s.number = entnum; + + // + // take current state as baseline + // + VectorCopy (svent->s.origin, svent->s.old_origin); + sv.baselines[entnum] = svent->s; + } +} + + +/* +================= +SV_CheckForSavegame +================= +*/ +void SV_CheckForSavegame (void) +{ + char name[MAX_OSPATH]; + FILE *f; + int i; + + if (sv_noreload->value) + return; + + if (Cvar_VariableValue ("deathmatch")) + return; + + Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name); + f = fopen (name, "rb"); + if (!f) + return; // no savegame + + fclose (f); + + SV_ClearWorld (); + + // get configstrings and areaportals + SV_ReadLevelFile (); + + if (!sv.loadgame) + { // coming back to a level after being in a different + // level, so run it for ten seconds + + // rlava2 was sending too many lightstyles, and overflowing the + // reliable data. temporarily changing the server state to loading + // prevents these from being passed down. + server_state_t previousState; // PGM + + previousState = sv.state; // PGM + sv.state = ss_loading; // PGM + for (i=0 ; i<100 ; i++) + ge->RunFrame (); + + sv.state = previousState; // PGM + } +} + + +/* +================ +SV_SpawnServer + +Change the server to a new map, taking all connected +clients along with it. + +================ +*/ +void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame) +{ + int i; + unsigned checksum; + + if (attractloop) + Cvar_Set ("paused", "0"); + + Com_Printf ("------- Server Initialization -------\n"); + + Com_DPrintf ("SpawnServer: %s\n",server); + if (sv.demofile) + fclose (sv.demofile); + + svs.spawncount++; // any partially connected client will be + // restarted + sv.state = ss_dead; + Com_SetServerState (sv.state); + + // wipe the entire per-level structure + memset (&sv, 0, sizeof(sv)); + svs.realtime = 0; + sv.loadgame = loadgame; + sv.attractloop = attractloop; + + // save name for levels that don't set message + strcpy (sv.configstrings[CS_NAME], server); + if (Cvar_VariableValue ("deathmatch")) + { + sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value); + pm_airaccelerate = sv_airaccelerate->value; + } + else + { + strcpy(sv.configstrings[CS_AIRACCEL], "0"); + pm_airaccelerate = 0; + } + + SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf)); + + strcpy (sv.name, server); + + // leave slots at start for clients only + for (i=0 ; ivalue ; i++) + { + // needs to reconnect + if (svs.clients[i].state > cs_connected) + svs.clients[i].state = cs_connected; + svs.clients[i].lastframe = -1; + } + + sv.time = 1000; + + strcpy (sv.name, server); + strcpy (sv.configstrings[CS_NAME], server); + + if (serverstate != ss_game) + { + sv.models[1] = CM_LoadMap ("", false, &checksum); // no real map + } + else + { + Com_sprintf (sv.configstrings[CS_MODELS+1],sizeof(sv.configstrings[CS_MODELS+1]), + "maps/%s.bsp", server); + sv.models[1] = CM_LoadMap (sv.configstrings[CS_MODELS+1], false, &checksum); + } + Com_sprintf (sv.configstrings[CS_MAPCHECKSUM],sizeof(sv.configstrings[CS_MAPCHECKSUM]), + "%i", checksum); + + // + // clear physics interaction links + // + SV_ClearWorld (); + + for (i=1 ; i< CM_NumInlineModels() ; i++) + { + Com_sprintf (sv.configstrings[CS_MODELS+1+i], sizeof(sv.configstrings[CS_MODELS+1+i]), + "*%i", i); + sv.models[i+1] = CM_InlineModel (sv.configstrings[CS_MODELS+1+i]); + } + + // + // spawn the rest of the entities on the map + // + + // precache and static commands can be issued during + // map initialization + sv.state = ss_loading; + Com_SetServerState (sv.state); + + // load and spawn all other entities + ge->SpawnEntities ( sv.name, CM_EntityString(), spawnpoint ); + + // run two frames to allow everything to settle + ge->RunFrame (); + ge->RunFrame (); + + // all precaches are complete + sv.state = serverstate; + Com_SetServerState (sv.state); + + // create a baseline for more efficient communications + SV_CreateBaseline (); + + // check for a savegame + SV_CheckForSavegame (); + + // set serverinfo variable + Cvar_FullSet ("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET); + + Com_Printf ("-------------------------------------\n"); +} + +/* +============== +SV_InitGame + +A brand new game has been started +============== +*/ +void SV_InitGame (void) +{ + int i; + edict_t *ent; + char idmaster[32]; + + if (svs.initialized) + { + // cause any connected clients to reconnect + SV_Shutdown ("Server restarted\n", true); + } + else + { + // make sure the client is down + CL_Drop (); + SCR_BeginLoadingPlaque (); + } + + // get any latched variable changes (maxclients, etc) + Cvar_GetLatchedVars (); + + svs.initialized = true; + + if (Cvar_VariableValue ("coop") && Cvar_VariableValue ("deathmatch")) + { + Com_Printf("Deathmatch and Coop both set, disabling Coop\n"); + Cvar_FullSet ("coop", "0", CVAR_SERVERINFO | CVAR_LATCH); + } + + // dedicated servers are can't be single player and are usually DM + // so unless they explicity set coop, force it to deathmatch + if (dedicated->value) + { + if (!Cvar_VariableValue ("coop")) + Cvar_FullSet ("deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH); + } + + // init clients + if (Cvar_VariableValue ("deathmatch")) + { + if (maxclients->value <= 1) + Cvar_FullSet ("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH); + else if (maxclients->value > MAX_CLIENTS) + Cvar_FullSet ("maxclients", va("%i", MAX_CLIENTS), CVAR_SERVERINFO | CVAR_LATCH); + } + else if (Cvar_VariableValue ("coop")) + { + if (maxclients->value <= 1 || maxclients->value > 4) + Cvar_FullSet ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH); +#ifdef COPYPROTECT + if (!sv.attractloop && !dedicated->value) + Sys_CopyProtect (); +#endif + } + else // non-deathmatch, non-coop is one player + { + Cvar_FullSet ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH); +#ifdef COPYPROTECT + if (!sv.attractloop) + Sys_CopyProtect (); +#endif + } + + svs.spawncount = rand(); + svs.clients = Z_Malloc (sizeof(client_t)*maxclients->value); + svs.num_client_entities = maxclients->value*UPDATE_BACKUP*64; + svs.client_entities = Z_Malloc (sizeof(entity_state_t)*svs.num_client_entities); + + // init network stuff + NET_Config ( (maxclients->value > 1) ); + + // heartbeats will always be sent to the id master + svs.last_heartbeat = -99999; // send immediately + Com_sprintf(idmaster, sizeof(idmaster), "192.246.40.37:%i", PORT_MASTER); + NET_StringToAdr (idmaster, &master_adr[0]); + + // init game + SV_InitGameProgs (); + for (i=0 ; ivalue ; i++) + { + ent = EDICT_NUM(i+1); + ent->s.number = i+1; + svs.clients[i].edict = ent; + memset (&svs.clients[i].lastcmd, 0, sizeof(svs.clients[i].lastcmd)); + } +} + + +/* +====================== +SV_Map + + the full syntax is: + + map [*]$+ + +command from the console or progs. +Map can also be a.cin, .pcx, or .dm2 file +Nextserver is used to allow a cinematic to play, then proceed to +another level: + + map tram.cin+jail_e3 +====================== +*/ +void SV_Map (qboolean attractloop, char *levelstring, qboolean loadgame) +{ + char level[MAX_QPATH]; + char *ch; + int l; + char spawnpoint[MAX_QPATH]; + + sv.loadgame = loadgame; + sv.attractloop = attractloop; + + if (sv.state == ss_dead && !sv.loadgame) + SV_InitGame (); // the game is just starting + + strcpy (level, levelstring); + + // if there is a + in the map, set nextserver to the remainder + ch = strstr(level, "+"); + if (ch) + { + *ch = 0; + Cvar_Set ("nextserver", va("gamemap \"%s\"", ch+1)); + } + else + Cvar_Set ("nextserver", ""); + + //ZOID special hack for end game screen in coop mode + if (Cvar_VariableValue ("coop") && !Q_stricmp(level, "victory.pcx")) + Cvar_Set ("nextserver", "gamemap \"*base1\""); + + // if there is a $, use the remainder as a spawnpoint + ch = strstr(level, "$"); + if (ch) + { + *ch = 0; + strcpy (spawnpoint, ch+1); + } + else + spawnpoint[0] = 0; + + // skip the end-of-unit flag if necessary + if (level[0] == '*') + strcpy (level, level+1); + + l = strlen(level); + if (l > 4 && !strcmp (level+l-4, ".cin") ) + { + SCR_BeginLoadingPlaque (); // for local system + SV_BroadcastCommand ("changing\n"); + SV_SpawnServer (level, spawnpoint, ss_cinematic, attractloop, loadgame); + } + else if (l > 4 && !strcmp (level+l-4, ".dm2") ) + { + SCR_BeginLoadingPlaque (); // for local system + SV_BroadcastCommand ("changing\n"); + SV_SpawnServer (level, spawnpoint, ss_demo, attractloop, loadgame); + } + else if (l > 4 && !strcmp (level+l-4, ".pcx") ) + { + SCR_BeginLoadingPlaque (); // for local system + SV_BroadcastCommand ("changing\n"); + SV_SpawnServer (level, spawnpoint, ss_pic, attractloop, loadgame); + } + else + { + SCR_BeginLoadingPlaque (); // for local system + SV_BroadcastCommand ("changing\n"); + SV_SendClientMessages (); + SV_SpawnServer (level, spawnpoint, ss_game, attractloop, loadgame); + Cbuf_CopyToDefer (); + } + + SV_BroadcastCommand ("reconnect\n"); +} diff --git a/server/sv_main.c b/server/sv_main.c new file mode 100644 index 000000000..e176e97cc --- /dev/null +++ b/server/sv_main.c @@ -0,0 +1,1055 @@ +/* +Copyright (C) 1997-2001 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 "server.h" + +netadr_t master_adr[MAX_MASTERS]; // address of group servers + +client_t *sv_client; // current client + +cvar_t *sv_paused; +cvar_t *sv_timedemo; + +cvar_t *sv_enforcetime; + +cvar_t *timeout; // seconds without any message +cvar_t *zombietime; // seconds to sink messages after disconnect + +cvar_t *rcon_password; // password for remote server commands + +cvar_t *allow_download; +cvar_t *allow_download_players; +cvar_t *allow_download_models; +cvar_t *allow_download_sounds; +cvar_t *allow_download_maps; + +cvar_t *sv_airaccelerate; + +cvar_t *sv_noreload; // don't reload level state when reentering + +cvar_t *maxclients; // FIXME: rename sv_maxclients +cvar_t *sv_showclamp; + +cvar_t *hostname; +cvar_t *public_server; // should heartbeats be sent + +cvar_t *sv_reconnect_limit; // minimum seconds between connect messages + +void Master_Shutdown (void); + + +//============================================================================ + + +/* +===================== +SV_DropClient + +Called when the player is totally leaving the server, either willingly +or unwillingly. This is NOT called if the entire server is quiting +or crashing. +===================== +*/ +void SV_DropClient (client_t *drop) +{ + // add the disconnect + MSG_WriteByte (&drop->netchan.message, svc_disconnect); + + if (drop->state == cs_spawned) + { + // call the prog function for removing a client + // this will remove the body, among other things + ge->ClientDisconnect (drop->edict); + } + + if (drop->download) + { + FS_FreeFile (drop->download); + drop->download = NULL; + } + + drop->state = cs_zombie; // become free in a few seconds + drop->name[0] = 0; +} + + + +/* +============================================================================== + +CONNECTIONLESS COMMANDS + +============================================================================== +*/ + +/* +=============== +SV_StatusString + +Builds the string that is sent as heartbeats and status replies +=============== +*/ +char *SV_StatusString (void) +{ + char player[1024]; + static char status[MAX_MSGLEN - 16]; + int i; + client_t *cl; + int statusLength; + int playerLength; + + strcpy (status, Cvar_Serverinfo()); + strcat (status, "\n"); + statusLength = strlen(status); + + for (i=0 ; ivalue ; i++) + { + cl = &svs.clients[i]; + if (cl->state == cs_connected || cl->state == cs_spawned ) + { + Com_sprintf (player, sizeof(player), "%i %i \"%s\"\n", + cl->edict->client->ps.stats[STAT_FRAGS], cl->ping, cl->name); + playerLength = strlen(player); + if (statusLength + playerLength >= sizeof(status) ) + break; // can't hold any more + strcpy (status + statusLength, player); + statusLength += playerLength; + } + } + + return status; +} + +/* +================ +SVC_Status + +Responds with all the info that qplug or qspy can see +================ +*/ +void SVC_Status (void) +{ + Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", SV_StatusString()); +#if 0 + Com_BeginRedirect (RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect); + Com_Printf (SV_StatusString()); + Com_EndRedirect (); +#endif +} + +/* +================ +SVC_Ack + +================ +*/ +void SVC_Ack (void) +{ + Com_Printf ("Ping acknowledge from %s\n", NET_AdrToString(net_from)); +} + +/* +================ +SVC_Info + +Responds with short info for broadcast scans +The second parameter should be the current protocol version number. +================ +*/ +void SVC_Info (void) +{ + char string[64]; + int i, count; + int version; + + if (maxclients->value == 1) + return; // ignore in single player + + version = atoi (Cmd_Argv(1)); + + if (version != PROTOCOL_VERSION) + Com_sprintf (string, sizeof(string), "%s: wrong version\n", hostname->string, sizeof(string)); + else + { + count = 0; + for (i=0 ; ivalue ; i++) + if (svs.clients[i].state >= cs_connected) + count++; + + Com_sprintf (string, sizeof(string), "%16s %8s %2i/%2i\n", hostname->string, sv.name, count, (int)maxclients->value); + } + + Netchan_OutOfBandPrint (NS_SERVER, net_from, "info\n%s", string); +} + +/* +================ +SVC_Ping + +Just responds with an acknowledgement +================ +*/ +void SVC_Ping (void) +{ + Netchan_OutOfBandPrint (NS_SERVER, net_from, "ack"); +} + + +/* +================= +SVC_GetChallenge + +Returns a challenge number that can be used +in a subsequent client_connect command. +We do this to prevent denial of service attacks that +flood the server with invalid connection IPs. With a +challenge, they must give a valid IP address. +================= +*/ +void SVC_GetChallenge (void) +{ + int i; + int oldest; + int oldestTime; + + oldest = 0; + oldestTime = 0x7fffffff; + + // see if we already have a challenge for this ip + for (i = 0 ; i < MAX_CHALLENGES ; i++) + { + if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr)) + break; + if (svs.challenges[i].time < oldestTime) + { + oldestTime = svs.challenges[i].time; + oldest = i; + } + } + + if (i == MAX_CHALLENGES) + { + // overwrite the oldest + svs.challenges[oldest].challenge = rand() & 0x7fff; + svs.challenges[oldest].adr = net_from; + svs.challenges[oldest].time = curtime; + i = oldest; + } + + // send it back + Netchan_OutOfBandPrint (NS_SERVER, net_from, "challenge %i", svs.challenges[i].challenge); +} + +/* +================== +SVC_DirectConnect + +A connection request that did not come from the master +================== +*/ +void SVC_DirectConnect (void) +{ + char userinfo[MAX_INFO_STRING]; + netadr_t adr; + int i; + client_t *cl, *newcl; + client_t temp; + edict_t *ent; + int edictnum; + int version; + int qport; + int challenge; + + adr = net_from; + + Com_DPrintf ("SVC_DirectConnect ()\n"); + + version = atoi(Cmd_Argv(1)); + if (version != PROTOCOL_VERSION) + { + Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is version %4.2f.\n", VERSION); + Com_DPrintf (" rejected connect from version %i\n", version); + return; + } + + qport = atoi(Cmd_Argv(2)); + + challenge = atoi(Cmd_Argv(3)); + + strncpy (userinfo, Cmd_Argv(4), sizeof(userinfo)-1); + userinfo[sizeof(userinfo) - 1] = 0; + + // force the IP key/value pair so the game can filter based on ip + Info_SetValueForKey (userinfo, "ip", NET_AdrToString(net_from)); + + // attractloop servers are ONLY for local clients + if (sv.attractloop) + { + if (!NET_IsLocalAddress (adr)) + { + Com_Printf ("Remote connect in attract loop. Ignored.\n"); + Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n"); + return; + } + } + + // see if the challenge is valid + if (!NET_IsLocalAddress (adr)) + { + for (i=0 ; ivalue ; i++,cl++) + { + if (cl->state == cs_free) + continue; + if (NET_CompareBaseAdr (adr, cl->netchan.remote_address) + && ( cl->netchan.qport == qport + || adr.port == cl->netchan.remote_address.port ) ) + { + if (!NET_IsLocalAddress (adr) && (svs.realtime - cl->lastconnect) < ((int)sv_reconnect_limit->value * 1000)) + { + Com_DPrintf ("%s:reconnect rejected : too soon\n", NET_AdrToString (adr)); + return; + } + Com_Printf ("%s:reconnect\n", NET_AdrToString (adr)); + newcl = cl; + goto gotnewcl; + } + } + + // find a client slot + newcl = NULL; + for (i=0,cl=svs.clients ; ivalue ; i++,cl++) + { + if (cl->state == cs_free) + { + newcl = cl; + break; + } + } + if (!newcl) + { + Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is full.\n"); + Com_DPrintf ("Rejected a connection.\n"); + return; + } + +gotnewcl: + // build a new connection + // accept the new client + // this is the only place a client_t is ever initialized + *newcl = temp; + sv_client = newcl; + edictnum = (newcl-svs.clients)+1; + ent = EDICT_NUM(edictnum); + newcl->edict = ent; + newcl->challenge = challenge; // save challenge for checksumming + + // get the game a chance to reject this connection or modify the userinfo + if (!(ge->ClientConnect (ent, userinfo))) + { + if (*Info_ValueForKey (userinfo, "rejmsg")) + Netchan_OutOfBandPrint (NS_SERVER, adr, "print\n%s\nConnection refused.\n", + Info_ValueForKey (userinfo, "rejmsg")); + else + Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n" ); + Com_DPrintf ("Game rejected a connection.\n"); + return; + } + + // parse some info from the info strings + strncpy (newcl->userinfo, userinfo, sizeof(newcl->userinfo)-1); + SV_UserinfoChanged (newcl); + + // send the connect packet to the client + Netchan_OutOfBandPrint (NS_SERVER, adr, "client_connect"); + + Netchan_Setup (NS_SERVER, &newcl->netchan , adr, qport); + + newcl->state = cs_connected; + + SZ_Init (&newcl->datagram, newcl->datagram_buf, sizeof(newcl->datagram_buf) ); + newcl->datagram.allowoverflow = true; + newcl->lastmessage = svs.realtime; // don't timeout + newcl->lastconnect = svs.realtime; +} + +int Rcon_Validate (void) +{ + if (!strlen (rcon_password->string)) + return 0; + + if (strcmp (Cmd_Argv(1), rcon_password->string) ) + return 0; + + return 1; +} + +/* +=============== +SVC_RemoteCommand + +A client issued an rcon command. +Shift down the remaining args +Redirect all printfs +=============== +*/ +void SVC_RemoteCommand (void) +{ + int i; + char remaining[1024]; + + i = Rcon_Validate (); + + if (i == 0) + Com_Printf ("Bad rcon from %s:\n%s\n", NET_AdrToString (net_from), net_message.data+4); + else + Com_Printf ("Rcon from %s:\n%s\n", NET_AdrToString (net_from), net_message.data+4); + + Com_BeginRedirect (RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect); + + if (!Rcon_Validate ()) + { + Com_Printf ("Bad rcon_password.\n"); + } + else + { + remaining[0] = 0; + + for (i=2 ; iping variables +=================== +*/ +void SV_CalcPings (void) +{ + int i, j; + client_t *cl; + int total, count; + + for (i=0 ; ivalue ; i++) + { + cl = &svs.clients[i]; + if (cl->state != cs_spawned ) + continue; + +#if 0 + if (cl->lastframe > 0) + cl->frame_latency[sv.framenum&(LATENCY_COUNTS-1)] = sv.framenum - cl->lastframe + 1; + else + cl->frame_latency[sv.framenum&(LATENCY_COUNTS-1)] = 0; +#endif + + total = 0; + count = 0; + for (j=0 ; jframe_latency[j] > 0) + { + count++; + total += cl->frame_latency[j]; + } + } + if (!count) + cl->ping = 0; + else +#if 0 + cl->ping = total*100/count - 100; +#else + cl->ping = total / count; +#endif + + // let the game dll know about the ping + cl->edict->client->ping = cl->ping; + } +} + + +/* +=================== +SV_GiveMsec + +Every few frames, gives all clients an allotment of milliseconds +for their command moves. If they exceed it, assume cheating. +=================== +*/ +void SV_GiveMsec (void) +{ + int i; + client_t *cl; + + if (sv.framenum & 15) + return; + + for (i=0 ; ivalue ; i++) + { + cl = &svs.clients[i]; + if (cl->state == cs_free ) + continue; + + cl->commandMsec = 1800; // 1600 + some slop + } +} + + +/* +================= +SV_ReadPackets +================= +*/ +void SV_ReadPackets (void) +{ + int i; + client_t *cl; + int qport; + + while (NET_GetPacket (NS_SERVER, &net_from, &net_message)) + { + // check for connectionless packet (0xffffffff) first + if (*(int *)net_message.data == -1) + { + SV_ConnectionlessPacket (); + continue; + } + + // read the qport out of the message so we can fix up + // stupid address translating routers + MSG_BeginReading (&net_message); + MSG_ReadLong (&net_message); // sequence number + MSG_ReadLong (&net_message); // sequence number + qport = MSG_ReadShort (&net_message) & 0xffff; + + // check for packets from connected clients + for (i=0, cl=svs.clients ; ivalue ; i++,cl++) + { + if (cl->state == cs_free) + continue; + if (!NET_CompareBaseAdr (net_from, cl->netchan.remote_address)) + continue; + if (cl->netchan.qport != qport) + continue; + if (cl->netchan.remote_address.port != net_from.port) + { + Com_Printf ("SV_ReadPackets: fixing up a translated port\n"); + cl->netchan.remote_address.port = net_from.port; + } + + if (Netchan_Process(&cl->netchan, &net_message)) + { // this is a valid, sequenced packet, so process it + if (cl->state != cs_zombie) + { + cl->lastmessage = svs.realtime; // don't timeout + SV_ExecuteClientMessage (cl); + } + } + break; + } + + if (i != maxclients->value) + continue; + } +} + +/* +================== +SV_CheckTimeouts + +If a packet has not been received from a client for timeout->value +seconds, drop the conneciton. Server frames are used instead of +realtime to avoid dropping the local client while debugging. + +When a client is normally dropped, the client_t goes into a zombie state +for a few seconds to make sure any final reliable message gets resent +if necessary +================== +*/ +void SV_CheckTimeouts (void) +{ + int i; + client_t *cl; + int droppoint; + int zombiepoint; + + droppoint = svs.realtime - 1000*timeout->value; + zombiepoint = svs.realtime - 1000*zombietime->value; + + for (i=0,cl=svs.clients ; ivalue ; i++,cl++) + { + // message times may be wrong across a changelevel + if (cl->lastmessage > svs.realtime) + cl->lastmessage = svs.realtime; + + if (cl->state == cs_zombie + && cl->lastmessage < zombiepoint) + { + cl->state = cs_free; // can now be reused + continue; + } + if ( (cl->state == cs_connected || cl->state == cs_spawned) + && cl->lastmessage < droppoint) + { + SV_BroadcastPrintf (PRINT_HIGH, "%s timed out\n", cl->name); + SV_DropClient (cl); + cl->state = cs_free; // don't bother with zombie state + } + } +} + +/* +================ +SV_PrepWorldFrame + +This has to be done before the world logic, because +player processing happens outside RunWorldFrame +================ +*/ +void SV_PrepWorldFrame (void) +{ + edict_t *ent; + int i; + + for (i=0 ; inum_edicts ; i++, ent++) + { + ent = EDICT_NUM(i); + // events only last for a single message + ent->s.event = 0; + } + +} + + +/* +================= +SV_RunGameFrame +================= +*/ +void SV_RunGameFrame (void) +{ + if (host_speeds->value) + time_before_game = Sys_Milliseconds (); + + // we always need to bump framenum, even if we + // don't run the world, otherwise the delta + // compression can get confused when a client + // has the "current" frame + sv.framenum++; + sv.time = sv.framenum*100; + + // don't run if paused + if (!sv_paused->value || maxclients->value > 1) + { + ge->RunFrame (); + + // never get more than one tic behind + if (sv.time < svs.realtime) + { + if (sv_showclamp->value) + Com_Printf ("sv highclamp\n"); + svs.realtime = sv.time; + } + } + + if (host_speeds->value) + time_after_game = Sys_Milliseconds (); + +} + +/* +================== +SV_Frame + +================== +*/ +void SV_Frame (int msec) +{ + time_before_game = time_after_game = 0; + + // if server is not active, do nothing + if (!svs.initialized) + return; + + svs.realtime += msec; + + // keep the random time dependent + rand (); + + // check timeouts + SV_CheckTimeouts (); + + // get packets from clients + SV_ReadPackets (); + + // move autonomous things around if enough time has passed + if (!sv_timedemo->value && svs.realtime < sv.time) + { + // never let the time get too far off + if (sv.time - svs.realtime > 100) + { + if (sv_showclamp->value) + Com_Printf ("sv lowclamp\n"); + svs.realtime = sv.time - 100; + } + NET_Sleep(sv.time - svs.realtime); + return; + } + + // update ping based on the last known frame from all clients + SV_CalcPings (); + + // give the clients some timeslices + SV_GiveMsec (); + + // let everything in the world think and move + SV_RunGameFrame (); + + // send messages back to the clients that had packets read this frame + SV_SendClientMessages (); + + // save the entire world state if recording a serverdemo + SV_RecordDemoMessage (); + + // send a heartbeat to the master if needed + Master_Heartbeat (); + + // clear teleport flags, etc for next frame + SV_PrepWorldFrame (); + +} + +//============================================================================ + +/* +================ +Master_Heartbeat + +Send a message to the master every few minutes to +let it know we are alive, and log information +================ +*/ +#define HEARTBEAT_SECONDS 300 +void Master_Heartbeat (void) +{ + char *string; + int i; + + + if (!dedicated->value) + return; // only dedicated servers send heartbeats + + if (!public_server->value) + return; // a private dedicated game + + // check for time wraparound + if (svs.last_heartbeat > svs.realtime) + svs.last_heartbeat = svs.realtime; + + if (svs.realtime - svs.last_heartbeat < HEARTBEAT_SECONDS*1000) + return; // not time to send yet + + svs.last_heartbeat = svs.realtime; + + // send the same string that we would give for a status OOB command + string = SV_StatusString(); + + // send to group master + for (i=0 ; ivalue) + return; // only dedicated servers send heartbeats + + if (!public_server->value) + return; // a private dedicated game + + // send to group master + for (i=0 ; i 0) + Com_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i])); + Netchan_OutOfBandPrint (NS_SERVER, master_adr[i], "shutdown"); + } +} + +//============================================================================ + + +/* +================= +SV_UserinfoChanged + +Pull specific info from a newly changed userinfo string +into a more C freindly form. +================= +*/ +void SV_UserinfoChanged (client_t *cl) +{ + char *val; + int i; + + // call prog code to allow overrides + ge->ClientUserinfoChanged (cl->edict, cl->userinfo); + + // name for C code + strncpy (cl->name, Info_ValueForKey (cl->userinfo, "name"), sizeof(cl->name)-1); + // mask off high bit + for (i=0 ; iname) ; i++) + cl->name[i] &= 127; + + // rate command + val = Info_ValueForKey (cl->userinfo, "rate"); + if (strlen(val)) + { + i = atoi(val); + cl->rate = i; + if (cl->rate < 100) + cl->rate = 100; + if (cl->rate > 15000) + cl->rate = 15000; + } + else + cl->rate = 5000; + + // msg command + val = Info_ValueForKey (cl->userinfo, "msg"); + if (strlen(val)) + { + cl->messagelevel = atoi(val); + } + +} + + +//============================================================================ + +/* +=============== +SV_Init + +Only called at quake2.exe startup, not for each game +=============== +*/ +void SV_Init (void) +{ + SV_InitOperatorCommands (); + + rcon_password = Cvar_Get ("rcon_password", "", 0); + Cvar_Get ("skill", "1", 0); + Cvar_Get ("deathmatch", "0", CVAR_LATCH); + Cvar_Get ("coop", "0", CVAR_LATCH); + Cvar_Get ("dmflags", va("%i", DF_INSTANT_ITEMS), CVAR_SERVERINFO); + Cvar_Get ("fraglimit", "0", CVAR_SERVERINFO); + Cvar_Get ("timelimit", "0", CVAR_SERVERINFO); + Cvar_Get ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH); + Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO|CVAR_NOSET);; + maxclients = Cvar_Get ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH); + hostname = Cvar_Get ("hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE); + timeout = Cvar_Get ("timeout", "125", 0); + zombietime = Cvar_Get ("zombietime", "2", 0); + sv_showclamp = Cvar_Get ("showclamp", "0", 0); + sv_paused = Cvar_Get ("paused", "0", 0); + sv_timedemo = Cvar_Get ("timedemo", "0", 0); + sv_enforcetime = Cvar_Get ("sv_enforcetime", "0", 0); + allow_download = Cvar_Get ("allow_download", "0", CVAR_ARCHIVE); + allow_download_players = Cvar_Get ("allow_download_players", "0", CVAR_ARCHIVE); + allow_download_models = Cvar_Get ("allow_download_models", "1", CVAR_ARCHIVE); + allow_download_sounds = Cvar_Get ("allow_download_sounds", "1", CVAR_ARCHIVE); + allow_download_maps = Cvar_Get ("allow_download_maps", "1", CVAR_ARCHIVE); + + sv_noreload = Cvar_Get ("sv_noreload", "0", 0); + + sv_airaccelerate = Cvar_Get("sv_airaccelerate", "0", CVAR_LATCH); + + public_server = Cvar_Get ("public", "0", 0); + + sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE); + + SZ_Init (&net_message, net_message_buffer, sizeof(net_message_buffer)); +} + +/* +================== +SV_FinalMessage + +Used by SV_Shutdown to send a final message to all +connected clients before the server goes down. The messages are sent immediately, +not just stuck on the outgoing message list, because the server is going +to totally exit after returning from this function. +================== +*/ +void SV_FinalMessage (char *message, qboolean reconnect) +{ + int i; + client_t *cl; + + SZ_Clear (&net_message); + MSG_WriteByte (&net_message, svc_print); + MSG_WriteByte (&net_message, PRINT_HIGH); + MSG_WriteString (&net_message, message); + + if (reconnect) + MSG_WriteByte (&net_message, svc_reconnect); + else + MSG_WriteByte (&net_message, svc_disconnect); + + // send it twice + // stagger the packets to crutch operating system limited buffers + + for (i=0, cl = svs.clients ; ivalue ; i++, cl++) + if (cl->state >= cs_connected) + Netchan_Transmit (&cl->netchan, net_message.cursize + , net_message.data); + + for (i=0, cl = svs.clients ; ivalue ; i++, cl++) + if (cl->state >= cs_connected) + Netchan_Transmit (&cl->netchan, net_message.cursize + , net_message.data); +} + + + +/* +================ +SV_Shutdown + +Called when each game quits, +before Sys_Quit or Sys_Error +================ +*/ +void SV_Shutdown (char *finalmsg, qboolean reconnect) +{ + if (svs.clients) + SV_FinalMessage (finalmsg, reconnect); + + Master_Shutdown (); + SV_ShutdownGameProgs (); + + // free current level + if (sv.demofile) + fclose (sv.demofile); + memset (&sv, 0, sizeof(sv)); + Com_SetServerState (sv.state); + + // free server static data + if (svs.clients) + Z_Free (svs.clients); + if (svs.client_entities) + Z_Free (svs.client_entities); + if (svs.demofile) + fclose (svs.demofile); + memset (&svs, 0, sizeof(svs)); +} + diff --git a/server/sv_null.c b/server/sv_null.c new file mode 100644 index 000000000..e9f59368f --- /dev/null +++ b/server/sv_null.c @@ -0,0 +1,15 @@ +// sv_null.c -- this file can stub out the entire server system +// for pure net-only clients + +void SV_Init (void) +{ +} + +void SV_Shutdown (char *finalmsg, qboolean reconnect) +{ +} + +void SV_Frame (float time) +{ +} + diff --git a/server/sv_send.c b/server/sv_send.c new file mode 100644 index 000000000..70aeb148d --- /dev/null +++ b/server/sv_send.c @@ -0,0 +1,567 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// sv_main.c -- server main program + +#include "server.h" + +/* +============================================================================= + +Com_Printf redirection + +============================================================================= +*/ + +char sv_outputbuf[SV_OUTPUTBUF_LENGTH]; + +void SV_FlushRedirect (int sv_redirected, char *outputbuf) +{ + if (sv_redirected == RD_PACKET) + { + Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", outputbuf); + } + else if (sv_redirected == RD_CLIENT) + { + MSG_WriteByte (&sv_client->netchan.message, svc_print); + MSG_WriteByte (&sv_client->netchan.message, PRINT_HIGH); + MSG_WriteString (&sv_client->netchan.message, outputbuf); + } +} + + +/* +============================================================================= + +EVENT MESSAGES + +============================================================================= +*/ + + +/* +================= +SV_ClientPrintf + +Sends text across to be displayed if the level passes +================= +*/ +void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...) +{ + va_list argptr; + char string[1024]; + + if (level < cl->messagelevel) + return; + + va_start (argptr,fmt); + vsprintf (string, fmt,argptr); + va_end (argptr); + + MSG_WriteByte (&cl->netchan.message, svc_print); + MSG_WriteByte (&cl->netchan.message, level); + MSG_WriteString (&cl->netchan.message, string); +} + +/* +================= +SV_BroadcastPrintf + +Sends text to all active clients +================= +*/ +void SV_BroadcastPrintf (int level, char *fmt, ...) +{ + va_list argptr; + char string[2048]; + client_t *cl; + int i; + + va_start (argptr,fmt); + vsprintf (string, fmt,argptr); + va_end (argptr); + + // echo to console + if (dedicated->value) + { + char copy[1024]; + int i; + + // mask off high bits + for (i=0 ; i<1023 && string[i] ; i++) + copy[i] = string[i]&127; + copy[i] = 0; + Com_Printf ("%s", copy); + } + + for (i=0, cl = svs.clients ; ivalue; i++, cl++) + { + if (level < cl->messagelevel) + continue; + if (cl->state != cs_spawned) + continue; + MSG_WriteByte (&cl->netchan.message, svc_print); + MSG_WriteByte (&cl->netchan.message, level); + MSG_WriteString (&cl->netchan.message, string); + } +} + +/* +================= +SV_BroadcastCommand + +Sends text to all active clients +================= +*/ +void SV_BroadcastCommand (char *fmt, ...) +{ + va_list argptr; + char string[1024]; + + if (!sv.state) + return; + va_start (argptr,fmt); + vsprintf (string, fmt,argptr); + va_end (argptr); + + MSG_WriteByte (&sv.multicast, svc_stufftext); + MSG_WriteString (&sv.multicast, string); + SV_Multicast (NULL, MULTICAST_ALL_R); +} + + +/* +================= +SV_Multicast + +Sends the contents of sv.multicast to a subset of the clients, +then clears sv.multicast. + +MULTICAST_ALL same as broadcast (origin can be NULL) +MULTICAST_PVS send to clients potentially visible from org +MULTICAST_PHS send to clients potentially hearable from org +================= +*/ +void SV_Multicast (vec3_t origin, multicast_t to) +{ + client_t *client; + byte *mask; + int leafnum, cluster; + int j; + qboolean reliable; + int area1, area2; + + reliable = false; + + if (to != MULTICAST_ALL_R && to != MULTICAST_ALL) + { + leafnum = CM_PointLeafnum (origin); + area1 = CM_LeafArea (leafnum); + } + else + { + leafnum = 0; // just to avoid compiler warnings + area1 = 0; + } + + // if doing a serverrecord, store everything + if (svs.demofile) + SZ_Write (&svs.demo_multicast, sv.multicast.data, sv.multicast.cursize); + + switch (to) + { + case MULTICAST_ALL_R: + reliable = true; // intentional fallthrough + case MULTICAST_ALL: + leafnum = 0; + mask = NULL; + break; + + case MULTICAST_PHS_R: + reliable = true; // intentional fallthrough + case MULTICAST_PHS: + leafnum = CM_PointLeafnum (origin); + cluster = CM_LeafCluster (leafnum); + mask = CM_ClusterPHS (cluster); + break; + + case MULTICAST_PVS_R: + reliable = true; // intentional fallthrough + case MULTICAST_PVS: + leafnum = CM_PointLeafnum (origin); + cluster = CM_LeafCluster (leafnum); + mask = CM_ClusterPVS (cluster); + break; + + default: + mask = NULL; + Com_Error (ERR_FATAL, "SV_Multicast: bad to:%i", to); + } + + // send the data to all relevent clients + for (j = 0, client = svs.clients; j < maxclients->value; j++, client++) + { + if (client->state == cs_free || client->state == cs_zombie) + continue; + if (client->state != cs_spawned && !reliable) + continue; + + if (mask) + { + leafnum = CM_PointLeafnum (client->edict->s.origin); + cluster = CM_LeafCluster (leafnum); + area2 = CM_LeafArea (leafnum); + if (!CM_AreasConnected (area1, area2)) + continue; + if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) ) + continue; + } + + if (reliable) + SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize); + else + SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize); + } + + SZ_Clear (&sv.multicast); +} + + +/* +================== +SV_StartSound + +Each entity can have eight independant sound sources, like voice, +weapon, feet, etc. + +If cahnnel & 8, the sound will be sent to everyone, not just +things in the PHS. + +FIXME: if entity isn't in PHS, they must be forced to be sent or +have the origin explicitly sent. + +Channel 0 is an auto-allocate channel, the others override anything +already running on that entity/channel pair. + +An attenuation of 0 will play full volume everywhere in the level. +Larger attenuations will drop off. (max 4 attenuation) + +Timeofs can range from 0.0 to 0.1 to cause sounds to be started +later in the frame than they normally would. + +If origin is NULL, the origin is determined from the entity origin +or the midpoint of the entity box for bmodels. +================== +*/ +void SV_StartSound (vec3_t origin, edict_t *entity, int channel, + int soundindex, float volume, + float attenuation, float timeofs) +{ + int sendchan; + int flags; + int i; + int ent; + vec3_t origin_v; + qboolean use_phs; + + if (volume < 0 || volume > 1.0) + Com_Error (ERR_FATAL, "SV_StartSound: volume = %f", volume); + + if (attenuation < 0 || attenuation > 4) + Com_Error (ERR_FATAL, "SV_StartSound: attenuation = %f", attenuation); + +// if (channel < 0 || channel > 15) +// Com_Error (ERR_FATAL, "SV_StartSound: channel = %i", channel); + + if (timeofs < 0 || timeofs > 0.255) + Com_Error (ERR_FATAL, "SV_StartSound: timeofs = %f", timeofs); + + ent = NUM_FOR_EDICT(entity); + + if (channel & 8) // no PHS flag + { + use_phs = false; + channel &= 7; + } + else + use_phs = true; + + sendchan = (ent<<3) | (channel&7); + + flags = 0; + if (volume != DEFAULT_SOUND_PACKET_VOLUME) + flags |= SND_VOLUME; + if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION) + flags |= SND_ATTENUATION; + + // the client doesn't know that bmodels have weird origins + // the origin can also be explicitly set + if ( (entity->svflags & SVF_NOCLIENT) + || (entity->solid == SOLID_BSP) + || origin ) + flags |= SND_POS; + + // always send the entity number for channel overrides + flags |= SND_ENT; + + if (timeofs) + flags |= SND_OFFSET; + + // use the entity origin unless it is a bmodel or explicitly specified + if (!origin) + { + origin = origin_v; + if (entity->solid == SOLID_BSP) + { + for (i=0 ; i<3 ; i++) + origin_v[i] = entity->s.origin[i]+0.5*(entity->mins[i]+entity->maxs[i]); + } + else + { + VectorCopy (entity->s.origin, origin_v); + } + } + + MSG_WriteByte (&sv.multicast, svc_sound); + MSG_WriteByte (&sv.multicast, flags); + MSG_WriteByte (&sv.multicast, soundindex); + + if (flags & SND_VOLUME) + MSG_WriteByte (&sv.multicast, volume*255); + if (flags & SND_ATTENUATION) + MSG_WriteByte (&sv.multicast, attenuation*64); + if (flags & SND_OFFSET) + MSG_WriteByte (&sv.multicast, timeofs*1000); + + if (flags & SND_ENT) + MSG_WriteShort (&sv.multicast, sendchan); + + if (flags & SND_POS) + MSG_WritePos (&sv.multicast, origin); + + // if the sound doesn't attenuate,send it to everyone + // (global radio chatter, voiceovers, etc) + if (attenuation == ATTN_NONE) + use_phs = false; + + if (channel & CHAN_RELIABLE) + { + if (use_phs) + SV_Multicast (origin, MULTICAST_PHS_R); + else + SV_Multicast (origin, MULTICAST_ALL_R); + } + else + { + if (use_phs) + SV_Multicast (origin, MULTICAST_PHS); + else + SV_Multicast (origin, MULTICAST_ALL); + } +} + + +/* +=============================================================================== + +FRAME UPDATES + +=============================================================================== +*/ + + + +/* +======================= +SV_SendClientDatagram +======================= +*/ +qboolean SV_SendClientDatagram (client_t *client) +{ + byte msg_buf[MAX_MSGLEN]; + sizebuf_t msg; + + SV_BuildClientFrame (client); + + SZ_Init (&msg, msg_buf, sizeof(msg_buf)); + msg.allowoverflow = true; + + // send over all the relevant entity_state_t + // and the player_state_t + SV_WriteFrameToClient (client, &msg); + + // copy the accumulated multicast datagram + // for this client out to the message + // it is necessary for this to be after the WriteEntities + // so that entity references will be current + if (client->datagram.overflowed) + Com_Printf ("WARNING: datagram overflowed for %s\n", client->name); + else + SZ_Write (&msg, client->datagram.data, client->datagram.cursize); + SZ_Clear (&client->datagram); + + if (msg.overflowed) + { // must have room left for the packet header + Com_Printf ("WARNING: msg overflowed for %s\n", client->name); + SZ_Clear (&msg); + } + + // send the datagram + Netchan_Transmit (&client->netchan, msg.cursize, msg.data); + + // record the size for rate estimation + client->message_size[sv.framenum % RATE_MESSAGES] = msg.cursize; + + return true; +} + + +/* +================== +SV_DemoCompleted +================== +*/ +void SV_DemoCompleted (void) +{ + if (sv.demofile) + { + fclose (sv.demofile); + sv.demofile = NULL; + } + SV_Nextserver (); +} + + +/* +======================= +SV_RateDrop + +Returns true if the client is over its current +bandwidth estimation and should not be sent another packet +======================= +*/ +qboolean SV_RateDrop (client_t *c) +{ + int total; + int i; + + // never drop over the loopback + if (c->netchan.remote_address.type == NA_LOOPBACK) + return false; + + total = 0; + + for (i = 0 ; i < RATE_MESSAGES ; i++) + { + total += c->message_size[i]; + } + + if (total > c->rate) + { + c->surpressCount++; + c->message_size[sv.framenum % RATE_MESSAGES] = 0; + return true; + } + + return false; +} + +/* +======================= +SV_SendClientMessages +======================= +*/ +void SV_SendClientMessages (void) +{ + int i; + client_t *c; + int msglen; + byte msgbuf[MAX_MSGLEN]; + int r; + + msglen = 0; + + // read the next demo message if needed + if (sv.state == ss_demo && sv.demofile) + { + if (sv_paused->value) + msglen = 0; + else + { + // get the next message + r = fread (&msglen, 4, 1, sv.demofile); + if (r != 1) + { + SV_DemoCompleted (); + return; + } + msglen = LittleLong (msglen); + if (msglen == -1) + { + SV_DemoCompleted (); + return; + } + if (msglen > MAX_MSGLEN) + Com_Error (ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN"); + r = fread (msgbuf, msglen, 1, sv.demofile); + if (r != 1) + { + SV_DemoCompleted (); + return; + } + } + } + + // send a message to each connected client + for (i=0, c = svs.clients ; ivalue; i++, c++) + { + if (!c->state) + continue; + // if the reliable message overflowed, + // drop the client + if (c->netchan.message.overflowed) + { + SZ_Clear (&c->netchan.message); + SZ_Clear (&c->datagram); + SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name); + SV_DropClient (c); + } + + if (sv.state == ss_cinematic + || sv.state == ss_demo + || sv.state == ss_pic + ) + Netchan_Transmit (&c->netchan, msglen, msgbuf); + else if (c->state == cs_spawned) + { + // don't overrun bandwidth + if (SV_RateDrop (c)) + continue; + + SV_SendClientDatagram (c); + } + else + { + // just update reliable if needed + if (c->netchan.message.cursize || curtime - c->netchan.last_sent > 1000 ) + Netchan_Transmit (&c->netchan, 0, NULL); + } + } +} + diff --git a/server/sv_user.c b/server/sv_user.c new file mode 100644 index 000000000..7ab7cc01d --- /dev/null +++ b/server/sv_user.c @@ -0,0 +1,664 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// sv_user.c -- server code for moving users + +#include "server.h" + +edict_t *sv_player; + +/* +============================================================ + +USER STRINGCMD EXECUTION + +sv_client and sv_player will be valid. +============================================================ +*/ + +/* +================== +SV_BeginDemoServer +================== +*/ +void SV_BeginDemoserver (void) +{ + char name[MAX_OSPATH]; + + Com_sprintf (name, sizeof(name), "demos/%s", sv.name); + FS_FOpenFile (name, &sv.demofile); + if (!sv.demofile) + Com_Error (ERR_DROP, "Couldn't open %s\n", name); +} + +/* +================ +SV_New_f + +Sends the first message from the server to a connected client. +This will be sent on the initial connection and upon each server load. +================ +*/ +void SV_New_f (void) +{ + char *gamedir; + int playernum; + edict_t *ent; + + Com_DPrintf ("New() from %s\n", sv_client->name); + + if (sv_client->state != cs_connected) + { + Com_Printf ("New not valid -- already spawned\n"); + return; + } + + // demo servers just dump the file message + if (sv.state == ss_demo) + { + SV_BeginDemoserver (); + return; + } + + // + // serverdata needs to go over for all types of servers + // to make sure the protocol is right, and to set the gamedir + // + gamedir = Cvar_VariableString ("gamedir"); + + // send the serverdata + MSG_WriteByte (&sv_client->netchan.message, svc_serverdata); + MSG_WriteLong (&sv_client->netchan.message, PROTOCOL_VERSION); + MSG_WriteLong (&sv_client->netchan.message, svs.spawncount); + MSG_WriteByte (&sv_client->netchan.message, sv.attractloop); + MSG_WriteString (&sv_client->netchan.message, gamedir); + + if (sv.state == ss_cinematic || sv.state == ss_pic) + playernum = -1; + else + playernum = sv_client - svs.clients; + MSG_WriteShort (&sv_client->netchan.message, playernum); + + // send full levelname + MSG_WriteString (&sv_client->netchan.message, sv.configstrings[CS_NAME]); + + // + // game server + // + if (sv.state == ss_game) + { + // set up the entity for the client + ent = EDICT_NUM(playernum+1); + ent->s.number = playernum+1; + sv_client->edict = ent; + memset (&sv_client->lastcmd, 0, sizeof(sv_client->lastcmd)); + + // begin fetching configstrings + MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); + MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i 0\n",svs.spawncount) ); + } + +} + +/* +================== +SV_Configstrings_f +================== +*/ +void SV_Configstrings_f (void) +{ + int start; + + Com_DPrintf ("Configstrings() from %s\n", sv_client->name); + + if (sv_client->state != cs_connected) + { + Com_Printf ("configstrings not valid -- already spawned\n"); + return; + } + + // handle the case of a level changing while a client was connecting + if ( atoi(Cmd_Argv(1)) != svs.spawncount ) + { + Com_Printf ("SV_Configstrings_f from different level\n"); + SV_New_f (); + return; + } + + start = atoi(Cmd_Argv(2)); + + // write a packet full of data + + while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 + && start < MAX_CONFIGSTRINGS) + { + if (sv.configstrings[start][0]) + { + MSG_WriteByte (&sv_client->netchan.message, svc_configstring); + MSG_WriteShort (&sv_client->netchan.message, start); + MSG_WriteString (&sv_client->netchan.message, sv.configstrings[start]); + } + start++; + } + + // send next command + + if (start == MAX_CONFIGSTRINGS) + { + MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); + MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i 0\n",svs.spawncount) ); + } + else + { + MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); + MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i %i\n",svs.spawncount, start) ); + } +} + +/* +================== +SV_Baselines_f +================== +*/ +void SV_Baselines_f (void) +{ + int start; + entity_state_t nullstate; + entity_state_t *base; + + Com_DPrintf ("Baselines() from %s\n", sv_client->name); + + if (sv_client->state != cs_connected) + { + Com_Printf ("baselines not valid -- already spawned\n"); + return; + } + + // handle the case of a level changing while a client was connecting + if ( atoi(Cmd_Argv(1)) != svs.spawncount ) + { + Com_Printf ("SV_Baselines_f from different level\n"); + SV_New_f (); + return; + } + + start = atoi(Cmd_Argv(2)); + + memset (&nullstate, 0, sizeof(nullstate)); + + // write a packet full of data + + while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 + && start < MAX_EDICTS) + { + base = &sv.baselines[start]; + if (base->modelindex || base->sound || base->effects) + { + MSG_WriteByte (&sv_client->netchan.message, svc_spawnbaseline); + MSG_WriteDeltaEntity (&nullstate, base, &sv_client->netchan.message, true, true); + } + start++; + } + + // send next command + + if (start == MAX_EDICTS) + { + MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); + MSG_WriteString (&sv_client->netchan.message, va("precache %i\n", svs.spawncount) ); + } + else + { + MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); + MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i %i\n",svs.spawncount, start) ); + } +} + +/* +================== +SV_Begin_f +================== +*/ +void SV_Begin_f (void) +{ + Com_DPrintf ("Begin() from %s\n", sv_client->name); + + // handle the case of a level changing while a client was connecting + if ( atoi(Cmd_Argv(1)) != svs.spawncount ) + { + Com_Printf ("SV_Begin_f from different level\n"); + SV_New_f (); + return; + } + + sv_client->state = cs_spawned; + + // call the game begin function + ge->ClientBegin (sv_player); + + Cbuf_InsertFromDefer (); +} + +//============================================================================= + +/* +================== +SV_NextDownload_f +================== +*/ +void SV_NextDownload_f (void) +{ + int r; + int percent; + int size; + + if (!sv_client->download) + return; + + r = sv_client->downloadsize - sv_client->downloadcount; + if (r > 1024) + r = 1024; + + MSG_WriteByte (&sv_client->netchan.message, svc_download); + MSG_WriteShort (&sv_client->netchan.message, r); + + sv_client->downloadcount += r; + size = sv_client->downloadsize; + if (!size) + size = 1; + percent = sv_client->downloadcount*100/size; + MSG_WriteByte (&sv_client->netchan.message, percent); + SZ_Write (&sv_client->netchan.message, + sv_client->download + sv_client->downloadcount - r, r); + + if (sv_client->downloadcount != sv_client->downloadsize) + return; + + FS_FreeFile (sv_client->download); + sv_client->download = NULL; +} + +/* +================== +SV_BeginDownload_f +================== +*/ +void SV_BeginDownload_f(void) +{ + char *name; + extern cvar_t *allow_download; + extern cvar_t *allow_download_players; + extern cvar_t *allow_download_models; + extern cvar_t *allow_download_sounds; + extern cvar_t *allow_download_maps; + extern int file_from_pak; // ZOID did file come from pak? + int offset = 0; + + name = Cmd_Argv(1); + + if (Cmd_Argc() > 2) + offset = atoi(Cmd_Argv(2)); // downloaded offset + + // hacked by zoid to allow more conrol over download + // first off, no .. or global allow check + if (strstr (name, "..") || !allow_download->value + // leading dot is no good + || *name == '.' + // leading slash bad as well, must be in subdir + || *name == '/' + // next up, skin check + || (strncmp(name, "players/", 6) == 0 && !allow_download_players->value) + // now models + || (strncmp(name, "models/", 6) == 0 && !allow_download_models->value) + // now sounds + || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) + // now maps (note special case for maps, must not be in pak) + || (strncmp(name, "maps/", 6) == 0 && !allow_download_maps->value) + // MUST be in a subdirectory + || !strstr (name, "/") ) + { // don't allow anything with .. path + MSG_WriteByte (&sv_client->netchan.message, svc_download); + MSG_WriteShort (&sv_client->netchan.message, -1); + MSG_WriteByte (&sv_client->netchan.message, 0); + return; + } + + + if (sv_client->download) + FS_FreeFile (sv_client->download); + + sv_client->downloadsize = FS_LoadFile (name, (void **)&sv_client->download); + sv_client->downloadcount = offset; + + if (offset > sv_client->downloadsize) + sv_client->downloadcount = sv_client->downloadsize; + + if (!sv_client->download + // special check for maps, if it came from a pak file, don't allow + // download ZOID + || (strncmp(name, "maps/", 5) == 0 && file_from_pak)) + { + Com_DPrintf ("Couldn't download %s to %s\n", name, sv_client->name); + if (sv_client->download) { + FS_FreeFile (sv_client->download); + sv_client->download = NULL; + } + + MSG_WriteByte (&sv_client->netchan.message, svc_download); + MSG_WriteShort (&sv_client->netchan.message, -1); + MSG_WriteByte (&sv_client->netchan.message, 0); + return; + } + + SV_NextDownload_f (); + Com_DPrintf ("Downloading %s to %s\n", name, sv_client->name); +} + + + +//============================================================================ + + +/* +================= +SV_Disconnect_f + +The client is going to disconnect, so remove the connection immediately +================= +*/ +void SV_Disconnect_f (void) +{ +// SV_EndRedirect (); + SV_DropClient (sv_client); +} + + +/* +================== +SV_ShowServerinfo_f + +Dumps the serverinfo info string +================== +*/ +void SV_ShowServerinfo_f (void) +{ + Info_Print (Cvar_Serverinfo()); +} + + +void SV_Nextserver (void) +{ + char *v; + + //ZOID, ss_pic can be nextserver'd in coop mode + if (sv.state == ss_game || (sv.state == ss_pic && !Cvar_VariableValue("coop"))) + return; // can't nextserver while playing a normal game + + svs.spawncount++; // make sure another doesn't sneak in + v = Cvar_VariableString ("nextserver"); + if (!v[0]) + Cbuf_AddText ("killserver\n"); + else + { + Cbuf_AddText (v); + Cbuf_AddText ("\n"); + } + Cvar_Set ("nextserver",""); +} + +/* +================== +SV_Nextserver_f + +A cinematic has completed or been aborted by a client, so move +to the next server, +================== +*/ +void SV_Nextserver_f (void) +{ + if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { + Com_DPrintf ("Nextserver() from wrong level, from %s\n", sv_client->name); + return; // leftover from last server + } + + Com_DPrintf ("Nextserver() from %s\n", sv_client->name); + + SV_Nextserver (); +} + +typedef struct +{ + char *name; + void (*func) (void); +} ucmd_t; + +ucmd_t ucmds[] = +{ + // auto issued + {"new", SV_New_f}, + {"configstrings", SV_Configstrings_f}, + {"baselines", SV_Baselines_f}, + {"begin", SV_Begin_f}, + + {"nextserver", SV_Nextserver_f}, + + {"disconnect", SV_Disconnect_f}, + + // issued by hand at client consoles + {"info", SV_ShowServerinfo_f}, + + {"download", SV_BeginDownload_f}, + {"nextdl", SV_NextDownload_f}, + + {NULL, NULL} +}; + +/* +================== +SV_ExecuteUserCommand +================== +*/ +void SV_ExecuteUserCommand (char *s) +{ + ucmd_t *u; + + Cmd_TokenizeString (s, true); + sv_player = sv_client->edict; + +// SV_BeginRedirect (RD_CLIENT); + + for (u=ucmds ; u->name ; u++) + if (!strcmp (Cmd_Argv(0), u->name) ) + { + u->func (); + break; + } + + if (!u->name && sv.state == ss_game) + ge->ClientCommand (sv_player); + +// SV_EndRedirect (); +} + +/* +=========================================================================== + +USER CMD EXECUTION + +=========================================================================== +*/ + + + +void SV_ClientThink (client_t *cl, usercmd_t *cmd) + +{ + cl->commandMsec -= cmd->msec; + + if (cl->commandMsec < 0 && sv_enforcetime->value ) + { + Com_DPrintf ("commandMsec underflow from %s\n", cl->name); + return; + } + + ge->ClientThink (cl->edict, cmd); +} + + + +#define MAX_STRINGCMDS 8 +/* +=================== +SV_ExecuteClientMessage + +The current net_message is parsed for the given client +=================== +*/ +void SV_ExecuteClientMessage (client_t *cl) +{ + int c; + char *s; + + usercmd_t nullcmd; + usercmd_t oldest, oldcmd, newcmd; + int net_drop; + int stringCmdCount; + int checksum, calculatedChecksum; + int checksumIndex; + qboolean move_issued; + int lastframe; + + sv_client = cl; + sv_player = sv_client->edict; + + // only allow one move command + move_issued = false; + stringCmdCount = 0; + + while (1) + { + if (net_message.readcount > net_message.cursize) + { + Com_Printf ("SV_ReadClientMessage: badread\n"); + SV_DropClient (cl); + return; + } + + c = MSG_ReadByte (&net_message); + if (c == -1) + break; + + switch (c) + { + default: + Com_Printf ("SV_ReadClientMessage: unknown command char\n"); + SV_DropClient (cl); + return; + + case clc_nop: + break; + + case clc_userinfo: + strncpy (cl->userinfo, MSG_ReadString (&net_message), sizeof(cl->userinfo)-1); + SV_UserinfoChanged (cl); + break; + + case clc_move: + if (move_issued) + return; // someone is trying to cheat... + + move_issued = true; + checksumIndex = net_message.readcount; + checksum = MSG_ReadByte (&net_message); + lastframe = MSG_ReadLong (&net_message); + if (lastframe != cl->lastframe) { + cl->lastframe = lastframe; + if (cl->lastframe > 0) { + cl->frame_latency[cl->lastframe&(LATENCY_COUNTS-1)] = + svs.realtime - cl->frames[cl->lastframe & UPDATE_MASK].senttime; + } + } + + memset (&nullcmd, 0, sizeof(nullcmd)); + MSG_ReadDeltaUsercmd (&net_message, &nullcmd, &oldest); + MSG_ReadDeltaUsercmd (&net_message, &oldest, &oldcmd); + MSG_ReadDeltaUsercmd (&net_message, &oldcmd, &newcmd); + + if ( cl->state != cs_spawned ) + { + cl->lastframe = -1; + break; + } + + // if the checksum fails, ignore the rest of the packet + calculatedChecksum = COM_BlockSequenceCRCByte ( + net_message.data + checksumIndex + 1, + net_message.readcount - checksumIndex - 1, + cl->netchan.incoming_sequence); + + if (calculatedChecksum != checksum) + { + Com_DPrintf ("Failed command checksum for %s (%d != %d)/%d\n", + cl->name, calculatedChecksum, checksum, + cl->netchan.incoming_sequence); + return; + } + + if (!sv_paused->value) + { + net_drop = cl->netchan.dropped; + if (net_drop < 20) + { + +//if (net_drop > 2) + +// Com_Printf ("drop %i\n", net_drop); + while (net_drop > 2) + { + SV_ClientThink (cl, &cl->lastcmd); + + net_drop--; + } + if (net_drop > 1) + SV_ClientThink (cl, &oldest); + + if (net_drop > 0) + SV_ClientThink (cl, &oldcmd); + + } + SV_ClientThink (cl, &newcmd); + } + + cl->lastcmd = newcmd; + break; + + case clc_stringcmd: + s = MSG_ReadString (&net_message); + + // malicious users may try using too many string commands + if (++stringCmdCount < MAX_STRINGCMDS) + SV_ExecuteUserCommand (s); + + if (cl->state == cs_zombie) + return; // disconnect command + break; + } + } +} + diff --git a/server/sv_world.c b/server/sv_world.c new file mode 100644 index 000000000..ded791ef5 --- /dev/null +++ b/server/sv_world.c @@ -0,0 +1,659 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// world.c -- world query functions + +#include "server.h" + +/* +=============================================================================== + +ENTITY AREA CHECKING + +FIXME: this use of "area" is different from the bsp file use +=============================================================================== +*/ + +// (type *)STRUCT_FROM_LINK(link_t *link, type, member) +// ent = STRUCT_FROM_LINK(link,entity_t,order) +// FIXME: remove this mess! +#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) + +#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) + +typedef struct areanode_s +{ + int axis; // -1 = leaf node + float dist; + struct areanode_s *children[2]; + link_t trigger_edicts; + link_t solid_edicts; +} areanode_t; + +#define AREA_DEPTH 4 +#define AREA_NODES 32 + +areanode_t sv_areanodes[AREA_NODES]; +int sv_numareanodes; + +float *area_mins, *area_maxs; +edict_t **area_list; +int area_count, area_maxcount; +int area_type; + +int SV_HullForEntity (edict_t *ent); + + +// ClearLink is used for new headnodes +void ClearLink (link_t *l) +{ + l->prev = l->next = l; +} + +void RemoveLink (link_t *l) +{ + l->next->prev = l->prev; + l->prev->next = l->next; +} + +void InsertLinkBefore (link_t *l, link_t *before) +{ + l->next = before; + l->prev = before->prev; + l->prev->next = l; + l->next->prev = l; +} + +/* +=============== +SV_CreateAreaNode + +Builds a uniformly subdivided tree for the given world size +=============== +*/ +areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) +{ + areanode_t *anode; + vec3_t size; + vec3_t mins1, maxs1, mins2, maxs2; + + anode = &sv_areanodes[sv_numareanodes]; + sv_numareanodes++; + + ClearLink (&anode->trigger_edicts); + ClearLink (&anode->solid_edicts); + + if (depth == AREA_DEPTH) + { + anode->axis = -1; + anode->children[0] = anode->children[1] = NULL; + return anode; + } + + VectorSubtract (maxs, mins, size); + if (size[0] > size[1]) + anode->axis = 0; + else + anode->axis = 1; + + anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); + VectorCopy (mins, mins1); + VectorCopy (mins, mins2); + VectorCopy (maxs, maxs1); + VectorCopy (maxs, maxs2); + + maxs1[anode->axis] = mins2[anode->axis] = anode->dist; + + anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2); + anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1); + + return anode; +} + +/* +=============== +SV_ClearWorld + +=============== +*/ +void SV_ClearWorld (void) +{ + memset (sv_areanodes, 0, sizeof(sv_areanodes)); + sv_numareanodes = 0; + SV_CreateAreaNode (0, sv.models[1]->mins, sv.models[1]->maxs); +} + + +/* +=============== +SV_UnlinkEdict + +=============== +*/ +void SV_UnlinkEdict (edict_t *ent) +{ + if (!ent->area.prev) + return; // not linked in anywhere + RemoveLink (&ent->area); + ent->area.prev = ent->area.next = NULL; +} + + +/* +=============== +SV_LinkEdict + +=============== +*/ +#define MAX_TOTAL_ENT_LEAFS 128 +void SV_LinkEdict (edict_t *ent) +{ + areanode_t *node; + int leafs[MAX_TOTAL_ENT_LEAFS]; + int clusters[MAX_TOTAL_ENT_LEAFS]; + int num_leafs; + int i, j, k; + int area; + int topnode; + + if (ent->area.prev) + SV_UnlinkEdict (ent); // unlink from old position + + if (ent == ge->edicts) + return; // don't add the world + + if (!ent->inuse) + return; + + // set the size + VectorSubtract (ent->maxs, ent->mins, ent->size); + + // encode the size into the entity_state for client prediction + if (ent->solid == SOLID_BBOX && !(ent->svflags & SVF_DEADMONSTER)) + { // assume that x/y are equal and symetric + i = ent->maxs[0]/8; + if (i<1) + i = 1; + if (i>31) + i = 31; + + // z is not symetric + j = (-ent->mins[2])/8; + if (j<1) + j = 1; + if (j>31) + j = 31; + + // and z maxs can be negative... + k = (ent->maxs[2]+32)/8; + if (k<1) + k = 1; + if (k>63) + k = 63; + + ent->s.solid = (k<<10) | (j<<5) | i; + } + else if (ent->solid == SOLID_BSP) + { + ent->s.solid = 31; // a solid_bbox will never create this value + } + else + ent->s.solid = 0; + + // set the abs box + if (ent->solid == SOLID_BSP && + (ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2]) ) + { // expand for rotation + float max, v; + int i; + + max = 0; + for (i=0 ; i<3 ; i++) + { + v =fabs( ent->mins[i]); + if (v > max) + max = v; + v =fabs( ent->maxs[i]); + if (v > max) + max = v; + } + for (i=0 ; i<3 ; i++) + { + ent->absmin[i] = ent->s.origin[i] - max; + ent->absmax[i] = ent->s.origin[i] + max; + } + } + else + { // normal + VectorAdd (ent->s.origin, ent->mins, ent->absmin); + VectorAdd (ent->s.origin, ent->maxs, ent->absmax); + } + + // because movement is clipped an epsilon away from an actual edge, + // we must fully check even when bounding boxes don't quite touch + ent->absmin[0] -= 1; + ent->absmin[1] -= 1; + ent->absmin[2] -= 1; + ent->absmax[0] += 1; + ent->absmax[1] += 1; + ent->absmax[2] += 1; + +// link to PVS leafs + ent->num_clusters = 0; + ent->areanum = 0; + ent->areanum2 = 0; + + //get all leafs, including solids + num_leafs = CM_BoxLeafnums (ent->absmin, ent->absmax, + leafs, MAX_TOTAL_ENT_LEAFS, &topnode); + + // set areas + for (i=0 ; iareanum && ent->areanum != area) + { + if (ent->areanum2 && ent->areanum2 != area && sv.state == ss_loading) + Com_DPrintf ("Object touching 3 areas at %f %f %f\n", + ent->absmin[0], ent->absmin[1], ent->absmin[2]); + ent->areanum2 = area; + } + else + ent->areanum = area; + } + } + + if (num_leafs >= MAX_TOTAL_ENT_LEAFS) + { // assume we missed some leafs, and mark by headnode + ent->num_clusters = -1; + ent->headnode = topnode; + } + else + { + ent->num_clusters = 0; + for (i=0 ; inum_clusters == MAX_ENT_CLUSTERS) + { // assume we missed some leafs, and mark by headnode + ent->num_clusters = -1; + ent->headnode = topnode; + break; + } + + ent->clusternums[ent->num_clusters++] = clusters[i]; + } + } + } + + // if first time, make sure old_origin is valid + if (!ent->linkcount) + { + VectorCopy (ent->s.origin, ent->s.old_origin); + } + ent->linkcount++; + + if (ent->solid == SOLID_NOT) + return; + +// find the first node that the ent's box crosses + node = sv_areanodes; + while (1) + { + if (node->axis == -1) + break; + if (ent->absmin[node->axis] > node->dist) + node = node->children[0]; + else if (ent->absmax[node->axis] < node->dist) + node = node->children[1]; + else + break; // crosses the node + } + + // link it in + if (ent->solid == SOLID_TRIGGER) + InsertLinkBefore (&ent->area, &node->trigger_edicts); + else + InsertLinkBefore (&ent->area, &node->solid_edicts); + +} + + +/* +==================== +SV_AreaEdicts_r + +==================== +*/ +void SV_AreaEdicts_r (areanode_t *node) +{ + link_t *l, *next, *start; + edict_t *check; + int count; + + count = 0; + + // touch linked edicts + if (area_type == AREA_SOLID) + start = &node->solid_edicts; + else + start = &node->trigger_edicts; + + for (l=start->next ; l != start ; l = next) + { + next = l->next; + check = EDICT_FROM_AREA(l); + + if (check->solid == SOLID_NOT) + continue; // deactivated + if (check->absmin[0] > area_maxs[0] + || check->absmin[1] > area_maxs[1] + || check->absmin[2] > area_maxs[2] + || check->absmax[0] < area_mins[0] + || check->absmax[1] < area_mins[1] + || check->absmax[2] < area_mins[2]) + continue; // not touching + + if (area_count == area_maxcount) + { + Com_Printf ("SV_AreaEdicts: MAXCOUNT\n"); + return; + } + + area_list[area_count] = check; + area_count++; + } + + if (node->axis == -1) + return; // terminal node + + // recurse down both sides + if ( area_maxs[node->axis] > node->dist ) + SV_AreaEdicts_r ( node->children[0] ); + if ( area_mins[node->axis] < node->dist ) + SV_AreaEdicts_r ( node->children[1] ); +} + +/* +================ +SV_AreaEdicts +================ +*/ +int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, + int maxcount, int areatype) +{ + area_mins = mins; + area_maxs = maxs; + area_list = list; + area_count = 0; + area_maxcount = maxcount; + area_type = areatype; + + SV_AreaEdicts_r (sv_areanodes); + + return area_count; +} + + +//=========================================================================== + +/* +============= +SV_PointContents +============= +*/ +int SV_PointContents (vec3_t p) +{ + edict_t *touch[MAX_EDICTS], *hit; + int i, num; + int contents, c2; + int headnode; + float *angles; + + // get base contents from world + contents = CM_PointContents (p, sv.models[1]->headnode); + + // or in contents from all the other entities + num = SV_AreaEdicts (p, p, touch, MAX_EDICTS, AREA_SOLID); + + for (i=0 ; is.angles; + if (hit->solid != SOLID_BSP) + angles = vec3_origin; // boxes don't rotate + + c2 = CM_TransformedPointContents (p, headnode, hit->s.origin, hit->s.angles); + + contents |= c2; + } + + return contents; +} + + + +typedef struct +{ + vec3_t boxmins, boxmaxs;// enclose the test object along entire move + float *mins, *maxs; // size of the moving object + vec3_t mins2, maxs2; // size when clipping against mosnters + float *start, *end; + trace_t trace; + edict_t *passedict; + int contentmask; +} moveclip_t; + + + +/* +================ +SV_HullForEntity + +Returns a headnode that can be used for testing or clipping an +object of mins/maxs size. +Offset is filled in to contain the adjustment that must be added to the +testing object's origin to get a point to use with the returned hull. +================ +*/ +int SV_HullForEntity (edict_t *ent) +{ + cmodel_t *model; + +// decide which clipping hull to use, based on the size + if (ent->solid == SOLID_BSP) + { // explicit hulls in the BSP model + model = sv.models[ ent->s.modelindex ]; + + if (!model) + Com_Error (ERR_FATAL, "MOVETYPE_PUSH with a non bsp model"); + + return model->headnode; + } + + // create a temp hull from bounding box sizes + + return CM_HeadnodeForBox (ent->mins, ent->maxs); +} + + +//=========================================================================== + +/* +==================== +SV_ClipMoveToEntities + +==================== +*/ +void SV_ClipMoveToEntities ( moveclip_t *clip ) +{ + int i, num; + edict_t *touchlist[MAX_EDICTS], *touch; + trace_t trace; + int headnode; + float *angles; + + num = SV_AreaEdicts (clip->boxmins, clip->boxmaxs, touchlist + , MAX_EDICTS, AREA_SOLID); + + // be careful, it is possible to have an entity in this + // list removed before we get to it (killtriggered) + for (i=0 ; isolid == SOLID_NOT) + continue; + if (touch == clip->passedict) + continue; + if (clip->trace.allsolid) + return; + if (clip->passedict) + { + if (touch->owner == clip->passedict) + continue; // don't clip against own missiles + if (clip->passedict->owner == touch) + continue; // don't clip against owner + } + + if ( !(clip->contentmask & CONTENTS_DEADMONSTER) + && (touch->svflags & SVF_DEADMONSTER) ) + continue; + + // might intersect, so do an exact clip + headnode = SV_HullForEntity (touch); + angles = touch->s.angles; + if (touch->solid != SOLID_BSP) + angles = vec3_origin; // boxes don't rotate + + if (touch->svflags & SVF_MONSTER) + trace = CM_TransformedBoxTrace (clip->start, clip->end, + clip->mins2, clip->maxs2, headnode, clip->contentmask, + touch->s.origin, angles); + else + trace = CM_TransformedBoxTrace (clip->start, clip->end, + clip->mins, clip->maxs, headnode, clip->contentmask, + touch->s.origin, angles); + + if (trace.allsolid || trace.startsolid || + trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + if (clip->trace.startsolid) + { + clip->trace = trace; + clip->trace.startsolid = true; + } + else + clip->trace = trace; + } + else if (trace.startsolid) + clip->trace.startsolid = true; + } +} + + +/* +================== +SV_TraceBounds +================== +*/ +void SV_TraceBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs) +{ +#if 0 +// debug to test against everything +boxmins[0] = boxmins[1] = boxmins[2] = -9999; +boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999; +#else + int i; + + for (i=0 ; i<3 ; i++) + { + if (end[i] > start[i]) + { + boxmins[i] = start[i] + mins[i] - 1; + boxmaxs[i] = end[i] + maxs[i] + 1; + } + else + { + boxmins[i] = end[i] + mins[i] - 1; + boxmaxs[i] = start[i] + maxs[i] + 1; + } + } +#endif +} + +/* +================== +SV_Trace + +Moves the given mins/maxs volume through the world from start to end. + +Passedict and edicts owned by passedict are explicitly not checked. + +================== +*/ +trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask) +{ + moveclip_t clip; + + if (!mins) + mins = vec3_origin; + if (!maxs) + maxs = vec3_origin; + + memset ( &clip, 0, sizeof ( moveclip_t ) ); + + // clip to world + clip.trace = CM_BoxTrace (start, end, mins, maxs, 0, contentmask); + clip.trace.ent = ge->edicts; + if (clip.trace.fraction == 0) + return clip.trace; // blocked by the world + + clip.contentmask = contentmask; + clip.start = start; + clip.end = end; + clip.mins = mins; + clip.maxs = maxs; + clip.passedict = passedict; + + VectorCopy (mins, clip.mins2); + VectorCopy (maxs, clip.maxs2); + + // create the bounding box of the entire move + SV_TraceBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); + + // clip to other solid entities + SV_ClipMoveToEntities ( &clip ); + + return clip.trace; +} + diff --git a/solaris/Makefile.OLD b/solaris/Makefile.OLD new file mode 100644 index 000000000..a3030e780 --- /dev/null +++ b/solaris/Makefile.OLD @@ -0,0 +1,478 @@ +# +# Quake2 Makefile for Solaris +# +# Jan '98 by Zoid +# + +ifneq (,$(findstring i86pc,$(shell uname -m))) +ARCH=i386 +else +ARCH=sparc +endif + +MOUNT_DIR=/chest/Quake2/code + +BUILD_DEBUG_DIR=debug$(ARCH) +BUILD_RELEASE_DIR=release$(ARCH) +CLIENT_DIR=$(MOUNT_DIR)/client +SERVER_DIR=$(MOUNT_DIR)/server +COMMON_DIR=$(MOUNT_DIR)/qcommon +SOLARIS_DIR=$(MOUNT_DIR)/solaris +GAME_DIR=$(MOUNT_DIR)/game +XATRIX_DIR=$(MOUNT_DIR)/xatrix +CTF_DIR=$(MOUNT_DIR)/game +NULL_DIR=$(MOUNT_DIR)/null + +ARCH=i386 + +CC=gcc +BASE_CFLAGS=-Dstricmp=strcasecmp +RELEASE_CFLAGS=$(BASE_CFLAGS) -O6 -fomit-frame-pointer -fno-strength-reduce -funroll-loops -fexpensive-optimizations +DEBUG_CFLAGS=$(BASE_CFLAGS) -g +LDFLAGS=-ldl -lm -lnsl -lsocket + +SHLIBEXT=so + +SHLIBCFLAGS=-fPIC +SHLIBLDFLAGS=-G + +DO_CC=$(CC) $(CFLAGS) -o $@ -c $< +DO_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $< + +############################################################################# +# SETUP AND BUILD +############################################################################# + +TARGETS=$(BUILDDIR)/quake2 $(BUILDDIR)/game$(ARCH).$(SHLIBEXT) + +build_debug: + @-mkdir $(BUILD_DEBUG_DIR) \ + $(BUILD_DEBUG_DIR)/client \ + $(BUILD_DEBUG_DIR)/game + $(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +build_release: + @-mkdir $(BUILD_RELEASE_DIR) \ + $(BUILD_RELEASE_DIR)/client \ + $(BUILD_RELEASE_DIR)/game + $(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)" + +all: build_debug build_release + +targets: $(TARGETS) + +############################################################################# +# CLIENT/SERVER +############################################################################# + +QUAKE2_OBJS = \ + $(BUILDDIR)/client/cl_cin.o \ + $(BUILDDIR)/client/cl_ents.o \ + $(BUILDDIR)/client/cl_fx.o \ + $(BUILDDIR)/client/cl_input.o \ + $(BUILDDIR)/client/cl_inv.o \ + $(BUILDDIR)/client/cl_main.o \ + $(BUILDDIR)/client/cl_parse.o \ + $(BUILDDIR)/client/cl_pred.o \ + $(BUILDDIR)/client/cl_tent.o \ + $(BUILDDIR)/client/cl_scrn.o \ + $(BUILDDIR)/client/cl_view.o \ + $(BUILDDIR)/client/console.o \ + $(BUILDDIR)/client/keys.o \ + $(BUILDDIR)/client/menu.o \ + $(BUILDDIR)/client/qmenu.o \ + $(BUILDDIR)/client/m_flash.o \ + \ + $(BUILDDIR)/client/cmd.o \ + $(BUILDDIR)/client/cmodel.o \ + $(BUILDDIR)/client/common.o \ + $(BUILDDIR)/client/cvar.o \ + $(BUILDDIR)/client/files.o \ + $(BUILDDIR)/client/md4.o \ + $(BUILDDIR)/client/net_chan.o \ + \ + $(BUILDDIR)/client/sv_ccmds.o \ + $(BUILDDIR)/client/sv_ents.o \ + $(BUILDDIR)/client/sv_game.o \ + $(BUILDDIR)/client/sv_init.o \ + $(BUILDDIR)/client/sv_main.o \ + $(BUILDDIR)/client/sv_send.o \ + $(BUILDDIR)/client/sv_user.o \ + $(BUILDDIR)/client/sv_world.o \ + \ + $(BUILDDIR)/client/snd_dma.o \ + $(BUILDDIR)/client/snd_mem.o \ + $(BUILDDIR)/client/snd_mix.o \ + \ + $(BUILDDIR)/client/cd_null.o \ + $(BUILDDIR)/client/q_shsolaris.o \ + $(BUILDDIR)/client/vid_null.o \ + $(BUILDDIR)/client/ref_null.o \ + $(BUILDDIR)/client/in_null.o \ + $(BUILDDIR)/client/snddma_null.o \ + $(BUILDDIR)/client/sys_solaris.o \ + $(BUILDDIR)/client/glob.o \ + $(BUILDDIR)/client/net_udp.o \ + \ + $(BUILDDIR)/client/q_shared.o \ + $(BUILDDIR)/client/pmove.o + +$(BUILDDIR)/quake2 : $(QUAKE2_OBJS) + $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(LDFLAGS) + +$(BUILDDIR)/client/cl_cin.o : $(CLIENT_DIR)/cl_cin.c + $(DO_CC) + +$(BUILDDIR)/client/cl_ents.o : $(CLIENT_DIR)/cl_ents.c + $(DO_CC) + +$(BUILDDIR)/client/cl_fx.o : $(CLIENT_DIR)/cl_fx.c + $(DO_CC) + +$(BUILDDIR)/client/cl_input.o : $(CLIENT_DIR)/cl_input.c + $(DO_CC) + +$(BUILDDIR)/client/cl_inv.o : $(CLIENT_DIR)/cl_inv.c + $(DO_CC) + +$(BUILDDIR)/client/cl_main.o : $(CLIENT_DIR)/cl_main.c + $(DO_CC) + +$(BUILDDIR)/client/cl_parse.o : $(CLIENT_DIR)/cl_parse.c + $(DO_CC) + +$(BUILDDIR)/client/cl_pred.o : $(CLIENT_DIR)/cl_pred.c + $(DO_CC) + +$(BUILDDIR)/client/cl_tent.o : $(CLIENT_DIR)/cl_tent.c + $(DO_CC) + +$(BUILDDIR)/client/cl_scrn.o : $(CLIENT_DIR)/cl_scrn.c + $(DO_CC) + +$(BUILDDIR)/client/cl_view.o : $(CLIENT_DIR)/cl_view.c + $(DO_CC) + +$(BUILDDIR)/client/console.o : $(CLIENT_DIR)/console.c + $(DO_CC) + +$(BUILDDIR)/client/keys.o : $(CLIENT_DIR)/keys.c + $(DO_CC) + +$(BUILDDIR)/client/menu.o : $(CLIENT_DIR)/menu.c + $(DO_CC) + +$(BUILDDIR)/client/qmenu.o : $(CLIENT_DIR)/qmenu.c + $(DO_CC) + +$(BUILDDIR)/client/m_flash.o : $(GAME_DIR)/m_flash.c + $(DO_CC) + +$(BUILDDIR)/client/cmd.o : $(COMMON_DIR)/cmd.c + $(DO_CC) + +$(BUILDDIR)/client/cmodel.o : $(COMMON_DIR)/cmodel.c + $(DO_CC) + +$(BUILDDIR)/client/common.o : $(COMMON_DIR)/common.c + $(DO_CC) + +$(BUILDDIR)/client/cvar.o : $(COMMON_DIR)/cvar.c + $(DO_CC) + +$(BUILDDIR)/client/files.o : $(COMMON_DIR)/files.c + $(DO_CC) + +$(BUILDDIR)/client/md4.o : $(COMMON_DIR)/md4.c + $(DO_CC) + +$(BUILDDIR)/client/net_chan.o : $(COMMON_DIR)/net_chan.c + $(DO_CC) + +$(BUILDDIR)/client/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_CC) + +$(BUILDDIR)/client/pmove.o : $(COMMON_DIR)/pmove.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ccmds.o : $(SERVER_DIR)/sv_ccmds.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ents.o : $(SERVER_DIR)/sv_ents.c + $(DO_CC) + +$(BUILDDIR)/client/sv_game.o : $(SERVER_DIR)/sv_game.c + $(DO_CC) + +$(BUILDDIR)/client/sv_init.o : $(SERVER_DIR)/sv_init.c + $(DO_CC) + +$(BUILDDIR)/client/sv_main.o : $(SERVER_DIR)/sv_main.c + $(DO_CC) + +$(BUILDDIR)/client/sv_send.o : $(SERVER_DIR)/sv_send.c + $(DO_CC) + +$(BUILDDIR)/client/sv_user.o : $(SERVER_DIR)/sv_user.c + $(DO_CC) + +$(BUILDDIR)/client/sv_world.o : $(SERVER_DIR)/sv_world.c + $(DO_CC) + +$(BUILDDIR)/client/cd_null.o : $(NULL_DIR)/cd_null.c + $(DO_CC) + +$(BUILDDIR)/client/q_shsolaris.o : $(SOLARIS_DIR)/q_shsolaris.c + $(DO_CC) + +$(BUILDDIR)/client/vid_null.o : $(NULL_DIR)/vid_null.c + $(DO_CC) + +$(BUILDDIR)/client/ref_null.o : $(NULL_DIR)/ref_null.c + $(DO_CC) + +$(BUILDDIR)/client/snddma_null.o : $(NULL_DIR)/snddma_null.c + $(DO_CC) + +$(BUILDDIR)/client/snd_dma.o : $(CLIENT_DIR)/snd_dma.c + $(DO_CC) + +$(BUILDDIR)/client/snd_mem.o : $(CLIENT_DIR)/snd_mem.c + $(DO_CC) + +$(BUILDDIR)/client/snd_mix.o : $(CLIENT_DIR)/snd_mix.c + $(DO_CC) + +$(BUILDDIR)/client/in_null.o : $(NULL_DIR)/in_null.c + $(DO_CC) + +$(BUILDDIR)/client/sys_solaris.o : $(SOLARIS_DIR)/sys_solaris.c + $(DO_CC) + +$(BUILDDIR)/client/glob.o : $(SOLARIS_DIR)/glob.c + $(DO_CC) + +$(BUILDDIR)/client/net_udp.o : $(SOLARIS_DIR)/net_udp.c + $(DO_CC) + +############################################################################# +# GAME +############################################################################# + +GAME_OBJS = \ + $(BUILDDIR)/game/g_ai.o \ + $(BUILDDIR)/game/p_client.o \ + $(BUILDDIR)/game/g_cmds.o \ + $(BUILDDIR)/game/g_svcmds.o \ + $(BUILDDIR)/game/g_combat.o \ + $(BUILDDIR)/game/g_func.o \ + $(BUILDDIR)/game/g_items.o \ + $(BUILDDIR)/game/g_main.o \ + $(BUILDDIR)/game/g_misc.o \ + $(BUILDDIR)/game/g_monster.o \ + $(BUILDDIR)/game/g_phys.o \ + $(BUILDDIR)/game/g_save.o \ + $(BUILDDIR)/game/g_spawn.o \ + $(BUILDDIR)/game/g_target.o \ + $(BUILDDIR)/game/g_trigger.o \ + $(BUILDDIR)/game/g_turret.o \ + $(BUILDDIR)/game/g_utils.o \ + $(BUILDDIR)/game/g_weapon.o \ + $(BUILDDIR)/game/m_actor.o \ + $(BUILDDIR)/game/m_berserk.o \ + $(BUILDDIR)/game/m_boss2.o \ + $(BUILDDIR)/game/m_boss3.o \ + $(BUILDDIR)/game/m_boss31.o \ + $(BUILDDIR)/game/m_boss32.o \ + $(BUILDDIR)/game/m_brain.o \ + $(BUILDDIR)/game/m_chick.o \ + $(BUILDDIR)/game/m_flipper.o \ + $(BUILDDIR)/game/m_float.o \ + $(BUILDDIR)/game/m_flyer.o \ + $(BUILDDIR)/game/m_gladiator.o \ + $(BUILDDIR)/game/m_gunner.o \ + $(BUILDDIR)/game/m_hover.o \ + $(BUILDDIR)/game/m_infantry.o \ + $(BUILDDIR)/game/m_insane.o \ + $(BUILDDIR)/game/m_medic.o \ + $(BUILDDIR)/game/m_move.o \ + $(BUILDDIR)/game/m_mutant.o \ + $(BUILDDIR)/game/m_parasite.o \ + $(BUILDDIR)/game/m_soldier.o \ + $(BUILDDIR)/game/m_supertank.o \ + $(BUILDDIR)/game/m_tank.o \ + $(BUILDDIR)/game/p_hud.o \ + $(BUILDDIR)/game/p_trail.o \ + $(BUILDDIR)/game/p_view.o \ + $(BUILDDIR)/game/p_weapon.o \ + $(BUILDDIR)/game/q_shared.o \ + $(BUILDDIR)/game/m_flash.o \ + $(BUILDDIR)/game/g_so.o + +$(BUILDDIR)/game$(ARCH).$(SHLIBEXT) : $(GAME_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(GAME_OBJS) + +$(BUILDDIR)/game/g_ai.o : $(GAME_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_client.o : $(GAME_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_cmds.o : $(GAME_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_svcmds.o : $(GAME_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_combat.o : $(GAME_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_func.o : $(GAME_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_items.o : $(GAME_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_main.o : $(GAME_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_misc.o : $(GAME_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_monster.o : $(GAME_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_phys.o : $(GAME_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_save.o : $(GAME_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_spawn.o : $(GAME_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_target.o : $(GAME_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_trigger.o : $(GAME_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_turret.o : $(GAME_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_utils.o : $(GAME_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_weapon.o : $(GAME_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_actor.o : $(GAME_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_berserk.o : $(GAME_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss2.o : $(GAME_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss3.o : $(GAME_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss31.o : $(GAME_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss32.o : $(GAME_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_brain.o : $(GAME_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_chick.o : $(GAME_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flipper.o : $(GAME_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_float.o : $(GAME_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flyer.o : $(GAME_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gladiator.o : $(GAME_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gunner.o : $(GAME_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_hover.o : $(GAME_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_infantry.o : $(GAME_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_insane.o : $(GAME_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_medic.o : $(GAME_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_move.o : $(GAME_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_mutant.o : $(GAME_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_parasite.o : $(GAME_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_soldier.o : $(GAME_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_supertank.o : $(GAME_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_tank.o : $(GAME_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_hud.o : $(GAME_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_trail.o : $(GAME_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_view.o : $(GAME_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_weapon.o : $(GAME_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flash.o : $(GAME_DIR)/m_flash.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_so.o : $(SOLARIS_DIR)/g_so.c + $(DO_SHLIB_CC) + +############################################################################# +# MISC +############################################################################# + +clean: clean-debug clean-release + +clean-debug: + $(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean-release: + $(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean2: + -rm -f $(QUAKE2_OBJS) \ + $(GAME_OBJS) \ + $(REF_SOFT_OBJS) \ + $(REF_SOFT_SVGA_OBJS) \ + $(REF_SOFT_X11_OBJS) \ + $(REF_GL_OBJS) + diff --git a/solaris/Makefile.Solaris b/solaris/Makefile.Solaris new file mode 100644 index 000000000..de900564f --- /dev/null +++ b/solaris/Makefile.Solaris @@ -0,0 +1,719 @@ +# +# Quake2 Makefile for Solaris +# +# Nov '97 by Zoid +# +# ELF only +# + +ifneq (,$(findstring i86pc,$(shell uname -m))) +ARCH=i386 +else +ARCH=sparc +endif + +MOUNT_DIR=/chest/Quake2/code + +BUILD_DEBUG_DIR=debug$(ARCH) +BUILD_RELEASE_DIR=release$(ARCH) +CLIENT_DIR=$(MOUNT_DIR)/client +SERVER_DIR=$(MOUNT_DIR)/server +COMMON_DIR=$(MOUNT_DIR)/qcommon +SOLARIS_DIR=$(MOUNT_DIR)/solaris +GAME_DIR=$(MOUNT_DIR)/game +CTF_DIR=$(MOUNT_DIR)/ctf +XATRIX_DIR=$(MOUNT_DIR)/xatrix +NULL_DIR=$(MOUNT_DIR)/null + +CC=gcc +BASE_CFLAGS=-Dstricmp=strcasecmp -DC_ONLY -DDEDICATED_ONLY +RELEASE_CFLAGS=$(BASE_CFLAGS) -ffast-math -funroll-loops \ + -fomit-frame-pointer -fexpensive-optimizations + +DEBUG_CFLAGS=$(BASE_CFLAGS) -g +LDFLAGS=-ldl -lm -lsocket -lnsl + +SHLIBEXT=so + +SHLIBCFLAGS=-fPIC +SHLIBLDFLAGS=-shared + +DO_CC=$(CC) $(CFLAGS) -o $@ -c $< +DO_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $< + +############################################################################# +# SETUP AND BUILD +############################################################################# + +TARGETS=$(BUILDDIR)/q2ded \ + $(BUILDDIR)/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) + +build_debug: + @-mkdir $(BUILD_DEBUG_DIR) \ + $(BUILD_DEBUG_DIR)/client \ + $(BUILD_DEBUG_DIR)/game \ + $(BUILD_DEBUG_DIR)/ctf \ + $(BUILD_DEBUG_DIR)/xatrix + $(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +build_release: + @-mkdir $(BUILD_RELEASE_DIR) \ + $(BUILD_RELEASE_DIR)/client \ + $(BUILD_RELEASE_DIR)/game \ + $(BUILD_RELEASE_DIR)/ctf \ + $(BUILD_RELEASE_DIR)/xatrix + $(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)" + +all: build_debug build_release + +targets: $(TARGETS) + +############################################################################# +# CLIENT/SERVER +############################################################################# + +QUAKE2_OBJS = \ + \ + $(BUILDDIR)/client/cmd.o \ + $(BUILDDIR)/client/cmodel.o \ + $(BUILDDIR)/client/common.o \ + $(BUILDDIR)/client/crc.o \ + $(BUILDDIR)/client/cvar.o \ + $(BUILDDIR)/client/files.o \ + $(BUILDDIR)/client/md4.o \ + $(BUILDDIR)/client/net_chan.o \ + \ + $(BUILDDIR)/client/sv_ccmds.o \ + $(BUILDDIR)/client/sv_ents.o \ + $(BUILDDIR)/client/sv_game.o \ + $(BUILDDIR)/client/sv_init.o \ + $(BUILDDIR)/client/sv_main.o \ + $(BUILDDIR)/client/sv_send.o \ + $(BUILDDIR)/client/sv_user.o \ + $(BUILDDIR)/client/sv_world.o \ + \ + $(BUILDDIR)/client/q_shsolaris.o \ + $(BUILDDIR)/client/sys_solaris.o \ + $(BUILDDIR)/client/glob.o \ + $(BUILDDIR)/client/net_udp.o \ + \ + $(BUILDDIR)/client/q_shared.o \ + $(BUILDDIR)/client/pmove.o \ + \ + $(BUILDDIR)/client/cl_null.o \ + $(BUILDDIR)/client/cd_null.o + +$(BUILDDIR)/q2ded : $(QUAKE2_OBJS) + $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(LDFLAGS) + +$(BUILDDIR)/client/cmd.o : $(COMMON_DIR)/cmd.c + $(DO_CC) + +$(BUILDDIR)/client/cmodel.o : $(COMMON_DIR)/cmodel.c + $(DO_CC) + +$(BUILDDIR)/client/common.o : $(COMMON_DIR)/common.c + $(DO_CC) + +$(BUILDDIR)/client/crc.o : $(COMMON_DIR)/crc.c + $(DO_CC) + +$(BUILDDIR)/client/cvar.o : $(COMMON_DIR)/cvar.c + $(DO_CC) + +$(BUILDDIR)/client/files.o : $(COMMON_DIR)/files.c + $(DO_CC) + +$(BUILDDIR)/client/md4.o : $(COMMON_DIR)/md4.c + $(DO_CC) + +$(BUILDDIR)/client/net_chan.o : $(COMMON_DIR)/net_chan.c + $(DO_CC) + +$(BUILDDIR)/client/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_CC) + +$(BUILDDIR)/client/pmove.o : $(COMMON_DIR)/pmove.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ccmds.o : $(SERVER_DIR)/sv_ccmds.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ents.o : $(SERVER_DIR)/sv_ents.c + $(DO_CC) + +$(BUILDDIR)/client/sv_game.o : $(SERVER_DIR)/sv_game.c + $(DO_CC) + +$(BUILDDIR)/client/sv_init.o : $(SERVER_DIR)/sv_init.c + $(DO_CC) + +$(BUILDDIR)/client/sv_main.o : $(SERVER_DIR)/sv_main.c + $(DO_CC) + +$(BUILDDIR)/client/sv_send.o : $(SERVER_DIR)/sv_send.c + $(DO_CC) + +$(BUILDDIR)/client/sv_user.o : $(SERVER_DIR)/sv_user.c + $(DO_CC) + +$(BUILDDIR)/client/sv_world.o : $(SERVER_DIR)/sv_world.c + $(DO_CC) + +$(BUILDDIR)/client/q_shsolaris.o : $(SOLARIS_DIR)/q_shsolaris.c + $(DO_CC) + +$(BUILDDIR)/client/sys_solaris.o : $(SOLARIS_DIR)/sys_solaris.c + $(DO_CC) + +$(BUILDDIR)/client/glob.o : $(SOLARIS_DIR)/glob.c + $(DO_CC) + +$(BUILDDIR)/client/net_udp.o : $(SOLARIS_DIR)/net_udp.c + $(DO_CC) + +$(BUILDDIR)/client/cd_null.o : $(NULL_DIR)/cd_null.c + $(DO_CC) + +$(BUILDDIR)/client/cl_null.o : $(NULL_DIR)/cl_null.c + $(DO_CC) + +############################################################################# +# GAME +############################################################################# + +GAME_OBJS = \ + $(BUILDDIR)/game/g_ai.o \ + $(BUILDDIR)/game/p_client.o \ + $(BUILDDIR)/game/g_cmds.o \ + $(BUILDDIR)/game/g_svcmds.o \ + $(BUILDDIR)/game/g_combat.o \ + $(BUILDDIR)/game/g_func.o \ + $(BUILDDIR)/game/g_items.o \ + $(BUILDDIR)/game/g_main.o \ + $(BUILDDIR)/game/g_misc.o \ + $(BUILDDIR)/game/g_monster.o \ + $(BUILDDIR)/game/g_phys.o \ + $(BUILDDIR)/game/g_save.o \ + $(BUILDDIR)/game/g_spawn.o \ + $(BUILDDIR)/game/g_target.o \ + $(BUILDDIR)/game/g_trigger.o \ + $(BUILDDIR)/game/g_turret.o \ + $(BUILDDIR)/game/g_utils.o \ + $(BUILDDIR)/game/g_weapon.o \ + $(BUILDDIR)/game/m_actor.o \ + $(BUILDDIR)/game/m_berserk.o \ + $(BUILDDIR)/game/m_boss2.o \ + $(BUILDDIR)/game/m_boss3.o \ + $(BUILDDIR)/game/m_boss31.o \ + $(BUILDDIR)/game/m_boss32.o \ + $(BUILDDIR)/game/m_brain.o \ + $(BUILDDIR)/game/m_chick.o \ + $(BUILDDIR)/game/m_flipper.o \ + $(BUILDDIR)/game/m_float.o \ + $(BUILDDIR)/game/m_flyer.o \ + $(BUILDDIR)/game/m_gladiator.o \ + $(BUILDDIR)/game/m_gunner.o \ + $(BUILDDIR)/game/m_hover.o \ + $(BUILDDIR)/game/m_infantry.o \ + $(BUILDDIR)/game/m_insane.o \ + $(BUILDDIR)/game/m_medic.o \ + $(BUILDDIR)/game/m_move.o \ + $(BUILDDIR)/game/m_mutant.o \ + $(BUILDDIR)/game/m_parasite.o \ + $(BUILDDIR)/game/m_soldier.o \ + $(BUILDDIR)/game/m_supertank.o \ + $(BUILDDIR)/game/m_tank.o \ + $(BUILDDIR)/game/p_hud.o \ + $(BUILDDIR)/game/p_trail.o \ + $(BUILDDIR)/game/p_view.o \ + $(BUILDDIR)/game/p_weapon.o \ + $(BUILDDIR)/game/q_shared.o \ + $(BUILDDIR)/game/m_flash.o + +$(BUILDDIR)/game$(ARCH).$(SHLIBEXT) : $(GAME_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(GAME_OBJS) + +$(BUILDDIR)/game/g_ai.o : $(GAME_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_client.o : $(GAME_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_cmds.o : $(GAME_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_svcmds.o : $(GAME_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_combat.o : $(GAME_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_func.o : $(GAME_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_items.o : $(GAME_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_main.o : $(GAME_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_misc.o : $(GAME_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_monster.o : $(GAME_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_phys.o : $(GAME_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_save.o : $(GAME_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_spawn.o : $(GAME_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_target.o : $(GAME_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_trigger.o : $(GAME_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_turret.o : $(GAME_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_utils.o : $(GAME_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_weapon.o : $(GAME_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_actor.o : $(GAME_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_berserk.o : $(GAME_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss2.o : $(GAME_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss3.o : $(GAME_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss31.o : $(GAME_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss32.o : $(GAME_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_brain.o : $(GAME_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_chick.o : $(GAME_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flipper.o : $(GAME_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_float.o : $(GAME_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flyer.o : $(GAME_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gladiator.o : $(GAME_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gunner.o : $(GAME_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_hover.o : $(GAME_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_infantry.o : $(GAME_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_insane.o : $(GAME_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_medic.o : $(GAME_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_move.o : $(GAME_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_mutant.o : $(GAME_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_parasite.o : $(GAME_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_soldier.o : $(GAME_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_supertank.o : $(GAME_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_tank.o : $(GAME_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_hud.o : $(GAME_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_trail.o : $(GAME_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_view.o : $(GAME_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_weapon.o : $(GAME_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flash.o : $(GAME_DIR)/m_flash.c + $(DO_SHLIB_CC) + +############################################################################# +# CTF +############################################################################# + +CTF_OBJS = \ + $(BUILDDIR)/ctf/g_ai.o \ + $(BUILDDIR)/ctf/g_chase.o \ + $(BUILDDIR)/ctf/g_cmds.o \ + $(BUILDDIR)/ctf/g_combat.o \ + $(BUILDDIR)/ctf/g_ctf.o \ + $(BUILDDIR)/ctf/g_func.o \ + $(BUILDDIR)/ctf/g_items.o \ + $(BUILDDIR)/ctf/g_main.o \ + $(BUILDDIR)/ctf/g_misc.o \ + $(BUILDDIR)/ctf/g_monster.o \ + $(BUILDDIR)/ctf/g_phys.o \ + $(BUILDDIR)/ctf/g_save.o \ + $(BUILDDIR)/ctf/g_spawn.o \ + $(BUILDDIR)/ctf/g_svcmds.o \ + $(BUILDDIR)/ctf/g_target.o \ + $(BUILDDIR)/ctf/g_trigger.o \ + $(BUILDDIR)/ctf/g_utils.o \ + $(BUILDDIR)/ctf/g_weapon.o \ + $(BUILDDIR)/ctf/m_move.o \ + $(BUILDDIR)/ctf/p_client.o \ + $(BUILDDIR)/ctf/p_hud.o \ + $(BUILDDIR)/ctf/p_menu.o \ + $(BUILDDIR)/ctf/p_trail.o \ + $(BUILDDIR)/ctf/p_view.o \ + $(BUILDDIR)/ctf/p_weapon.o \ + $(BUILDDIR)/ctf/q_shared.o + +$(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) : $(CTF_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(CTF_OBJS) + +$(BUILDDIR)/ctf/g_ai.o : $(CTF_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_chase.o : $(CTF_DIR)/g_chase.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_cmds.o : $(CTF_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_combat.o : $(CTF_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_ctf.o : $(CTF_DIR)/g_ctf.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_func.o : $(CTF_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_items.o : $(CTF_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_main.o : $(CTF_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_misc.o : $(CTF_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_monster.o : $(CTF_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_phys.o : $(CTF_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_save.o : $(CTF_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_spawn.o : $(CTF_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_svcmds.o : $(CTF_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_target.o : $(CTF_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_trigger.o : $(CTF_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_utils.o : $(CTF_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_weapon.o : $(CTF_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/m_move.o : $(CTF_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_client.o : $(CTF_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_hud.o : $(CTF_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_menu.o : $(CTF_DIR)/p_menu.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_trail.o : $(CTF_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_view.o : $(CTF_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_weapon.o : $(CTF_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/q_shared.o : $(CTF_DIR)/q_shared.c + $(DO_SHLIB_CC) + +############################################################################# +# XATRIX +############################################################################# + +XATRIX_OBJS = \ + $(BUILDDIR)/xatrix/g_ai.o \ + $(BUILDDIR)/xatrix/g_cmds.o \ + $(BUILDDIR)/xatrix/g_combat.o \ + $(BUILDDIR)/xatrix/g_func.o \ + $(BUILDDIR)/xatrix/g_items.o \ + $(BUILDDIR)/xatrix/g_main.o \ + $(BUILDDIR)/xatrix/g_misc.o \ + $(BUILDDIR)/xatrix/g_monster.o \ + $(BUILDDIR)/xatrix/g_phys.o \ + $(BUILDDIR)/xatrix/g_save.o \ + $(BUILDDIR)/xatrix/g_spawn.o \ + $(BUILDDIR)/xatrix/g_svcmds.o \ + $(BUILDDIR)/xatrix/g_target.o \ + $(BUILDDIR)/xatrix/g_trigger.o \ + $(BUILDDIR)/xatrix/g_turret.o \ + $(BUILDDIR)/xatrix/g_utils.o \ + $(BUILDDIR)/xatrix/g_weapon.o \ + $(BUILDDIR)/xatrix/m_actor.o \ + $(BUILDDIR)/xatrix/m_berserk.o \ + $(BUILDDIR)/xatrix/m_boss2.o \ + $(BUILDDIR)/xatrix/m_boss3.o \ + $(BUILDDIR)/xatrix/m_boss31.o \ + $(BUILDDIR)/xatrix/m_boss32.o \ + $(BUILDDIR)/xatrix/m_boss5.o \ + $(BUILDDIR)/xatrix/m_brain.o \ + $(BUILDDIR)/xatrix/m_chick.o \ + $(BUILDDIR)/xatrix/m_fixbot.o \ + $(BUILDDIR)/xatrix/m_flash.o \ + $(BUILDDIR)/xatrix/m_flipper.o \ + $(BUILDDIR)/xatrix/m_float.o \ + $(BUILDDIR)/xatrix/m_flyer.o \ + $(BUILDDIR)/xatrix/m_gekk.o \ + $(BUILDDIR)/xatrix/m_gladb.o \ + $(BUILDDIR)/xatrix/m_gladiator.o \ + $(BUILDDIR)/xatrix/m_gunner.o \ + $(BUILDDIR)/xatrix/m_hover.o \ + $(BUILDDIR)/xatrix/m_infantry.o \ + $(BUILDDIR)/xatrix/m_insane.o \ + $(BUILDDIR)/xatrix/m_medic.o \ + $(BUILDDIR)/xatrix/m_move.o \ + $(BUILDDIR)/xatrix/m_mutant.o \ + $(BUILDDIR)/xatrix/m_parasite.o \ + $(BUILDDIR)/xatrix/m_soldier.o \ + $(BUILDDIR)/xatrix/m_supertank.o \ + $(BUILDDIR)/xatrix/m_tank.o \ + $(BUILDDIR)/xatrix/p_client.o \ + $(BUILDDIR)/xatrix/p_hud.o \ + $(BUILDDIR)/xatrix/p_trail.o \ + $(BUILDDIR)/xatrix/p_view.o \ + $(BUILDDIR)/xatrix/p_weapon.o \ + $(BUILDDIR)/xatrix/q_shared.o + +$(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) : $(XATRIX_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(XATRIX_OBJS) + +$(BUILDDIR)/xatrix/g_ai.o : $(XATRIX_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_cmds.o : $(XATRIX_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_combat.o : $(XATRIX_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_func.o : $(XATRIX_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_items.o : $(XATRIX_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_main.o : $(XATRIX_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_misc.o : $(XATRIX_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_monster.o : $(XATRIX_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_phys.o : $(XATRIX_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_save.o : $(XATRIX_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_spawn.o : $(XATRIX_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_svcmds.o : $(XATRIX_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_target.o : $(XATRIX_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_trigger.o : $(XATRIX_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_turret.o : $(XATRIX_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_utils.o : $(XATRIX_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_weapon.o : $(XATRIX_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_actor.o : $(XATRIX_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_berserk.o : $(XATRIX_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss2.o : $(XATRIX_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss3.o : $(XATRIX_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss31.o : $(XATRIX_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss32.o : $(XATRIX_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss5.o : $(XATRIX_DIR)/m_boss5.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_brain.o : $(XATRIX_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_chick.o : $(XATRIX_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_fixbot.o : $(XATRIX_DIR)/m_fixbot.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flash.o : $(XATRIX_DIR)/m_flash.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flipper.o : $(XATRIX_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_float.o : $(XATRIX_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flyer.o : $(XATRIX_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gekk.o : $(XATRIX_DIR)/m_gekk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gladb.o : $(XATRIX_DIR)/m_gladb.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gladiator.o : $(XATRIX_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gunner.o : $(XATRIX_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_hover.o : $(XATRIX_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_infantry.o : $(XATRIX_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_insane.o : $(XATRIX_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_medic.o : $(XATRIX_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_move.o : $(XATRIX_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_mutant.o : $(XATRIX_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_parasite.o : $(XATRIX_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_soldier.o : $(XATRIX_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_supertank.o : $(XATRIX_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_tank.o : $(XATRIX_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_client.o : $(XATRIX_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_hud.o : $(XATRIX_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_trail.o : $(XATRIX_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_view.o : $(XATRIX_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_weapon.o : $(XATRIX_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/q_shared.o : $(XATRIX_DIR)/q_shared.c + $(DO_SHLIB_CC) + +############################################################################# +# MISC +############################################################################# + +clean: clean-debug clean-release + +clean-debug: + $(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean-release: + $(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean2: + -rm -f $(QUAKE2_OBJS) $(GAME_OBJS) $(CTF_OBJS) $(XATRIX_OBJS) diff --git a/solaris/g_so.c b/solaris/g_so.c new file mode 100644 index 000000000..69f75f876 --- /dev/null +++ b/solaris/g_so.c @@ -0,0 +1,3 @@ +int main(int argc, char *argv) +{ +} diff --git a/solaris/glob.c b/solaris/glob.c new file mode 100644 index 000000000..f248b0394 --- /dev/null +++ b/solaris/glob.c @@ -0,0 +1,164 @@ + +#include +#include "../linux/glob.h" + +/* Like glob_match, but match PATTERN against any final segment of TEXT. */ +static int glob_match_after_star(char *pattern, char *text) +{ + register char *p = pattern, *t = text; + register char c, c1; + + while ((c = *p++) == '?' || c == '*') + if (c == '?' && *t++ == '\0') + return 0; + + if (c == '\0') + return 1; + + if (c == '\\') + c1 = *p; + else + c1 = c; + + while (1) { + if ((c == '[' || *t == c1) && glob_match(p - 1, t)) + return 1; + if (*t++ == '\0') + return 0; + } +} + +/* Return nonzero if PATTERN has any special globbing chars in it. */ +static int glob_pattern_p(char *pattern) +{ + register char *p = pattern; + register char c; + int open = 0; + + while ((c = *p++) != '\0') + switch (c) { + case '?': + case '*': + return 1; + + case '[': /* Only accept an open brace if there is a close */ + open++; /* brace to match it. Bracket expressions must be */ + continue; /* complete, according to Posix.2 */ + case ']': + if (open) + return 1; + continue; + + case '\\': + if (*p++ == '\0') + return 0; + } + + return 0; +} + +/* Match the pattern PATTERN against the string TEXT; + return 1 if it matches, 0 otherwise. + + A match means the entire string TEXT is used up in matching. + + In the pattern string, `*' matches any sequence of characters, + `?' matches any character, [SET] matches any character in the specified set, + [!SET] matches any character not in the specified set. + + A set is composed of characters or ranges; a range looks like + character hyphen character (as in 0-9 or A-Z). + [0-9a-zA-Z_] is the set of characters allowed in C identifiers. + Any other character in the pattern must be matched exactly. + + To suppress the special syntactic significance of any of `[]*?!-\', + and match the character exactly, precede it with a `\'. +*/ + +int glob_match(char *pattern, char *text) +{ + register char *p = pattern, *t = text; + register char c; + + while ((c = *p++) != '\0') + switch (c) { + case '?': + if (*t == '\0') + return 0; + else + ++t; + break; + + case '\\': + if (*p++ != *t++) + return 0; + break; + + case '*': + return glob_match_after_star(p, t); + + case '[': + { + register char c1 = *t++; + int invert; + + if (!c1) + return (0); + + invert = ((*p == '!') || (*p == '^')); + if (invert) + p++; + + c = *p++; + while (1) { + register char cstart = c, cend = c; + + if (c == '\\') { + cstart = *p++; + cend = cstart; + } + if (c == '\0') + return 0; + + c = *p++; + if (c == '-' && *p != ']') { + cend = *p++; + if (cend == '\\') + cend = *p++; + if (cend == '\0') + return 0; + c = *p++; + } + if (c1 >= cstart && c1 <= cend) + goto match; + if (c == ']') + break; + } + if (!invert) + return 0; + break; + + match: + /* Skip the rest of the [...] construct that already matched. */ + while (c != ']') { + if (c == '\0') + return 0; + c = *p++; + if (c == '\0') + return 0; + else if (c == '\\') + ++p; + } + if (invert) + return 0; + break; + } + + default: + if (c != *t++) + return 0; + } + + return *t == '\0'; +} + diff --git a/solaris/glob.h b/solaris/glob.h new file mode 100644 index 000000000..c4a1b4346 --- /dev/null +++ b/solaris/glob.h @@ -0,0 +1 @@ +int glob_match(char *pattern, char *text); diff --git a/solaris/net_udp.c b/solaris/net_udp.c new file mode 100644 index 000000000..eba7f9d96 --- /dev/null +++ b/solaris/net_udp.c @@ -0,0 +1,537 @@ +// net_wins.c + +#include "../qcommon/qcommon.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NeXT +#include +#endif + +netadr_t net_local_adr; + +#define LOOPBACK 0x7f000001 + +#define MAX_LOOPBACK 4 + +typedef struct +{ + byte data[MAX_MSGLEN]; + int datalen; +} loopmsg_t; + +typedef struct +{ + loopmsg_t msgs[MAX_LOOPBACK]; + int get, send; +} loopback_t; + +loopback_t loopbacks[2]; +int ip_sockets[2]; +int ipx_sockets[2]; + +int NET_Socket (char *net_interface, int port); +char *NET_ErrorString (void); + +//============================================================================= + +void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s) +{ + memset (s, 0, sizeof(*s)); + + if (a->type == NA_BROADCAST) + { + s->sin_family = AF_INET; + + s->sin_port = a->port; + *(int *)&s->sin_addr = -1; + } + else if (a->type == NA_IP) + { + s->sin_family = AF_INET; + + *(int *)&s->sin_addr = *(int *)&a->ip; + s->sin_port = a->port; + } +} + +void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a) +{ + *(int *)&a->ip = *(int *)&s->sin_addr; + a->port = s->sin_port; + a->type = NA_IP; +} + + +qboolean NET_CompareAdr (netadr_t a, netadr_t b) +{ + if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port) + return true; + return false; +} + +/* +=================== +NET_CompareBaseAdr + +Compares without the port +=================== +*/ +qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) +{ + if (a.type != b.type) + return false; + + if (a.type == NA_LOOPBACK) + return true; + + if (a.type == NA_IP) + { + if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3]) + return true; + return false; + } + + if (a.type == NA_IPX) + { + if ((memcmp(a.ipx, b.ipx, 10) == 0)) + return true; + return false; + } +} + +char *NET_AdrToString (netadr_t a) +{ + static char s[64]; + + Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port)); + + return s; +} + +char *NET_BaseAdrToString (netadr_t a) +{ + static char s[64]; + + Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); + + return s; +} + +/* +============= +NET_StringToAdr + +localhost +idnewt +idnewt:28000 +192.246.40.70 +192.246.40.70:28000 +============= +*/ +qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr) +{ + struct hostent *h; + char *colon; + char copy[128]; + + memset (sadr, 0, sizeof(*sadr)); + ((struct sockaddr_in *)sadr)->sin_family = AF_INET; + + ((struct sockaddr_in *)sadr)->sin_port = 0; + + strcpy (copy, s); + // strip off a trailing :port if present + for (colon = copy ; *colon ; colon++) + if (*colon == ':') + { + *colon = 0; + ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1)); + } + + if (copy[0] >= '0' && copy[0] <= '9') + { + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy); + } + else + { + if (! (h = gethostbyname(copy)) ) + return 0; + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; + } + + return true; +} + +/* +============= +NET_StringToAdr + +localhost +idnewt +idnewt:28000 +192.246.40.70 +192.246.40.70:28000 +============= +*/ +qboolean NET_StringToAdr (char *s, netadr_t *a) +{ + struct sockaddr_in sadr; + + if (!strcmp (s, "localhost")) + { + memset (a, 0, sizeof(*a)); + a->type = NA_LOOPBACK; + return true; + } + + if (!NET_StringToSockaddr (s, (struct sockaddr *)&sadr)) + return false; + + SockadrToNetadr (&sadr, a); + + return true; +} + + +qboolean NET_IsLocalAddress (netadr_t adr) +{ + return NET_CompareAdr (adr, net_local_adr); +} + +/* +============================================================================= + +LOOPBACK BUFFERS FOR LOCAL PLAYER + +============================================================================= +*/ + +qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) +{ + int i; + loopback_t *loop; + + loop = &loopbacks[sock]; + + if (loop->send - loop->get > MAX_LOOPBACK) + loop->get = loop->send - MAX_LOOPBACK; + + if (loop->get >= loop->send) + return false; + + i = loop->get & (MAX_LOOPBACK-1); + loop->get++; + + memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen); + net_message->cursize = loop->msgs[i].datalen; + *net_from = net_local_adr; + return true; + +} + + +void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) +{ + int i; + loopback_t *loop; + + loop = &loopbacks[sock^1]; + + i = loop->send & (MAX_LOOPBACK-1); + loop->send++; + + memcpy (loop->msgs[i].data, data, length); + loop->msgs[i].datalen = length; +} + +//============================================================================= + +qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) +{ + int ret; + struct sockaddr_in from; + int fromlen; + int net_socket; + int protocol; + int err; + + if (NET_GetLoopPacket (sock, net_from, net_message)) + return true; + + for (protocol = 0 ; protocol < 2 ; protocol++) + { + if (protocol == 0) + net_socket = ip_sockets[sock]; + else + net_socket = ipx_sockets[sock]; + + if (!net_socket) + continue; + + fromlen = sizeof(from); + ret = recvfrom (net_socket, net_message->data, net_message->maxsize + , 0, (struct sockaddr *)&from, &fromlen); + if (ret == -1) + { + err = errno; + + if (err == EWOULDBLOCK || err == ECONNREFUSED) + continue; + Com_Printf ("NET_GetPacket: %s", NET_ErrorString()); + continue; + } + + if (ret == net_message->maxsize) + { + Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); + continue; + } + + net_message->cursize = ret; + SockadrToNetadr (&from, net_from); + return true; + } + + return false; +} + +//============================================================================= + +void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) +{ + int ret; + struct sockaddr_in addr; + int net_socket; + + if ( to.type == NA_LOOPBACK ) + { + NET_SendLoopPacket (sock, length, data, to); + return; + } + + if (to.type == NA_BROADCAST) + { + net_socket = ip_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_IP) + { + net_socket = ip_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_IPX) + { + net_socket = ipx_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_BROADCAST_IPX) + { + net_socket = ipx_sockets[sock]; + if (!net_socket) + return; + } + else + Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); + + NetadrToSockadr (&to, &addr); + + ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); + if (ret == -1) + { + Com_Printf ("NET_SendPacket ERROR: %i\n", NET_ErrorString()); + } +} + + +//============================================================================= + + + + +/* +==================== +NET_OpenIP +==================== +*/ +void NET_OpenIP (void) +{ + cvar_t *port, *ip; + + port = Cvar_Get ("port", va("%i", PORT_SERVER), CVAR_NOSET); + ip = Cvar_Get ("ip", "localhost", CVAR_NOSET); + + if (!ip_sockets[NS_SERVER]) + ip_sockets[NS_SERVER] = NET_Socket (ip->string, port->value); + if (!ip_sockets[NS_CLIENT]) + ip_sockets[NS_CLIENT] = NET_Socket (ip->string, PORT_ANY); +} + +/* +==================== +NET_OpenIPX +==================== +*/ +void NET_OpenIPX (void) +{ +} + + +/* +==================== +NET_Config + +A single player game will only use the loopback code +==================== +*/ +void NET_Config (qboolean multiplayer) +{ + int i; + + if (!multiplayer) + { // shut down any existing sockets + for (i=0 ; i<2 ; i++) + { + if (ip_sockets[i]) + { + close (ip_sockets[i]); + ip_sockets[i] = 0; + } + if (ipx_sockets[i]) + { + close (ipx_sockets[i]); + ipx_sockets[i] = 0; + } + } + } + else + { // open sockets + NET_OpenIP (); + NET_OpenIPX (); + } +} + + +//=================================================================== + + +/* +==================== +NET_Init +==================== +*/ +void NET_Init (void) +{ +} + + +/* +==================== +NET_Socket +==================== +*/ +int NET_Socket (char *net_interface, int port) +{ + int newsocket; + struct sockaddr_in address; + qboolean _true = true; + int i = 1; + + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: socket:", NET_ErrorString()); + return 0; + } + + // make it non-blocking + if (ioctl (newsocket, FIONBIO, &_true) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString()); + return 0; + } + + // make it broadcast capable + if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString()); + return 0; + } + + if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) + address.sin_addr.s_addr = INADDR_ANY; + else + NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); + + if (port == PORT_ANY) + address.sin_port = 0; + else + address.sin_port = htons((short)port); + + address.sin_family = AF_INET; + + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); + close (newsocket); + return 0; + } + + return newsocket; +} + + +/* +==================== +NET_Shutdown +==================== +*/ +void NET_Shutdown (void) +{ + NET_Config (false); // close sockets +} + + +/* +==================== +NET_ErrorString +==================== +*/ +char *NET_ErrorString (void) +{ + int code; + + code = errno; + return strerror (code); +} + +// sleeps msec or until net socket is ready +void NET_Sleep(int msec) +{ + struct timeval timeout; + fd_set fdset; + extern cvar_t *dedicated; + extern qboolean stdin_active; + + if (!ip_sockets[NS_SERVER] || (dedicated && !dedicated->value)) + return; // we're not a server, just run full speed + + FD_ZERO(&fdset); + if (stdin_active) + FD_SET(0, &fdset); // stdin is processed too + FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket + timeout.tv_sec = msec/1000; + timeout.tv_usec = (msec%1000)*1000; + select(ip_sockets[NS_SERVER]+1, &fdset, NULL, NULL, &timeout); +} + diff --git a/solaris/q_shsolaris.c b/solaris/q_shsolaris.c new file mode 100644 index 000000000..c56055a1f --- /dev/null +++ b/solaris/q_shsolaris.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../linux/glob.h" + +#include "../qcommon/qcommon.h" + +//=============================================================================== + +byte *membase; +int maxhunksize; +int curhunksize; + +void *Hunk_Begin (int maxsize) +{ + // reserve a huge chunk of memory, but don't commit any yet + maxhunksize = maxsize; + curhunksize = 0; + membase = malloc(maxhunksize); + if (membase == NULL) + Sys_Error(ERR_FATAL, "unable to allocate %d bytes", maxsize); + + return membase; +} + +void *Hunk_Alloc (int size) +{ + byte *buf; + + // round to cacheline + size = (size+31)&~31; + if (curhunksize + size > maxhunksize) + Sys_Error(ERR_FATAL, "Hunk_Alloc overflow"); + buf = membase + curhunksize; + curhunksize += size; + return buf; +} + +int Hunk_End (void) +{ + byte *n; + + n = realloc(membase, curhunksize); + if (n != membase) + Sys_Error(ERR_FATAL, "Hunk_End: Could not remap virtual block (%d)", errno); + + return curhunksize; +} + +void Hunk_Free (void *base) +{ + if (base) + free(base); +} + +//=============================================================================== + + +/* +================ +Sys_Milliseconds +================ +*/ +int curtime; +int Sys_Milliseconds (void) +{ + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000; + } + + curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000; + + return curtime; +} + +void Sys_Mkdir (char *path) +{ + mkdir (path, 0777); +} + +char *strlwr (char *s) +{ + while (*s) { + *s = tolower(*s); + s++; + } +} + +//============================================ + +static char findbase[MAX_OSPATH]; +static char findpath[MAX_OSPATH]; +static char findpattern[MAX_OSPATH]; +static DIR *fdir; + +static qboolean CompareAttributes(char *path, char *name, + unsigned musthave, unsigned canthave ) +{ + struct stat st; + char fn[MAX_OSPATH]; + +// . and .. never match + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return false; + + sprintf(fn, "%s/%s", path, name); + if (stat(fn, &st) == -1) + return false; // shouldn't happen + + if ( ( st.st_mode & S_IFDIR ) && ( canthave & SFF_SUBDIR ) ) + return false; + + if ( ( musthave & SFF_SUBDIR ) && !( st.st_mode & S_IFDIR ) ) + return false; + + return true; +} + +char *Sys_FindFirst (char *path, unsigned musthave, unsigned canhave) +{ + struct dirent *d; + char *p; + + if (fdir) + Sys_Error ("Sys_BeginFind without close"); + +// COM_FilePath (path, findbase); + strcpy(findbase, path); + + if ((p = strrchr(findbase, '/')) != NULL) { + *p = 0; + strcpy(findpattern, p + 1); + } else + strcpy(findpattern, "*"); + + if (strcmp(findpattern, "*.*") == 0) + strcpy(findpattern, "*"); + + if ((fdir = opendir(path)) == NULL) + return NULL; + while ((d = readdir(fdir)) != NULL) { + if (!*findpattern || glob_match(findpattern, d->d_name)) { +// if (*findpattern) +// printf("%s matched %s\n", findpattern, d->d_name); + if (CompareAttributes(findbase, d->d_name, musthave, canhave)) { + sprintf (findpath, "%s/%s", findbase, d->d_name); + return findpath; + } + } + } + return NULL; +} + +char *Sys_FindNext (unsigned musthave, unsigned canhave) +{ + struct dirent *d; + + if (fdir == NULL) + return NULL; + while ((d = readdir(fdir)) != NULL) { + if (!*findpattern || glob_match(findpattern, d->d_name)) { +// if (*findpattern) +// printf("%s matched %s\n", findpattern, d->d_name); + if (CompareAttributes(findbase, d->d_name, musthave, canhave)) { + sprintf (findpath, "%s/%s", findbase, d->d_name); + return findpath; + } + } + } + return NULL; +} + +void Sys_FindClose (void) +{ + if (fdir != NULL) + closedir(fdir); + fdir = NULL; +} + + +//============================================ + diff --git a/solaris/sys_solaris.c b/solaris/sys_solaris.c new file mode 100644 index 000000000..7b8e59b22 --- /dev/null +++ b/solaris/sys_solaris.c @@ -0,0 +1,337 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../qcommon/qcommon.h" + +cvar_t *nostdout; + +unsigned sys_frame_time; + +qboolean stdin_active = true; + +// ======================================================================= +// General routines +// ======================================================================= + +void Sys_ConsoleOutput (char *string) +{ + if (nostdout && nostdout->value) + return; + + fputs(string, stdout); +} + +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 && nostdout->value) + 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); + } +} + +void Sys_Quit (void) +{ + CL_Shutdown (); + Qcommon_Shutdown (); + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + _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); + + CL_Shutdown (); + Qcommon_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 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 (!dedicated || !dedicated->value) + return NULL; + + if (!stdin_active) + return NULL; + + 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 == 0) { // eof! + stdin_active = false; + return NULL; + } + if (len < 1) + return NULL; + text[len-1] = 0; // rip off the /n and terminate + + return text; +} + +/*****************************************************************************/ + +static void *game_library; + +/* +================= +Sys_UnloadGame +================= +*/ +void Sys_UnloadGame (void) +{ + if (game_library) + dlclose (game_library); + game_library = NULL; +} + +/* +================= +Sys_GetGameAPI + +Loads the game dll +================= +*/ +void *Sys_GetGameAPI (void *parms) +{ + void *(*GetGameAPI) (void *); + + char name[MAX_OSPATH]; + char curpath[MAX_OSPATH]; + char *path; +#ifdef __i386__ + const char *gamename = "gamei386.so"; +#elif defined __sun__ + const char *gamename = "gamesparc.so"; +#else +#error Unknown arch +#endif + + if (game_library) + Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame"); + + getcwd(curpath, sizeof(curpath)); + + Com_Printf("------- Loading %s -------", gamename); + + // now run through the search paths + path = NULL; + while (1) + { + path = FS_NextPath (path); + if (!path) + return NULL; // couldn't find one anywhere + sprintf (name, "%s/%s/%s", curpath, path, gamename); + game_library = dlopen (name, RTLD_NOW ); + if (game_library) + { + Com_DPrintf ("LoadLibrary (%s)\n",name); + break; + } else + Com_Printf("error: %s\n", dlerror()); + } + + GetGameAPI = (void *)dlsym (game_library, "GetGameAPI"); + if (!GetGameAPI) + { + Sys_UnloadGame (); + return NULL; + } + + return GetGameAPI (parms); +} + +/*****************************************************************************/ + +void Sys_AppActivate (void) +{ +} + +void Sys_SendKeyEvents (void) +{ + // grab frame time + sys_frame_time = Sys_Milliseconds(); +} + +/*****************************************************************************/ + +char *Sys_GetClipboardData(void) +{ + return NULL; +} + +int main (int argc, char **argv) +{ + int time, oldtime, newtime; + +#if 0 + int newargc; + char **newargv; + int i; + + // force dedicated + newargc = argc; + newargv = malloc((argc + 3) * sizeof(char *)); + newargv[0] = argv[0]; + newargv[1] = "+set"; + newargv[2] = "dedicated"; + newargv[3] = "1"; + for (i = 1; i < argc; i++) + newargv[i + 3] = argv[i]; + newargc += 3; + + Qcommon_Init(newargc, newargv); +#else + Qcommon_Init(argc, argv); +#endif + + fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); + + nostdout = Cvar_Get("nostdout", "0", 0); + + if (!nostdout->value) { + fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); +// printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION); + } + + oldtime = Sys_Milliseconds (); + while (1) + { +// find time spent rendering last frame + do { + newtime = Sys_Milliseconds (); + time = newtime - oldtime; + } while (time < 1); + Qcommon_Frame (time); + oldtime = newtime; + } + +} + +void Sys_CopyProtect(void) +{ + return; +} + +#if 0 +/* +================ +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"); + +} + +#endif diff --git a/unix/makefile b/unix/makefile new file mode 100644 index 000000000..1f9c9a5eb --- /dev/null +++ b/unix/makefile @@ -0,0 +1,308 @@ + +CFLAGS = -c +LDFLAGS = +ODIR = baddir + +EXEBASE = quake2 +EXE = $(ODIR)/quake2 +all: $(EXE) + +#---------------------------------------------------------------------- + +SERVERFILES = $(ODIR)/sv_ccmds.o $(ODIR)/sv_ents.o $(ODIR)/sv_game.o $(ODIR)/sv_init.o $(ODIR)/sv_main.o $(ODIR)/sv_send.o $(ODIR)/sv_user.o $(ODIR)/sv_world.o + +CLIENTFILES = $(ODIR)/cl_demo.o $(ODIR)/cl_ents.o $(ODIR)/cl_fx.o $(ODIR)/cl_input.o $(ODIR)/cl_inv.o $(ODIR)/cl_main.o $(ODIR)/cl_parse.o $(ODIR)/cl_tent.o $(ODIR)/console.o $(ODIR)/keys.o $(ODIR)/menu.o $(ODIR)/qmenu.o $(ODIR)/screen.o $(ODIR)/scr_cin.o $(ODIR)/snd_dma.o $(ODIR)/snd_mem.o $(ODIR)/snd_mix.o $(ODIR)/view.o + +# commonfiles are used by both client and server +COMMONFILES = $(ODIR)/cmd.o $(ODIR)/cmodel.o $(ODIR)/cvar.o $(ODIR)/files.o $(ODIR)/md4.o $(ODIR)/net_chan.o $(ODIR)/net_udp.o + +REFGLFILES = $(ODIR)/gl_draw.o $(ODIR)/gl_inter.o $(ODIR)/gl_light.o $(ODIR)/gl_math.o $(ODIR)/gl_mesh.o $(ODIR)/gl_model.o $(ODIR)/gl_rmain.o $(ODIR)/gl_rmisc.o $(ODIR)/gl_rsurf.o $(ODIR)/gl_textr.o $(ODIR)/gl_warp. + +REFSOFTFILES = $(ODIR)/r_aclip.o $(ODIR)/r_alias.o $(ODIR)/r_bsp.o $(ODIR)/r_draw.o $(ODIR)/r_edge.o $(ODIR)/r_image.o $(ODIR)/r_light.o $(ODIR)/r_main.o $(ODIR)/r_misc.o $(ODIR)/r_model.o $(ODIR)/r_part.o $(ODIR)/r_polyse.o $(ODIR)/r_poly.o $(ODIR)/r_rast.o $(ODIR)/r_scan.o $(ODIR)/r_sprite.o $(ODIR)/r_surf.o + +# sharedfiles are included in EVERY dll +SHAREDFILES = $(ODIR)/q_shared + +#---------------------------------------------------------------------- + +_next: + make "CFLAGS = -c -Wall -g -O" "ODIR = next" + +_irix: + make "CFLAGS = -c -O2 -Xcpluscomm -woff 513 -woff 594 -woff 596" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix" + +_irixdebug: + make "CFLAGS = -c -O2 -g -Xcpluscomm" "LDFLAGS = -g" "ODIR = irix" + +clean: + rm -f next/*.o next/$(EXEBASE) + rm -f irix/*.o irix/$(EXEBASE) + +#---------------------------------------------------------------------- + +FILES = $(SERVERFILES) $(COMMONFILES) $(CLIENTFILES) $(REFSOFTFILES) $(SHAREDFILES) + +$(EXE) : $(FILES) + cc -o $(EXE) $(LDFLAGS) $(FILES) -lm + +#---------------------------------------------------------------------- + +$(ODIR)/q_shared.o : ../qcommon/q_shared.c + cc $(CFLAGS) -o $@ $? + +#---------------------------------------------------------------------- + +$(ODIR)/sv_ccmds.o : ../server/sv_ccmds.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_ents.o : ../server/sv_ents.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_game.o : ../server/sv_game.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_init.o : ../server/sv_init.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_main.o : ../server/sv_main.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_send.o : ../server/sv_send.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_user.o : ../server/sv_user.c + cc $(CFLAGS) -o $@ $? + +$(ODIR)/sv_world.o : ../server/sv_world.c + cc $(CFLAGS) -o $@ $? + +#---------------------------------------------------------------------- + +$(ODIR)/cl_demo.o : ../client/cl_demo.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_ents.o : ../client/cl_ents.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_fx.o : ../client/cl_fx.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_input.o : ../client/cl_input.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_inv.o : ../client/cl_inv.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_main.o : ../client/cl_main.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_parse.o : ../client/cl_parse.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_tent.o : ../client/cl_tent.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/console.o : ../client/console.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/keys.o : ../client/keys.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/menu.o : ../client/menu.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/qmenu.o : ../client/qmenu.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sbar2.o : ../client/sbar2.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/screen.o : ../client/screen.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/scr_cin.o : ../client/scr_cin.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/snd_dma.o : ../client/snd_dma.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/snd_mem.o : ../client/snd_mem.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/snd_mix.o : ../client/snd_mix.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/view.o : ../client/view.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/cmd.o : ../qcommon/cmd.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmodel.o : ../qcommon/cmodel.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cvar.o : ../qcommon/cvar.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/files.o : ../qcommon/files.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/md4.o : ../qcommon/md4.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/net_chan.o : ../qcommon/net_chan.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/net_udp.o : ../qcommon/net_udp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sys_null.o : ../qcommon/sys_null.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/gl_draw.o : ../ref_gl/gl_draw.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_inter.o : ../ref_gl/gl_inter.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_light.o : ../ref_gl/gl_light.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_math.o : ../ref_gl/gl_math.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_mesh.o : ../ref_gl/gl_mesh.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_model.o : ../ref_gl/gl_model.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_rmain.o : ../ref_gl/gl_rmain.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_rmisc.o : ../ref_gl/gl_rmisc.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_rsurf.o : ../ref_gl/gl_rsurf.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_textr.o : ../ref_gl/gl_textr.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_warp.o : ../ref_gl/gl_warp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/r_aclip.o : ../ref_soft/r_aclip.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_alias.o : ../ref_soft/r_alias.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_bsp.o : ../ref_soft/r_bsp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_draw.o : ../ref_soft/r_draw.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_edge.o : ../ref_soft/r_edge.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_image.o : ../ref_soft/r_image.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_light.o : ../ref_soft/r_light.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_main.o : ../ref_soft/r_main.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_misc.o : ../ref_soft/r_misc.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_model.o : ../ref_soft/r_model.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_part.o : ../ref_soft/r_part.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_polyse.o : ../ref_soft/r_polyse.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_poly.o : ../ref_soft/r_poly.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_rast.o : ../ref_soft/r_rast.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_scan.o : ../ref_soft/r_scan.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_sprite.o : ../ref_soft/r_sprite.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_surf.o : ../ref_soft/r_surf.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + diff --git a/unix/makefile_old b/unix/makefile_old new file mode 100644 index 000000000..aedec693e --- /dev/null +++ b/unix/makefile_old @@ -0,0 +1,317 @@ + +CFLAGS = -c +LDFLAGS = +ODIR = baddir + +EXEBASE = quake2 +EXE = $(ODIR)/quake2 +all: $(EXE) + +#---------------------------------------------------------------------- + +SERVERFILES = $(ODIR)/sv_ccmds.o $(ODIR)/sv_ents.o $(ODIR)/sv_game.o $(ODIR)/sv_init.o $(ODIR)/sv_main.o $(ODIR)/sv_send.o $(ODIR)/sv_user.o $(ODIR)/sv_world.o + +CLIENTFILES = $(ODIR)/cl_demo.o $(ODIR)/cl_ents.o $(ODIR)/cl_fx.o $(ODIR)/cl_input.o $(ODIR)/cl_inv.o $(ODIR)/cl_main.o $(ODIR)/cl_parse.o $(ODIR)/cl_tent.o $(ODIR)/console.o $(ODIR)/keys.o $(ODIR)/menu.o $(ODIR)/qmenu.o $(ODIR)/screen.o $(ODIR)/scr_cin.o $(ODIR)/snd_dma.o $(ODIR)/snd_mem.o $(ODIR)/snd_mix.o $(ODIR)/view.o + +# commonfiles are used by both client and server +COMMONFILES = $(ODIR)/cmd.o $(ODIR)/cmodel.o $(ODIR)/cvar.o $(ODIR)/files.o $(ODIR)/md4.o $(ODIR)/net_chan.o $(ODIR)/net_udp.o + +REFGLFILES = $(ODIR)/gl_draw.o $(ODIR)/gl_inter.o $(ODIR)/gl_light.o $(ODIR)/gl_math.o $(ODIR)/gl_mesh.o $(ODIR)/gl_model.o $(ODIR)/gl_rmain.o $(ODIR)/gl_rmisc.o $(ODIR)/gl_rsurf.o $(ODIR)/gl_textr.o $(ODIR)/gl_warp. + +REFSOFTFILES = $(ODIR)/r_aclip.o $(ODIR)/r_alias.o $(ODIR)/r_bsp.o $(ODIR)/r_draw.o $(ODIR)/r_edge.o $(ODIR)/r_image.o $(ODIR)/r_light.o $(ODIR)/r_main.o $(ODIR)/r_misc.o $(ODIR)/r_model.o $(ODIR)/r_part.o $(ODIR)/r_polyse.o $(ODIR)/r_poly.o $(ODIR)/r_rast.o $(ODIR)/r_scan.o $(ODIR)/r_sprite.o $(ODIR)/r_surf.o + +# sharedfiles are included in EVERY dll +SHAREDFILES = $(ODIR)/q_shared + +#---------------------------------------------------------------------- + +_next: + make "CFLAGS = -c -Wall -g -O" "ODIR = next" + +_irix: + make "CFLAGS = -c -woff 513 -Ofast=ip32_10k -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix" + +_irixdebug: + make "CFLAGS = -c -O2 -g -Xcpluscomm" "LDFLAGS = -g" "ODIR = irix" + +clean: + rm -f next/*.o next/$(EXEBASE) + rm -f irix/*.o irix/$(EXEBASE) + +#---------------------------------------------------------------------- + +FILES = $(SERVERFILES) $(COMMONFILES) $(CLIENTFILES) $(REFSOFTFILES) $(SHAREDFILES) + +$(EXE) : $(FILES) + cc -o $(EXE) $(LDFLAGS) $(FILES) -lm + +#---------------------------------------------------------------------- + +$(ODIR)/q_shared.o : ../qcommon/q_shared.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/sv_ccmds.o : ../server/sv_ccmds.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_ents.o : ../server/sv_ents.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_game.o : ../server/sv_game.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_init.o : ../server/sv_init.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_main.o : ../server/sv_main.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_send.o : ../server/sv_send.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_user.o : ../server/sv_user.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sv_world.o : ../server/sv_world.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/cl_demo.o : ../client/cl_demo.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_ents.o : ../client/cl_ents.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_fx.o : ../client/cl_fx.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_input.o : ../client/cl_input.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_inv.o : ../client/cl_inv.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_main.o : ../client/cl_main.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_parse.o : ../client/cl_parse.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cl_tent.o : ../client/cl_tent.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/console.o : ../client/console.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/keys.o : ../client/keys.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/menu.o : ../client/menu.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/qmenu.o : ../client/qmenu.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sbar2.o : ../client/sbar2.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/screen.o : ../client/screen.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/scr_cin.o : ../client/scr_cin.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/snd_dma.o : ../client/snd_dma.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/snd_mem.o : ../client/snd_mem.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/snd_mix.o : ../client/snd_mix.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/view.o : ../client/view.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/cmd.o : ../qcommon/cmd.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmodel.o : ../qcommon/cmodel.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cvar.o : ../qcommon/cvar.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/files.o : ../qcommon/files.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/md4.o : ../qcommon/md4.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/net_chan.o : ../qcommon/net_chan.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/net_udp.o : ../qcommon/net_udp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/sys_null.o : ../qcommon/sys_null.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/gl_draw.o : ../ref_gl/gl_draw.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_inter.o : ../ref_gl/gl_inter.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_light.o : ../ref_gl/gl_light.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_math.o : ../ref_gl/gl_math.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_mesh.o : ../ref_gl/gl_mesh.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_model.o : ../ref_gl/gl_model.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_rmain.o : ../ref_gl/gl_rmain.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_rmisc.o : ../ref_gl/gl_rmisc.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_rsurf.o : ../ref_gl/gl_rsurf.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_textr.o : ../ref_gl/gl_textr.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/gl_warp.o : ../ref_gl/gl_warp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + +$(ODIR)/r_aclip.o : ../ref_soft/r_aclip.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_alias.o : ../ref_soft/r_alias.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_bsp.o : ../ref_soft/r_bsp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_draw.o : ../ref_soft/r_draw.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_edge.o : ../ref_soft/r_edge.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_image.o : ../ref_soft/r_image.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_light.o : ../ref_soft/r_light.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_main.o : ../ref_soft/r_main.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_misc.o : ../ref_soft/r_misc.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_model.o : ../ref_soft/r_model.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_part.o : ../ref_soft/r_part.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_polyse.o : ../ref_soft/r_polyse.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_poly.o : ../ref_soft/r_poly.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_rast.o : ../ref_soft/r_rast.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_scan.o : ../ref_soft/r_scan.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_sprite.o : ../ref_soft/r_sprite.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/r_surf.o : ../ref_soft/r_surf.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +#---------------------------------------------------------------------- + diff --git a/unix/next/sv_ccmds.o b/unix/next/sv_ccmds.o new file mode 100644 index 000000000..8e9738259 Binary files /dev/null and b/unix/next/sv_ccmds.o differ diff --git a/win32/cd_win.c b/win32/cd_win.c new file mode 100644 index 000000000..fcae2f74f --- /dev/null +++ b/win32/cd_win.c @@ -0,0 +1,510 @@ +/* +Copyright (C) 1997-2001 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 +#include "../client/client.h" + +extern HWND cl_hwnd; + +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 byte remap[100]; +static byte cdrom; +static byte playTrack; +static byte maxTrack; + +cvar_t *cd_nocd; +cvar_t *cd_loopcount; +cvar_t *cd_looptrack; + +UINT wDeviceID; +int loopcounter; + + +void CDAudio_Pause(void); + +static void CDAudio_Eject(void) +{ + DWORD dwReturn; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL)) + Com_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)) + Com_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) + { + Com_DPrintf("CDAudio: drive ready test - get status failed\n"); + return -1; + } + if (!mciStatusParms.dwReturn) + { + Com_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) + { + Com_DPrintf("CDAudio: get tracks - status failed\n"); + return -1; + } + if (mciStatusParms.dwReturn < 1) + { + Com_DPrintf("CDAudio: no music tracks\n"); + return -1; + } + + cdValid = true; + maxTrack = mciStatusParms.dwReturn; + + return 0; +} + + + +void CDAudio_Play2(int 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) + { + CDAudio_Stop(); + 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) + { + Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); + return; + } + if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) + { + Com_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) + { + Com_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)cl_hwnd; + dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); + if (dwReturn) + { + Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); + return; + } + + playLooping = looping; + playTrack = track; + playing = true; + + if ( Cvar_VariableValue( "cd_nocd" ) ) + CDAudio_Pause (); +} + + +void CDAudio_Play(int track, qboolean looping) +{ + // set a loop counter so that this track will change to the + // looptrack later + loopcounter = 0; + CDAudio_Play2(track, looping); +} + +void CDAudio_Stop(void) +{ + DWORD dwReturn; + + if (!enabled) + return; + + if (!playing) + return; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) + Com_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)cl_hwnd; + if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) + Com_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)cl_hwnd; + dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); + if (dwReturn) + { + Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); + return; + } + 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) + Com_Printf(" %u -> %u\n", n, remap[n]); + return; + } + for (n = 1; n <= ret; n++) + remap[n] = atoi(Cmd_Argv (n+1)); + return; + } + + if (Q_strcasecmp(command, "close") == 0) + { + CDAudio_CloseDoor(); + return; + } + + if (!cdValid) + { + CDAudio_GetAudioDiskInfo(); + if (!cdValid) + { + Com_Printf("No CD in player.\n"); + return; + } + } + + if (Q_strcasecmp(command, "play") == 0) + { + CDAudio_Play(atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "loop") == 0) + { + CDAudio_Play(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) + { + Com_Printf("%u tracks\n", maxTrack); + if (playing) + Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); + else if (wasPlaying) + Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); + 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) + { + // if the track has played the given number of times, + // go to the ambient track + if (++loopcounter >= cd_loopcount->value) + CDAudio_Play2(cd_looptrack->value, true); + else + CDAudio_Play2(playTrack, true); + } + } + break; + + case MCI_NOTIFY_ABORTED: + case MCI_NOTIFY_SUPERSEDED: + break; + + case MCI_NOTIFY_FAILURE: + Com_DPrintf("MCI_NOTIFY_FAILURE\n"); + CDAudio_Stop (); + cdValid = false; + break; + + default: + Com_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); + return 1; + } + + return 0; +} + + +void CDAudio_Update(void) +{ + if ( cd_nocd->value != !enabled ) + { + if ( cd_nocd->value ) + { + CDAudio_Stop(); + enabled = false; + } + else + { + enabled = true; + CDAudio_Resume (); + } + } +} + + +int CDAudio_Init(void) +{ + DWORD dwReturn; + MCI_OPEN_PARMS mciOpenParms; + MCI_SET_PARMS mciSetParms; + int n; + + cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE ); + cd_loopcount = Cvar_Get ("cd_loopcount", "4", 0); + cd_looptrack = Cvar_Get ("cd_looptrack", "11", 0); + if ( cd_nocd->value) + return -1; + + mciOpenParms.lpstrDeviceType = "cdaudio"; + if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) + { + Com_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)) + { + Com_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()) + { +// Com_Printf("CDAudio_Init: No CD in player.\n"); + cdValid = false; + enabled = false; + } + + Cmd_AddCommand ("cd", CD_f); + + Com_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)) + Com_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); +} + + +/* +=========== +CDAudio_Activate + +Called when the main window gains or loses focus. +The window have been destroyed and recreated +between a deactivate and an activate. +=========== +*/ +void CDAudio_Activate (qboolean active) +{ + if (active) + CDAudio_Resume (); + else + CDAudio_Pause (); +} diff --git a/win32/conproc.c b/win32/conproc.c new file mode 100644 index 000000000..977e536fd --- /dev/null +++ b/win32/conproc.c @@ -0,0 +1,431 @@ +/* +Copyright (C) 1997-2001 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 -- support for qhost +#include +#include +#include +#include "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 + + +HANDLE heventDone; +HANDLE hfileBuffer; +HANDLE heventChildSend; +HANDLE heventParentSend; +HANDLE hStdout; +HANDLE hStdin; + +unsigned _stdcall RequestProc (void *arg); +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); + +int ccom_argc; +char **ccom_argv; + +/* +================ +CCheckParm + +Returns the position (1 to argc-1) in the program's argument list +where the given parameter apears, or 0 if not present +================ +*/ +int CCheckParm (char *parm) +{ + int i; + + for (i=1 ; i 0) + { + if (t < argc) + hFile = (HANDLE)atoi (ccom_argv[t+1]); + } + + if ((t = CCheckParm ("-HPARENT")) > 0) + { + if (t < argc) + heventParent = (HANDLE)atoi (ccom_argv[t+1]); + } + + if ((t = CCheckParm ("-HCHILD")) > 0) + { + if (t < argc) + heventChild = (HANDLE)atoi (ccom_argv[t+1]); + } + + +// ignore if we don't have all the events. + if (!hFile || !heventParent || !heventChild) + { + printf ("Qhost not present.\n"); + return; + } + + printf ("Initializing for qhost.\n"); + + hfileBuffer = hFile; + heventParentSend = heventParent; + heventChildSend = heventChild; + +// so we'll know when to go away. + heventDone = CreateEvent (NULL, FALSE, FALSE, NULL); + + if (!heventDone) + { + printf ("Couldn't create heventDone\n"); + return; + } + + if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr)) + { + CloseHandle (heventDone); + printf ("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); +} + + +unsigned _stdcall RequestProc (void *arg) +{ + 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) + { + printf ("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); + } + + _endthreadex (0); + 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; +} + diff --git a/win32/conproc.h b/win32/conproc.h new file mode 100644 index 000000000..40d473446 --- /dev/null +++ b/win32/conproc.h @@ -0,0 +1,24 @@ +/* +Copyright (C) 1997-2001 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 -- support for qhost + +void InitConProc (int argc, char **argv); +void DeinitConProc (void); + diff --git a/win32/glw_imp.c b/win32/glw_imp.c new file mode 100644 index 000000000..943d87835 --- /dev/null +++ b/win32/glw_imp.c @@ -0,0 +1,616 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +/* +** GLW_IMP.C +** +** This file contains ALL Win32 specific stuff having to do with the +** OpenGL refresh. When a port is being made the following functions +** must be implemented by the port: +** +** GLimp_EndFrame +** GLimp_Init +** GLimp_Shutdown +** GLimp_SwitchFullscreen +** +*/ +#include +#include +#include "../ref_gl/gl_local.h" +#include "glw_win.h" +#include "winquake.h" + +static qboolean GLimp_SwitchFullscreen( int width, int height ); +qboolean GLimp_InitGL (void); + +glwstate_t glw_state; + +extern cvar_t *vid_fullscreen; +extern cvar_t *vid_ref; + +static qboolean VerifyDriver( void ) +{ + char buffer[1024]; + + strcpy( buffer, qglGetString( GL_RENDERER ) ); + strlwr( buffer ); + if ( strcmp( buffer, "gdi generic" ) == 0 ) + if ( !glw_state.mcd_accelerated ) + return false; + return true; +} + +/* +** VID_CreateWindow +*/ +#define WINDOW_CLASS_NAME "Quake 2" + +qboolean VID_CreateWindow( int width, int height, qboolean fullscreen ) +{ + WNDCLASS wc; + RECT r; + cvar_t *vid_xpos, *vid_ypos; + int stylebits; + int x, y, w, h; + int exstyle; + + /* Register the frame class */ + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)glw_state.wndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = glw_state.hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = (void *)COLOR_GRAYTEXT; + wc.lpszMenuName = 0; + wc.lpszClassName = WINDOW_CLASS_NAME; + + if (!RegisterClass (&wc) ) + ri.Sys_Error (ERR_FATAL, "Couldn't register window class"); + + if (fullscreen) + { + exstyle = WS_EX_TOPMOST; + stylebits = WS_POPUP|WS_VISIBLE; + } + else + { + exstyle = 0; + stylebits = WINDOW_STYLE; + } + + r.left = 0; + r.top = 0; + r.right = width; + r.bottom = height; + + AdjustWindowRect (&r, stylebits, FALSE); + + w = r.right - r.left; + h = r.bottom - r.top; + + if (fullscreen) + { + x = 0; + y = 0; + } + else + { + vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0); + vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0); + x = vid_xpos->value; + y = vid_ypos->value; + } + + glw_state.hWnd = CreateWindowEx ( + exstyle, + WINDOW_CLASS_NAME, + "Quake 2", + stylebits, + x, y, w, h, + NULL, + NULL, + glw_state.hInstance, + NULL); + + if (!glw_state.hWnd) + ri.Sys_Error (ERR_FATAL, "Couldn't create window"); + + ShowWindow( glw_state.hWnd, SW_SHOW ); + UpdateWindow( glw_state.hWnd ); + + // init all the gl stuff for the window + if (!GLimp_InitGL ()) + { + ri.Con_Printf( PRINT_ALL, "VID_CreateWindow() - GLimp_InitGL failed\n"); + return false; + } + + SetForegroundWindow( glw_state.hWnd ); + SetFocus( glw_state.hWnd ); + + // let the sound and input subsystems know about the new window + ri.Vid_NewWindow (width, height); + + return true; +} + + +/* +** GLimp_SetMode +*/ +rserr_t GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) +{ + int width, height; + const char *win_fs[] = { "W", "FS" }; + + ri.Con_Printf( PRINT_ALL, "Initializing OpenGL display\n"); + + ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode ); + + if ( !ri.Vid_GetModeInfo( &width, &height, mode ) ) + { + ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); + return rserr_invalid_mode; + } + + ri.Con_Printf( PRINT_ALL, " %d %d %s\n", width, height, win_fs[fullscreen] ); + + // destroy the existing window + if (glw_state.hWnd) + { + GLimp_Shutdown (); + } + + // do a CDS if needed + if ( fullscreen ) + { + DEVMODE dm; + + ri.Con_Printf( PRINT_ALL, "...attempting fullscreen\n" ); + + memset( &dm, 0, sizeof( dm ) ); + + dm.dmSize = sizeof( dm ); + + dm.dmPelsWidth = width; + dm.dmPelsHeight = height; + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + + if ( gl_bitdepth->value != 0 ) + { + dm.dmBitsPerPel = gl_bitdepth->value; + dm.dmFields |= DM_BITSPERPEL; + ri.Con_Printf( PRINT_ALL, "...using gl_bitdepth of %d\n", ( int ) gl_bitdepth->value ); + } + else + { + HDC hdc = GetDC( NULL ); + int bitspixel = GetDeviceCaps( hdc, BITSPIXEL ); + + ri.Con_Printf( PRINT_ALL, "...using desktop display depth of %d\n", bitspixel ); + + ReleaseDC( 0, hdc ); + } + + ri.Con_Printf( PRINT_ALL, "...calling CDS: " ); + if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL ) + { + *pwidth = width; + *pheight = height; + + gl_state.fullscreen = true; + + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + if ( !VID_CreateWindow (width, height, true) ) + return rserr_invalid_mode; + + return rserr_ok; + } + else + { + *pwidth = width; + *pheight = height; + + ri.Con_Printf( PRINT_ALL, "failed\n" ); + + ri.Con_Printf( PRINT_ALL, "...calling CDS assuming dual monitors:" ); + + dm.dmPelsWidth = width * 2; + dm.dmPelsHeight = height; + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + + if ( gl_bitdepth->value != 0 ) + { + dm.dmBitsPerPel = gl_bitdepth->value; + dm.dmFields |= DM_BITSPERPEL; + } + + /* + ** our first CDS failed, so maybe we're running on some weird dual monitor + ** system + */ + if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL ) + { + ri.Con_Printf( PRINT_ALL, " failed\n" ); + + ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" ); + + ChangeDisplaySettings( 0, 0 ); + + *pwidth = width; + *pheight = height; + gl_state.fullscreen = false; + if ( !VID_CreateWindow (width, height, false) ) + return rserr_invalid_mode; + return rserr_invalid_fullscreen; + } + else + { + ri.Con_Printf( PRINT_ALL, " ok\n" ); + if ( !VID_CreateWindow (width, height, true) ) + return rserr_invalid_mode; + + gl_state.fullscreen = true; + return rserr_ok; + } + } + } + else + { + ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" ); + + ChangeDisplaySettings( 0, 0 ); + + *pwidth = width; + *pheight = height; + gl_state.fullscreen = false; + if ( !VID_CreateWindow (width, height, false) ) + return rserr_invalid_mode; + } + + return rserr_ok; +} + +/* +** GLimp_Shutdown +** +** This routine does all OS specific shutdown procedures for the OpenGL +** subsystem. Under OpenGL this means NULLing out the current DC and +** HGLRC, deleting the rendering context, and releasing the DC acquired +** for the window. The state structure is also nulled out. +** +*/ +void GLimp_Shutdown( void ) +{ + if ( qwglMakeCurrent && !qwglMakeCurrent( NULL, NULL ) ) + ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - wglMakeCurrent failed\n"); + if ( glw_state.hGLRC ) + { + if ( qwglDeleteContext && !qwglDeleteContext( glw_state.hGLRC ) ) + ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - wglDeleteContext failed\n"); + glw_state.hGLRC = NULL; + } + if (glw_state.hDC) + { + if ( !ReleaseDC( glw_state.hWnd, glw_state.hDC ) ) + ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - ReleaseDC failed\n" ); + glw_state.hDC = NULL; + } + if (glw_state.hWnd) + { + DestroyWindow ( glw_state.hWnd ); + glw_state.hWnd = NULL; + } + + if ( glw_state.log_fp ) + { + fclose( glw_state.log_fp ); + glw_state.log_fp = 0; + } + + UnregisterClass (WINDOW_CLASS_NAME, glw_state.hInstance); + + if ( gl_state.fullscreen ) + { + ChangeDisplaySettings( 0, 0 ); + gl_state.fullscreen = false; + } +} + + +/* +** GLimp_Init +** +** This routine is responsible for initializing the OS specific portions +** of OpenGL. Under Win32 this means dealing with the pixelformats and +** doing the wgl interface stuff. +*/ +qboolean GLimp_Init( void *hinstance, void *wndproc ) +{ +#define OSR2_BUILD_NUMBER 1111 + + OSVERSIONINFO vinfo; + + vinfo.dwOSVersionInfoSize = sizeof(vinfo); + + glw_state.allowdisplaydepthchange = false; + + if ( GetVersionEx( &vinfo) ) + { + if ( vinfo.dwMajorVersion > 4 ) + { + glw_state.allowdisplaydepthchange = true; + } + else if ( vinfo.dwMajorVersion == 4 ) + { + if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) + { + glw_state.allowdisplaydepthchange = true; + } + else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) + { + if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER ) + { + glw_state.allowdisplaydepthchange = true; + } + } + } + } + else + { + ri.Con_Printf( PRINT_ALL, "GLimp_Init() - GetVersionEx failed\n" ); + return false; + } + + glw_state.hInstance = ( HINSTANCE ) hinstance; + glw_state.wndproc = wndproc; + + return true; +} + +qboolean GLimp_InitGL (void) +{ + PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 24, // 24-bit color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + int pixelformat; + cvar_t *stereo; + + stereo = ri.Cvar_Get( "cl_stereo", "0", 0 ); + + /* + ** set PFD_STEREO if necessary + */ + if ( stereo->value != 0 ) + { + ri.Con_Printf( PRINT_ALL, "...attempting to use stereo\n" ); + pfd.dwFlags |= PFD_STEREO; + gl_state.stereo_enabled = true; + } + else + { + gl_state.stereo_enabled = false; + } + + /* + ** figure out if we're running on a minidriver or not + */ + if ( strstr( gl_driver->string, "opengl32" ) != 0 ) + glw_state.minidriver = false; + else + glw_state.minidriver = true; + + /* + ** Get a DC for the specified window + */ + if ( glw_state.hDC != NULL ) + ri.Con_Printf( PRINT_ALL, "GLimp_Init() - non-NULL DC exists\n" ); + + if ( ( glw_state.hDC = GetDC( glw_state.hWnd ) ) == NULL ) + { + ri.Con_Printf( PRINT_ALL, "GLimp_Init() - GetDC failed\n" ); + return false; + } + + if ( glw_state.minidriver ) + { + if ( (pixelformat = qwglChoosePixelFormat( glw_state.hDC, &pfd)) == 0 ) + { + ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglChoosePixelFormat failed\n"); + return false; + } + if ( qwglSetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE ) + { + ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglSetPixelFormat failed\n"); + return false; + } + qwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd ); + } + else + { + if ( ( pixelformat = ChoosePixelFormat( glw_state.hDC, &pfd)) == 0 ) + { + ri.Con_Printf (PRINT_ALL, "GLimp_Init() - ChoosePixelFormat failed\n"); + return false; + } + if ( SetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE ) + { + ri.Con_Printf (PRINT_ALL, "GLimp_Init() - SetPixelFormat failed\n"); + return false; + } + DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd ); + + if ( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) ) + { + extern cvar_t *gl_allow_software; + + if ( gl_allow_software->value ) + glw_state.mcd_accelerated = true; + else + glw_state.mcd_accelerated = false; + } + else + { + glw_state.mcd_accelerated = true; + } + } + + /* + ** report if stereo is desired but unavailable + */ + if ( !( pfd.dwFlags & PFD_STEREO ) && ( stereo->value != 0 ) ) + { + ri.Con_Printf( PRINT_ALL, "...failed to select stereo pixel format\n" ); + ri.Cvar_SetValue( "cl_stereo", 0 ); + gl_state.stereo_enabled = false; + } + + /* + ** startup the OpenGL subsystem by creating a context and making + ** it current + */ + if ( ( glw_state.hGLRC = qwglCreateContext( glw_state.hDC ) ) == 0 ) + { + ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglCreateContext failed\n"); + + goto fail; + } + + if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) + { + ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglMakeCurrent failed\n"); + + goto fail; + } + + if ( !VerifyDriver() ) + { + ri.Con_Printf( PRINT_ALL, "GLimp_Init() - no hardware acceleration detected\n" ); + goto fail; + } + + /* + ** print out PFD specifics + */ + ri.Con_Printf( PRINT_ALL, "GL PFD: color(%d-bits) Z(%d-bit)\n", ( int ) pfd.cColorBits, ( int ) pfd.cDepthBits ); + + return true; + +fail: + if ( glw_state.hGLRC ) + { + qwglDeleteContext( glw_state.hGLRC ); + glw_state.hGLRC = NULL; + } + + if ( glw_state.hDC ) + { + ReleaseDC( glw_state.hWnd, glw_state.hDC ); + glw_state.hDC = NULL; + } + return false; +} + +/* +** GLimp_BeginFrame +*/ +void GLimp_BeginFrame( float camera_separation ) +{ + if ( gl_bitdepth->modified ) + { + if ( gl_bitdepth->value != 0 && !glw_state.allowdisplaydepthchange ) + { + ri.Cvar_SetValue( "gl_bitdepth", 0 ); + ri.Con_Printf( PRINT_ALL, "gl_bitdepth requires Win95 OSR2.x or WinNT 4.x\n" ); + } + gl_bitdepth->modified = false; + } + + if ( camera_separation < 0 && gl_state.stereo_enabled ) + { + qglDrawBuffer( GL_BACK_LEFT ); + } + else if ( camera_separation > 0 && gl_state.stereo_enabled ) + { + qglDrawBuffer( GL_BACK_RIGHT ); + } + else + { + qglDrawBuffer( GL_BACK ); + } +} + +/* +** GLimp_EndFrame +** +** Responsible for doing a swapbuffers and possibly for other stuff +** as yet to be determined. Probably better not to make this a GLimp +** function and instead do a call to GLimp_SwapBuffers. +*/ +void GLimp_EndFrame (void) +{ + int err; + + err = qglGetError(); + assert( err == GL_NO_ERROR ); + + if ( stricmp( gl_drawbuffer->string, "GL_BACK" ) == 0 ) + { + if ( !qwglSwapBuffers( glw_state.hDC ) ) + ri.Sys_Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" ); + } +} + +/* +** GLimp_AppActivate +*/ +void GLimp_AppActivate( qboolean active ) +{ + if ( active ) + { + SetForegroundWindow( glw_state.hWnd ); + ShowWindow( glw_state.hWnd, SW_RESTORE ); + } + else + { + if ( vid_fullscreen->value ) + ShowWindow( glw_state.hWnd, SW_MINIMIZE ); + } +} diff --git a/win32/glw_win.h b/win32/glw_win.h new file mode 100644 index 000000000..ba7aa2b95 --- /dev/null +++ b/win32/glw_win.h @@ -0,0 +1,47 @@ +/* +Copyright (C) 1997-2001 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 _WIN32 +# error You should not be including this file on this platform +#endif + +#ifndef __GLW_WIN_H__ +#define __GLW_WIN_H__ + +typedef struct +{ + HINSTANCE hInstance; + void *wndproc; + + HDC hDC; // handle to device context + HWND hWnd; // handle to window + HGLRC hGLRC; // handle to GL rendering context + + HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library + + qboolean minidriver; + qboolean allowdisplaydepthchange; + qboolean mcd_accelerated; + + FILE *log_fp; +} glwstate_t; + +extern glwstate_t glw_state; + +#endif diff --git a/win32/in_win.c b/win32/in_win.c new file mode 100644 index 000000000..7ec577ee4 --- /dev/null +++ b/win32/in_win.c @@ -0,0 +1,889 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// in_win.c -- windows 95 mouse and joystick code +// 02/21/97 JCB Added extended DirectInput code to support external controllers. + +#include "../client/client.h" +#include "winquake.h" + +extern unsigned sys_msg_time; + +// joystick defines and variables +// where should defines be moved? +#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick +#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball +#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V +#define JOY_AXIS_X 0 +#define JOY_AXIS_Y 1 +#define JOY_AXIS_Z 2 +#define JOY_AXIS_R 3 +#define JOY_AXIS_U 4 +#define JOY_AXIS_V 5 + +enum _ControlList +{ + AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn, AxisUp +}; + +DWORD dwAxisFlags[JOY_MAX_AXES] = +{ + JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV +}; + +DWORD dwAxisMap[JOY_MAX_AXES]; +DWORD dwControlMap[JOY_MAX_AXES]; +PDWORD pdwRawValue[JOY_MAX_AXES]; + +cvar_t *in_mouse; +cvar_t *in_joystick; + + +// none of these cvars are saved over a session +// this means that advanced controller configuration needs to be executed +// each time. this avoids any problems with getting back to a default usage +// or when changing from one controller to another. this way at least something +// works. +cvar_t *joy_name; +cvar_t *joy_advanced; +cvar_t *joy_advaxisx; +cvar_t *joy_advaxisy; +cvar_t *joy_advaxisz; +cvar_t *joy_advaxisr; +cvar_t *joy_advaxisu; +cvar_t *joy_advaxisv; +cvar_t *joy_forwardthreshold; +cvar_t *joy_sidethreshold; +cvar_t *joy_pitchthreshold; +cvar_t *joy_yawthreshold; +cvar_t *joy_forwardsensitivity; +cvar_t *joy_sidesensitivity; +cvar_t *joy_pitchsensitivity; +cvar_t *joy_yawsensitivity; +cvar_t *joy_upthreshold; +cvar_t *joy_upsensitivity; + +qboolean joy_avail, joy_advancedinit, joy_haspov; +DWORD joy_oldbuttonstate, joy_oldpovstate; + +int joy_id; +DWORD joy_flags; +DWORD joy_numbuttons; + +static JOYINFOEX ji; + +qboolean in_appactive; + +// forward-referenced functions +void IN_StartupJoystick (void); +void Joy_AdvancedUpdate_f (void); +void IN_JoyMove (usercmd_t *cmd); + +/* +============================================================ + + MOUSE CONTROL + +============================================================ +*/ + +// mouse variables +cvar_t *m_filter; + +qboolean mlooking; + +void IN_MLookDown (void) { mlooking = true; } +void IN_MLookUp (void) { +mlooking = false; +if (!freelook->value && lookspring->value) + IN_CenterView (); +} + +int mouse_buttons; +int mouse_oldbuttonstate; +POINT current_pos; +int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; + +int old_x, old_y; + +qboolean mouseactive; // false when not focus app + +qboolean restore_spi; +qboolean mouseinitialized; +int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; +qboolean mouseparmsvalid; + +int window_center_x, window_center_y; +RECT window_rect; + + +/* +=========== +IN_ActivateMouse + +Called when the window gains focus or changes in some way +=========== +*/ +void IN_ActivateMouse (void) +{ + int width, height; + + if (!mouseinitialized) + return; + if (!in_mouse->value) + { + mouseactive = false; + return; + } + if (mouseactive) + return; + + mouseactive = true; + + if (mouseparmsvalid) + restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); + + width = GetSystemMetrics (SM_CXSCREEN); + height = GetSystemMetrics (SM_CYSCREEN); + + GetWindowRect ( cl_hwnd, &window_rect); + if (window_rect.left < 0) + window_rect.left = 0; + if (window_rect.top < 0) + window_rect.top = 0; + if (window_rect.right >= width) + window_rect.right = width-1; + if (window_rect.bottom >= height-1) + window_rect.bottom = height-1; + + window_center_x = (window_rect.right + window_rect.left)/2; + window_center_y = (window_rect.top + window_rect.bottom)/2; + + SetCursorPos (window_center_x, window_center_y); + + old_x = window_center_x; + old_y = window_center_y; + + SetCapture ( cl_hwnd ); + ClipCursor (&window_rect); + while (ShowCursor (FALSE) >= 0) + ; +} + + +/* +=========== +IN_DeactivateMouse + +Called when the window loses focus +=========== +*/ +void IN_DeactivateMouse (void) +{ + if (!mouseinitialized) + return; + if (!mouseactive) + return; + + if (restore_spi) + SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); + + mouseactive = false; + + ClipCursor (NULL); + ReleaseCapture (); + while (ShowCursor (TRUE) < 0) + ; +} + + + +/* +=========== +IN_StartupMouse +=========== +*/ +void IN_StartupMouse (void) +{ + cvar_t *cv; + + cv = Cvar_Get ("in_initmouse", "1", CVAR_NOSET); + if ( !cv->value ) + return; + + mouseinitialized = true; + mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); + mouse_buttons = 3; +} + +/* +=========== +IN_MouseEvent +=========== +*/ +void IN_MouseEvent (int mstate) +{ + int i; + + if (!mouseinitialized) + return; + +// perform button actions + for (i=0 ; ivalue) + { + mouse_x = (mx + old_mouse_x) * 0.5; + mouse_y = (my + old_mouse_y) * 0.5; + } + else + { + mouse_x = mx; + mouse_y = my; + } + + old_mouse_x = mx; + old_mouse_y = my; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + +// add mouse X/Y movement to cmd + if ( (in_strafe.state & 1) || (lookstrafe->value && mlooking )) + cmd->sidemove += m_side->value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw->value * mouse_x; + + if ( (mlooking || freelook->value) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch->value * mouse_y; + } + else + { + cmd->forwardmove -= m_forward->value * mouse_y; + } + + // force the mouse to the center, so there's room to move + if (mx || my) + SetCursorPos (window_center_x, window_center_y); +} + + +/* +========================================================================= + +VIEW CENTERING + +========================================================================= +*/ + +cvar_t *v_centermove; +cvar_t *v_centerspeed; + + +/* +=========== +IN_Init +=========== +*/ +void IN_Init (void) +{ + // mouse variables + m_filter = Cvar_Get ("m_filter", "0", 0); + in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE); + + // joystick variables + in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE); + joy_name = Cvar_Get ("joy_name", "joystick", 0); + joy_advanced = Cvar_Get ("joy_advanced", "0", 0); + joy_advaxisx = Cvar_Get ("joy_advaxisx", "0", 0); + joy_advaxisy = Cvar_Get ("joy_advaxisy", "0", 0); + joy_advaxisz = Cvar_Get ("joy_advaxisz", "0", 0); + joy_advaxisr = Cvar_Get ("joy_advaxisr", "0", 0); + joy_advaxisu = Cvar_Get ("joy_advaxisu", "0", 0); + joy_advaxisv = Cvar_Get ("joy_advaxisv", "0", 0); + joy_forwardthreshold = Cvar_Get ("joy_forwardthreshold", "0.15", 0); + joy_sidethreshold = Cvar_Get ("joy_sidethreshold", "0.15", 0); + joy_upthreshold = Cvar_Get ("joy_upthreshold", "0.15", 0); + joy_pitchthreshold = Cvar_Get ("joy_pitchthreshold", "0.15", 0); + joy_yawthreshold = Cvar_Get ("joy_yawthreshold", "0.15", 0); + joy_forwardsensitivity = Cvar_Get ("joy_forwardsensitivity", "-1", 0); + joy_sidesensitivity = Cvar_Get ("joy_sidesensitivity", "-1", 0); + joy_upsensitivity = Cvar_Get ("joy_upsensitivity", "-1", 0); + joy_pitchsensitivity = Cvar_Get ("joy_pitchsensitivity", "1", 0); + joy_yawsensitivity = Cvar_Get ("joy_yawsensitivity", "-1", 0); + + // centering + v_centermove = Cvar_Get ("v_centermove", "0.15", 0); + v_centerspeed = Cvar_Get ("v_centerspeed", "500", 0); + + Cmd_AddCommand ("+mlook", IN_MLookDown); + Cmd_AddCommand ("-mlook", IN_MLookUp); + + Cmd_AddCommand ("joy_advancedupdate", Joy_AdvancedUpdate_f); + + IN_StartupMouse (); + IN_StartupJoystick (); +} + +/* +=========== +IN_Shutdown +=========== +*/ +void IN_Shutdown (void) +{ + IN_DeactivateMouse (); +} + + +/* +=========== +IN_Activate + +Called when the main window gains or loses focus. +The window may have been destroyed and recreated +between a deactivate and an activate. +=========== +*/ +void IN_Activate (qboolean active) +{ + in_appactive = active; + mouseactive = !active; // force a new window check or turn off +} + + +/* +================== +IN_Frame + +Called every frame, even if not generating commands +================== +*/ +void IN_Frame (void) +{ + if (!mouseinitialized) + return; + + if (!in_mouse || !in_appactive) + { + IN_DeactivateMouse (); + return; + } + + if ( !cl.refresh_prepped + || cls.key_dest == key_console + || cls.key_dest == key_menu) + { + // temporarily deactivate if in fullscreen + if (Cvar_VariableValue ("vid_fullscreen") == 0) + { + IN_DeactivateMouse (); + return; + } + } + + IN_ActivateMouse (); +} + +/* +=========== +IN_Move +=========== +*/ +void IN_Move (usercmd_t *cmd) +{ + IN_MouseMove (cmd); + + if (ActiveApp) + IN_JoyMove (cmd); +} + + +/* +=================== +IN_ClearStates +=================== +*/ +void IN_ClearStates (void) +{ + mx_accum = 0; + my_accum = 0; + mouse_oldbuttonstate = 0; +} + + +/* +========================================================================= + +JOYSTICK + +========================================================================= +*/ + +/* +=============== +IN_StartupJoystick +=============== +*/ +void IN_StartupJoystick (void) +{ + int numdevs; + JOYCAPS jc; + MMRESULT mmr; + cvar_t *cv; + + // assume no joystick + joy_avail = false; + + // abort startup if user requests no joystick + cv = Cvar_Get ("in_initjoy", "1", CVAR_NOSET); + if ( !cv->value ) + return; + + // verify joystick driver is present + if ((numdevs = joyGetNumDevs ()) == 0) + { +// Com_Printf ("\njoystick not found -- driver not present\n\n"); + return; + } + + // cycle through the joystick ids for the first valid one + for (joy_id=0 ; joy_idvalue == 0.0) + { + // default joystick initialization + // 2 axes only with joystick control + dwAxisMap[JOY_AXIS_X] = AxisTurn; + // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS; + dwAxisMap[JOY_AXIS_Y] = AxisForward; + // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS; + } + else + { + if (strcmp (joy_name->string, "joystick") != 0) + { + // notify user of advanced controller + Com_Printf ("\n%s configured\n\n", joy_name->string); + } + + // advanced initialization here + // data supplied by user via joy_axisn cvars + dwTemp = (DWORD) joy_advaxisx->value; + dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f; + dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS; + dwTemp = (DWORD) joy_advaxisy->value; + dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f; + dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS; + dwTemp = (DWORD) joy_advaxisz->value; + dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f; + dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS; + dwTemp = (DWORD) joy_advaxisr->value; + dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f; + dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS; + dwTemp = (DWORD) joy_advaxisu->value; + dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f; + dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS; + dwTemp = (DWORD) joy_advaxisv->value; + dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f; + dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS; + } + + // compute the axes to collect from DirectInput + joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV; + for (i = 0; i < JOY_MAX_AXES; i++) + { + if (dwAxisMap[i] != AxisNada) + { + joy_flags |= dwAxisFlags[i]; + } + } +} + + +/* +=========== +IN_Commands +=========== +*/ +void IN_Commands (void) +{ + int i, key_index; + DWORD buttonstate, povstate; + + if (!joy_avail) + { + return; + } + + + // loop through the joystick buttons + // key a joystick event or auxillary event for higher number buttons for each state change + buttonstate = ji.dwButtons; + for (i=0 ; i < joy_numbuttons ; i++) + { + if ( (buttonstate & (1<value) + { + return; + } + + // collect the joystick data, if possible + if (IN_ReadJoystick () != true) + { + return; + } + + if ( (in_speed.state & 1) ^ (int)cl_run->value) + speed = 2; + else + speed = 1; + aspeed = speed * cls.frametime; + + // loop through the axes + for (i = 0; i < JOY_MAX_AXES; i++) + { + // get the floating point zero-centered, potentially-inverted data for the current axis + fAxisValue = (float) *pdwRawValue[i]; + // move centerpoint to zero + fAxisValue -= 32768.0; + + // convert range from -32768..32767 to -1..1 + fAxisValue /= 32768.0; + + switch (dwAxisMap[i]) + { + case AxisForward: + if ((joy_advanced->value == 0.0) && mlooking) + { + // user wants forward control to become look control + if (fabs(fAxisValue) > joy_pitchthreshold->value) + { + // if mouse invert is on, invert the joystick pitch value + // only absolute control support here (joy_advanced is false) + if (m_pitch->value < 0.0) + { + cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value; + } + else + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value; + } + } + } + else + { + // user wants forward control to be forward control + if (fabs(fAxisValue) > joy_forwardthreshold->value) + { + cmd->forwardmove += (fAxisValue * joy_forwardsensitivity->value) * speed * cl_forwardspeed->value; + } + } + break; + + case AxisSide: + if (fabs(fAxisValue) > joy_sidethreshold->value) + { + cmd->sidemove += (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value; + } + break; + + case AxisUp: + if (fabs(fAxisValue) > joy_upthreshold->value) + { + cmd->upmove += (fAxisValue * joy_upsensitivity->value) * speed * cl_upspeed->value; + } + break; + + case AxisTurn: + if ((in_strafe.state & 1) || (lookstrafe->value && mlooking)) + { + // user wants turn control to become side control + if (fabs(fAxisValue) > joy_sidethreshold->value) + { + cmd->sidemove -= (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value; + } + } + else + { + // user wants turn control to be turn control + if (fabs(fAxisValue) > joy_yawthreshold->value) + { + if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) + { + cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * aspeed * cl_yawspeed->value; + } + else + { + cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * speed * 180.0; + } + + } + } + break; + + case AxisLook: + if (mlooking) + { + if (fabs(fAxisValue) > joy_pitchthreshold->value) + { + // pitch movement detected and pitch movement desired by user + if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value; + } + else + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * speed * 180.0; + } + } + } + break; + + default: + break; + } + } +} + diff --git a/win32/net_wins.c b/win32/net_wins.c new file mode 100644 index 000000000..82b6b299f --- /dev/null +++ b/win32/net_wins.c @@ -0,0 +1,842 @@ +/* +Copyright (C) 1997-2001 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 "winsock.h" +#include "wsipx.h" +#include "../qcommon/qcommon.h" + +#define MAX_LOOPBACK 4 + +typedef struct +{ + byte data[MAX_MSGLEN]; + int datalen; +} loopmsg_t; + +typedef struct +{ + loopmsg_t msgs[MAX_LOOPBACK]; + int get, send; +} loopback_t; + + +cvar_t *net_shownet; +static cvar_t *noudp; +static cvar_t *noipx; + +loopback_t loopbacks[2]; +int ip_sockets[2]; +int ipx_sockets[2]; + +char *NET_ErrorString (void); + +//============================================================================= + +void NetadrToSockadr (netadr_t *a, struct sockaddr *s) +{ + memset (s, 0, sizeof(*s)); + + if (a->type == NA_BROADCAST) + { + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_port = a->port; + ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (a->type == NA_IP) + { + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; + ((struct sockaddr_in *)s)->sin_port = a->port; + } + else if (a->type == NA_IPX) + { + ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; + memcpy(((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4); + memcpy(((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6); + ((struct sockaddr_ipx *)s)->sa_socket = a->port; + } + else if (a->type == NA_BROADCAST_IPX) + { + ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; + memset(((struct sockaddr_ipx *)s)->sa_netnum, 0, 4); + memset(((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6); + ((struct sockaddr_ipx *)s)->sa_socket = a->port; + } +} + +void SockadrToNetadr (struct sockaddr *s, netadr_t *a) +{ + if (s->sa_family == AF_INET) + { + a->type = NA_IP; + *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; + a->port = ((struct sockaddr_in *)s)->sin_port; + } + else if (s->sa_family == AF_IPX) + { + a->type = NA_IPX; + memcpy(&a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4); + memcpy(&a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6); + a->port = ((struct sockaddr_ipx *)s)->sa_socket; + } +} + + +qboolean NET_CompareAdr (netadr_t a, netadr_t b) +{ + if (a.type != b.type) + return false; + + if (a.type == NA_LOOPBACK) + return TRUE; + + if (a.type == NA_IP) + { + if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port) + return true; + return false; + } + + if (a.type == NA_IPX) + { + if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port) + return true; + return false; + } +} + +/* +=================== +NET_CompareBaseAdr + +Compares without the port +=================== +*/ +qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) +{ + if (a.type != b.type) + return false; + + if (a.type == NA_LOOPBACK) + return TRUE; + + if (a.type == NA_IP) + { + if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3]) + return true; + return false; + } + + if (a.type == NA_IPX) + { + if ((memcmp(a.ipx, b.ipx, 10) == 0)) + return true; + return false; + } +} + +char *NET_AdrToString (netadr_t a) +{ + static char s[64]; + + if (a.type == NA_LOOPBACK) + Com_sprintf (s, sizeof(s), "loopback"); + else if (a.type == NA_IP) + Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port)); + else + Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], ntohs(a.port)); + + return s; +} + + +/* +============= +NET_StringToAdr + +localhost +idnewt +idnewt:28000 +192.246.40.70 +192.246.40.70:28000 +============= +*/ +#define DO(src,dest) \ + copy[0] = s[src]; \ + copy[1] = s[src + 1]; \ + sscanf (copy, "%x", &val); \ + ((struct sockaddr_ipx *)sadr)->dest = val + +qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr) +{ + struct hostent *h; + char *colon; + int val; + char copy[128]; + + memset (sadr, 0, sizeof(*sadr)); + + if ((strlen(s) >= 23) && (s[8] == ':') && (s[21] == ':')) // check for an IPX address + { + ((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX; + copy[2] = 0; + 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]); + sscanf (&s[22], "%u", &val); + ((struct sockaddr_ipx *)sadr)->sa_socket = htons((unsigned short)val); + } + else + { + ((struct sockaddr_in *)sadr)->sin_family = AF_INET; + + ((struct sockaddr_in *)sadr)->sin_port = 0; + + strcpy (copy, s); + // strip off a trailing :port if present + for (colon = copy ; *colon ; colon++) + if (*colon == ':') + { + *colon = 0; + ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1)); + } + + if (copy[0] >= '0' && copy[0] <= '9') + { + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy); + } + else + { + if (! (h = gethostbyname(copy)) ) + return 0; + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; + } + } + + return true; +} + +#undef DO + +/* +============= +NET_StringToAdr + +localhost +idnewt +idnewt:28000 +192.246.40.70 +192.246.40.70:28000 +============= +*/ +qboolean NET_StringToAdr (char *s, netadr_t *a) +{ + struct sockaddr sadr; + + if (!strcmp (s, "localhost")) + { + memset (a, 0, sizeof(*a)); + a->type = NA_LOOPBACK; + return true; + } + + if (!NET_StringToSockaddr (s, &sadr)) + return false; + + SockadrToNetadr (&sadr, a); + + return true; +} + + +qboolean NET_IsLocalAddress (netadr_t adr) +{ + return adr.type == NA_LOOPBACK; +} + +/* +============================================================================= + +LOOPBACK BUFFERS FOR LOCAL PLAYER + +============================================================================= +*/ + +qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) +{ + int i; + loopback_t *loop; + + loop = &loopbacks[sock]; + + if (loop->send - loop->get > MAX_LOOPBACK) + loop->get = loop->send - MAX_LOOPBACK; + + if (loop->get >= loop->send) + return false; + + i = loop->get & (MAX_LOOPBACK-1); + loop->get++; + + memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen); + net_message->cursize = loop->msgs[i].datalen; + memset (net_from, 0, sizeof(*net_from)); + net_from->type = NA_LOOPBACK; + return true; + +} + + +void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) +{ + int i; + loopback_t *loop; + + loop = &loopbacks[sock^1]; + + i = loop->send & (MAX_LOOPBACK-1); + loop->send++; + + memcpy (loop->msgs[i].data, data, length); + loop->msgs[i].datalen = length; +} + +//============================================================================= + +qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) +{ + int ret; + struct sockaddr from; + int fromlen; + int net_socket; + int protocol; + int err; + + if (NET_GetLoopPacket (sock, net_from, net_message)) + return true; + + for (protocol = 0 ; protocol < 2 ; protocol++) + { + if (protocol == 0) + net_socket = ip_sockets[sock]; + else + net_socket = ipx_sockets[sock]; + + if (!net_socket) + continue; + + fromlen = sizeof(from); + ret = recvfrom (net_socket, net_message->data, net_message->maxsize + , 0, (struct sockaddr *)&from, &fromlen); + if (ret == -1) + { + err = WSAGetLastError(); + + if (err == WSAEWOULDBLOCK) + continue; + if (dedicated->value) // let dedicated servers continue after errors + Com_Printf ("NET_GetPacket: %s", NET_ErrorString()); + else + Com_Error (ERR_DROP, "NET_GetPacket: %s", NET_ErrorString()); + continue; + } + + SockadrToNetadr (&from, net_from); + + if (ret == net_message->maxsize) + { + Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); + continue; + } + + net_message->cursize = ret; + return true; + } + + return false; +} + +//============================================================================= + +void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) +{ + int ret; + struct sockaddr addr; + int net_socket; + + if ( to.type == NA_LOOPBACK ) + { + NET_SendLoopPacket (sock, length, data, to); + return; + } + + if (to.type == NA_BROADCAST) + { + net_socket = ip_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_IP) + { + net_socket = ip_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_IPX) + { + net_socket = ipx_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_BROADCAST_IPX) + { + net_socket = ipx_sockets[sock]; + if (!net_socket) + return; + } + else + Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); + + NetadrToSockadr (&to, &addr); + + ret = sendto (net_socket, data, length, 0, &addr, sizeof(addr) ); + if (ret == -1) + { + int err = WSAGetLastError(); + + // wouldblock is silent + if (err == WSAEWOULDBLOCK) + return; + + // some PPP links dont allow broadcasts + if ((err == WSAEADDRNOTAVAIL) && ((to.type == NA_BROADCAST) || (to.type == NA_BROADCAST_IPX))) + return; + + if (dedicated->value) // let dedicated servers continue after errors + { + Com_Printf ("NET_SendPacket ERROR: %s\n", NET_ErrorString()); + } + else + { + if (err == WSAEADDRNOTAVAIL) + { + Com_DPrintf ("NET_SendPacket Warning: %s : %s\n", NET_ErrorString(), NET_AdrToString (to)); + } + else + { + Com_Error (ERR_DROP, "NET_SendPacket ERROR: %s\n", NET_ErrorString()); + } + } + } +} + + +//============================================================================= + + +/* +==================== +NET_Socket +==================== +*/ +int NET_IPSocket (char *net_interface, int port) +{ + int newsocket; + struct sockaddr_in address; + qboolean _true = true; + int i = 1; + int err; + + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + err = WSAGetLastError(); + if (err != WSAEAFNOSUPPORT) + Com_Printf ("WARNING: UDP_OpenSocket: socket: %s", NET_ErrorString()); + return 0; + } + + // make it non-blocking + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + { + Com_Printf ("WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString()); + return 0; + } + + // make it broadcast capable + if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) + { + Com_Printf ("WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString()); + return 0; + } + + if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) + address.sin_addr.s_addr = INADDR_ANY; + else + NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); + + if (port == PORT_ANY) + address.sin_port = 0; + else + address.sin_port = htons((short)port); + + address.sin_family = AF_INET; + + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + { + Com_Printf ("WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); + closesocket (newsocket); + return 0; + } + + return newsocket; +} + + +/* +==================== +NET_OpenIP +==================== +*/ +void NET_OpenIP (void) +{ + cvar_t *ip; + int port; + int dedicated; + + ip = Cvar_Get ("ip", "localhost", CVAR_NOSET); + + dedicated = Cvar_VariableValue ("dedicated"); + + if (!ip_sockets[NS_SERVER]) + { + port = Cvar_Get("ip_hostport", "0", CVAR_NOSET)->value; + if (!port) + { + port = Cvar_Get("hostport", "0", CVAR_NOSET)->value; + if (!port) + { + port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value; + } + } + ip_sockets[NS_SERVER] = NET_IPSocket (ip->string, port); + if (!ip_sockets[NS_SERVER] && dedicated) + Com_Error (ERR_FATAL, "Couldn't allocate dedicated server IP port"); + } + + + // dedicated servers don't need client ports + if (dedicated) + return; + + if (!ip_sockets[NS_CLIENT]) + { + port = Cvar_Get("ip_clientport", "0", CVAR_NOSET)->value; + if (!port) + { + port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value; + if (!port) + port = PORT_ANY; + } + ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, port); + if (!ip_sockets[NS_CLIENT]) + ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, PORT_ANY); + } +} + + +/* +==================== +IPX_Socket +==================== +*/ +int NET_IPXSocket (int port) +{ + int newsocket; + struct sockaddr_ipx address; + int _true = 1; + int err; + + if ((newsocket = socket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1) + { + err = WSAGetLastError(); + if (err != WSAEAFNOSUPPORT) + Com_Printf ("WARNING: IPX_Socket: socket: %s\n", NET_ErrorString()); + return 0; + } + + // make it non-blocking + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + { + Com_Printf ("WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString()); + return 0; + } + + // make it broadcast capable + if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) == -1) + { + Com_Printf ("WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString()); + return 0; + } + + address.sa_family = AF_IPX; + memset (address.sa_netnum, 0, 4); + memset (address.sa_nodenum, 0, 6); + if (port == PORT_ANY) + address.sa_socket = 0; + else + address.sa_socket = htons((short)port); + + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + { + Com_Printf ("WARNING: IPX_Socket: bind: %s\n", NET_ErrorString()); + closesocket (newsocket); + return 0; + } + + return newsocket; +} + + +/* +==================== +NET_OpenIPX +==================== +*/ +void NET_OpenIPX (void) +{ + int port; + int dedicated; + + dedicated = Cvar_VariableValue ("dedicated"); + + if (!ipx_sockets[NS_SERVER]) + { + port = Cvar_Get("ipx_hostport", "0", CVAR_NOSET)->value; + if (!port) + { + port = Cvar_Get("hostport", "0", CVAR_NOSET)->value; + if (!port) + { + port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value; + } + } + ipx_sockets[NS_SERVER] = NET_IPXSocket (port); + } + + // dedicated servers don't need client ports + if (dedicated) + return; + + if (!ipx_sockets[NS_CLIENT]) + { + port = Cvar_Get("ipx_clientport", "0", CVAR_NOSET)->value; + if (!port) + { + port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value; + if (!port) + port = PORT_ANY; + } + ipx_sockets[NS_CLIENT] = NET_IPXSocket (port); + if (!ipx_sockets[NS_CLIENT]) + ipx_sockets[NS_CLIENT] = NET_IPXSocket (PORT_ANY); + } +} + + +/* +==================== +NET_Config + +A single player game will only use the loopback code +==================== +*/ +void NET_Config (qboolean multiplayer) +{ + int i; + static qboolean old_config; + + if (old_config == multiplayer) + return; + + old_config = multiplayer; + + if (!multiplayer) + { // shut down any existing sockets + for (i=0 ; i<2 ; i++) + { + if (ip_sockets[i]) + { + closesocket (ip_sockets[i]); + ip_sockets[i] = 0; + } + if (ipx_sockets[i]) + { + closesocket (ipx_sockets[i]); + ipx_sockets[i] = 0; + } + } + } + else + { // open sockets + if (! noudp->value) + NET_OpenIP (); + if (! noipx->value) + NET_OpenIPX (); + } +} + +// sleeps msec or until net socket is ready +void NET_Sleep(int msec) +{ + struct timeval timeout; + fd_set fdset; + extern cvar_t *dedicated; + int i; + + if (!dedicated || !dedicated->value) + return; // we're not a server, just run full speed + + FD_ZERO(&fdset); + i = 0; + if (ip_sockets[NS_SERVER]) { + FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket + i = ip_sockets[NS_SERVER]; + } + if (ipx_sockets[NS_SERVER]) { + FD_SET(ipx_sockets[NS_SERVER], &fdset); // network socket + if (ipx_sockets[NS_SERVER] > i) + i = ipx_sockets[NS_SERVER]; + } + timeout.tv_sec = msec/1000; + timeout.tv_usec = (msec%1000)*1000; + select(i+1, &fdset, NULL, NULL, &timeout); +} + +//=================================================================== + + +static WSADATA winsockdata; + +/* +==================== +NET_Init +==================== +*/ +void NET_Init (void) +{ + WORD wVersionRequested; + int r; + + wVersionRequested = MAKEWORD(1, 1); + + r = WSAStartup (MAKEWORD(1, 1), &winsockdata); + + if (r) + Com_Error (ERR_FATAL,"Winsock initialization failed."); + + Com_Printf("Winsock Initialized\n"); + + noudp = Cvar_Get ("noudp", "0", CVAR_NOSET); + noipx = Cvar_Get ("noipx", "0", CVAR_NOSET); + + net_shownet = Cvar_Get ("net_shownet", "0", 0); +} + + +/* +==================== +NET_Shutdown +==================== +*/ +void NET_Shutdown (void) +{ + NET_Config (false); // close sockets + + WSACleanup (); +} + + +/* +==================== +NET_ErrorString +==================== +*/ +char *NET_ErrorString (void) +{ + int code; + + code = WSAGetLastError (); + switch (code) + { + case WSAEINTR: return "WSAEINTR"; + case WSAEBADF: return "WSAEBADF"; + case WSAEACCES: return "WSAEACCES"; + case WSAEDISCON: return "WSAEDISCON"; + case WSAEFAULT: return "WSAEFAULT"; + case WSAEINVAL: return "WSAEINVAL"; + case WSAEMFILE: return "WSAEMFILE"; + case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK"; + case WSAEINPROGRESS: return "WSAEINPROGRESS"; + case WSAEALREADY: return "WSAEALREADY"; + case WSAENOTSOCK: return "WSAENOTSOCK"; + case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ"; + case WSAEMSGSIZE: return "WSAEMSGSIZE"; + case WSAEPROTOTYPE: return "WSAEPROTOTYPE"; + case WSAENOPROTOOPT: return "WSAENOPROTOOPT"; + case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT"; + case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT"; + case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP"; + case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT"; + case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT"; + case WSAEADDRINUSE: return "WSAEADDRINUSE"; + case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL"; + case WSAENETDOWN: return "WSAENETDOWN"; + case WSAENETUNREACH: return "WSAENETUNREACH"; + case WSAENETRESET: return "WSAENETRESET"; + case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR"; + case WSAECONNRESET: return "WSAECONNRESET"; + case WSAENOBUFS: return "WSAENOBUFS"; + case WSAEISCONN: return "WSAEISCONN"; + case WSAENOTCONN: return "WSAENOTCONN"; + case WSAESHUTDOWN: return "WSAESHUTDOWN"; + case WSAETOOMANYREFS: return "WSAETOOMANYREFS"; + case WSAETIMEDOUT: return "WSAETIMEDOUT"; + case WSAECONNREFUSED: return "WSAECONNREFUSED"; + case WSAELOOP: return "WSAELOOP"; + case WSAENAMETOOLONG: return "WSAENAMETOOLONG"; + case WSAEHOSTDOWN: return "WSAEHOSTDOWN"; + case WSASYSNOTREADY: return "WSASYSNOTREADY"; + case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED"; + case WSANOTINITIALISED: return "WSANOTINITIALISED"; + case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND"; + case WSATRY_AGAIN: return "WSATRY_AGAIN"; + case WSANO_RECOVERY: return "WSANO_RECOVERY"; + case WSANO_DATA: return "WSANO_DATA"; + default: return "NO ERROR"; + } +} diff --git a/win32/q2.aps b/win32/q2.aps new file mode 100644 index 000000000..37df322f2 Binary files /dev/null and b/win32/q2.aps differ diff --git a/win32/q2.ico b/win32/q2.ico new file mode 100644 index 000000000..a40f68696 Binary files /dev/null and b/win32/q2.ico differ diff --git a/win32/q2.rc b/win32/q2.rc new file mode 100644 index 000000000..aa7a0be87 --- /dev/null +++ b/win32/q2.rc @@ -0,0 +1,72 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "q2.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/win32/q_shwin.c b/win32/q_shwin.c new file mode 100644 index 000000000..775a4106e --- /dev/null +++ b/win32/q_shwin.c @@ -0,0 +1,215 @@ +/* +Copyright (C) 1997-2001 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 "../qcommon/qcommon.h" +#include "winquake.h" +#include +#include +#include +#include +#include +#include + +//=============================================================================== + +int hunkcount; + + +byte *membase; +int hunkmaxsize; +int cursize; + +#define VIRTUAL_ALLOC + +void *Hunk_Begin (int maxsize) +{ + // reserve a huge chunk of memory, but don't commit any yet + cursize = 0; + hunkmaxsize = maxsize; +#ifdef VIRTUAL_ALLOC + membase = VirtualAlloc (NULL, maxsize, MEM_RESERVE, PAGE_NOACCESS); +#else + membase = malloc (maxsize); + memset (membase, 0, maxsize); +#endif + if (!membase) + Sys_Error ("VirtualAlloc reserve failed"); + return (void *)membase; +} + +void *Hunk_Alloc (int size) +{ + void *buf; + + // round to cacheline + size = (size+31)&~31; + +#ifdef VIRTUAL_ALLOC + // commit pages as needed +// buf = VirtualAlloc (membase+cursize, size, MEM_COMMIT, PAGE_READWRITE); + buf = VirtualAlloc (membase, cursize+size, MEM_COMMIT, PAGE_READWRITE); + if (!buf) + { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buf, 0, NULL); + Sys_Error ("VirtualAlloc commit failed.\n%s", buf); + } +#endif + cursize += size; + if (cursize > hunkmaxsize) + Sys_Error ("Hunk_Alloc overflow"); + + return (void *)(membase+cursize-size); +} + +int Hunk_End (void) +{ + + // free the remaining unused virtual memory +#if 0 + void *buf; + + // write protect it + buf = VirtualAlloc (membase, cursize, MEM_COMMIT, PAGE_READONLY); + if (!buf) + Sys_Error ("VirtualAlloc commit failed"); +#endif + + hunkcount++; +//Com_Printf ("hunkcount: %i\n", hunkcount); + return cursize; +} + +void Hunk_Free (void *base) +{ + if ( base ) +#ifdef VIRTUAL_ALLOC + VirtualFree (base, 0, MEM_RELEASE); +#else + free (base); +#endif + + hunkcount--; +} + +//=============================================================================== + + +/* +================ +Sys_Milliseconds +================ +*/ +int curtime; +int Sys_Milliseconds (void) +{ + static int base; + static qboolean initialized = false; + + if (!initialized) + { // let base retain 16 bits of effectively random data + base = timeGetTime() & 0xffff0000; + initialized = true; + } + curtime = timeGetTime() - base; + + return curtime; +} + +void Sys_Mkdir (char *path) +{ + _mkdir (path); +} + +//============================================ + +char findbase[MAX_OSPATH]; +char findpath[MAX_OSPATH]; +int findhandle; + +static qboolean CompareAttributes( unsigned found, unsigned musthave, unsigned canthave ) +{ + if ( ( found & _A_RDONLY ) && ( canthave & SFF_RDONLY ) ) + return false; + if ( ( found & _A_HIDDEN ) && ( canthave & SFF_HIDDEN ) ) + return false; + if ( ( found & _A_SYSTEM ) && ( canthave & SFF_SYSTEM ) ) + return false; + if ( ( found & _A_SUBDIR ) && ( canthave & SFF_SUBDIR ) ) + return false; + if ( ( found & _A_ARCH ) && ( canthave & SFF_ARCH ) ) + return false; + + if ( ( musthave & SFF_RDONLY ) && !( found & _A_RDONLY ) ) + return false; + if ( ( musthave & SFF_HIDDEN ) && !( found & _A_HIDDEN ) ) + return false; + if ( ( musthave & SFF_SYSTEM ) && !( found & _A_SYSTEM ) ) + return false; + if ( ( musthave & SFF_SUBDIR ) && !( found & _A_SUBDIR ) ) + return false; + if ( ( musthave & SFF_ARCH ) && !( found & _A_ARCH ) ) + return false; + + return true; +} + +char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave ) +{ + struct _finddata_t findinfo; + + if (findhandle) + Sys_Error ("Sys_BeginFind without close"); + findhandle = 0; + + COM_FilePath (path, findbase); + findhandle = _findfirst (path, &findinfo); + if (findhandle == -1) + return NULL; + if ( !CompareAttributes( findinfo.attrib, musthave, canthave ) ) + return NULL; + Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name); + return findpath; +} + +char *Sys_FindNext ( unsigned musthave, unsigned canthave ) +{ + struct _finddata_t findinfo; + + if (findhandle == -1) + return NULL; + if (_findnext (findhandle, &findinfo) == -1) + return NULL; + if ( !CompareAttributes( findinfo.attrib, musthave, canthave ) ) + return NULL; + + Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name); + return findpath; +} + +void Sys_FindClose (void) +{ + if (findhandle != -1) + _findclose (findhandle); + findhandle = 0; +} + + +//============================================ + diff --git a/win32/qe3.ico b/win32/qe3.ico new file mode 100644 index 000000000..0b7ec3902 Binary files /dev/null and b/win32/qe3.ico differ diff --git a/win32/qgl_win.c b/win32/qgl_win.c new file mode 100644 index 000000000..146aa734e --- /dev/null +++ b/win32/qgl_win.c @@ -0,0 +1,4133 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +/* +** QGL_WIN.C +** +** This file implements the operating system binding of GL to QGL function +** pointers. When doing a port of Quake2 you must implement the following +** two functions: +** +** QGL_Init() - loads libraries, assigns function pointers, etc. +** QGL_Shutdown() - unloads libraries, NULLs function pointers +*/ +#include +#include "../ref_gl/gl_local.h" +#include "glw_win.h" + +int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); +int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); +int ( WINAPI * qwglGetPixelFormat)(HDC); +BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); +BOOL ( WINAPI * qwglSwapBuffers)(HDC); + +BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT); +HGLRC ( WINAPI * qwglCreateContext)(HDC); +HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int); +BOOL ( WINAPI * qwglDeleteContext)(HGLRC); +HGLRC ( WINAPI * qwglGetCurrentContext)(VOID); +HDC ( WINAPI * qwglGetCurrentDC)(VOID); +PROC ( WINAPI * qwglGetProcAddress)(LPCSTR); +BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC); +BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC); +BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD); + +BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT, + FLOAT, int, LPGLYPHMETRICSFLOAT); + +BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, + LPLAYERPLANEDESCRIPTOR); +int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, + CONST COLORREF *); +int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, + COLORREF *); +BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL); +BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT); + +void ( APIENTRY * qglAccum )(GLenum op, GLfloat value); +void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref); +GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); +void ( APIENTRY * qglArrayElement )(GLint i); +void ( APIENTRY * qglBegin )(GLenum mode); +void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture); +void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor); +void ( APIENTRY * qglCallList )(GLuint list); +void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists); +void ( APIENTRY * qglClear )(GLbitfield mask); +void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +void ( APIENTRY * qglClearDepth )(GLclampd depth); +void ( APIENTRY * qglClearIndex )(GLfloat c); +void ( APIENTRY * qglClearStencil )(GLint s); +void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation); +void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue); +void ( APIENTRY * qglColor3bv )(const GLbyte *v); +void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue); +void ( APIENTRY * qglColor3dv )(const GLdouble *v); +void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue); +void ( APIENTRY * qglColor3fv )(const GLfloat *v); +void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue); +void ( APIENTRY * qglColor3iv )(const GLint *v); +void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue); +void ( APIENTRY * qglColor3sv )(const GLshort *v); +void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue); +void ( APIENTRY * qglColor3ubv )(const GLubyte *v); +void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue); +void ( APIENTRY * qglColor3uiv )(const GLuint *v); +void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue); +void ( APIENTRY * qglColor3usv )(const GLushort *v); +void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +void ( APIENTRY * qglColor4bv )(const GLbyte *v); +void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +void ( APIENTRY * qglColor4dv )(const GLdouble *v); +void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +void ( APIENTRY * qglColor4fv )(const GLfloat *v); +void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha); +void ( APIENTRY * qglColor4iv )(const GLint *v); +void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); +void ( APIENTRY * qglColor4sv )(const GLshort *v); +void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +void ( APIENTRY * qglColor4ubv )(const GLubyte *v); +void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); +void ( APIENTRY * qglColor4uiv )(const GLuint *v); +void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); +void ( APIENTRY * qglColor4usv )(const GLushort *v); +void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode); +void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +void ( APIENTRY * qglCullFace )(GLenum mode); +void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range); +void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures); +void ( APIENTRY * qglDepthFunc )(GLenum func); +void ( APIENTRY * qglDepthMask )(GLboolean flag); +void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar); +void ( APIENTRY * qglDisable )(GLenum cap); +void ( APIENTRY * qglDisableClientState )(GLenum array); +void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count); +void ( APIENTRY * qglDrawBuffer )(GLenum mode); +void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglEdgeFlag )(GLboolean flag); +void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag); +void ( APIENTRY * qglEnable )(GLenum cap); +void ( APIENTRY * qglEnableClientState )(GLenum array); +void ( APIENTRY * qglEnd )(void); +void ( APIENTRY * qglEndList )(void); +void ( APIENTRY * qglEvalCoord1d )(GLdouble u); +void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u); +void ( APIENTRY * qglEvalCoord1f )(GLfloat u); +void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u); +void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v); +void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u); +void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v); +void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u); +void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2); +void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +void ( APIENTRY * qglEvalPoint1 )(GLint i); +void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j); +void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); +void ( APIENTRY * qglFinish )(void); +void ( APIENTRY * qglFlush )(void); +void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param); +void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params); +void ( APIENTRY * qglFogi )(GLenum pname, GLint param); +void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params); +void ( APIENTRY * qglFrontFace )(GLenum mode); +void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLuint ( APIENTRY * qglGenLists )(GLsizei range); +void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures); +void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params); +void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation); +void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params); +GLenum ( APIENTRY * qglGetError )(void); +void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params); +void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params); +void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v); +void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v); +void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v); +void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params); +void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values); +void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values); +void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values); +void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params); +void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask); +const GLubyte * ( APIENTRY * qglGetString )(GLenum name); +void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params); +void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); +void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); +void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); +void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); +void ( APIENTRY * qglHint )(GLenum target, GLenum mode); +void ( APIENTRY * qglIndexMask )(GLuint mask); +void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglIndexd )(GLdouble c); +void ( APIENTRY * qglIndexdv )(const GLdouble *c); +void ( APIENTRY * qglIndexf )(GLfloat c); +void ( APIENTRY * qglIndexfv )(const GLfloat *c); +void ( APIENTRY * qglIndexi )(GLint c); +void ( APIENTRY * qglIndexiv )(const GLint *c); +void ( APIENTRY * qglIndexs )(GLshort c); +void ( APIENTRY * qglIndexsv )(const GLshort *c); +void ( APIENTRY * qglIndexub )(GLubyte c); +void ( APIENTRY * qglIndexubv )(const GLubyte *c); +void ( APIENTRY * qglInitNames )(void); +void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); +GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap); +GLboolean ( APIENTRY * qglIsList )(GLuint list); +GLboolean ( APIENTRY * qglIsTexture )(GLuint texture); +void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param); +void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params); +void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param); +void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params); +void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param); +void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param); +void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params); +void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern); +void ( APIENTRY * qglLineWidth )(GLfloat width); +void ( APIENTRY * qglListBase )(GLuint base); +void ( APIENTRY * qglLoadIdentity )(void); +void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m); +void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m); +void ( APIENTRY * qglLoadName )(GLuint name); +void ( APIENTRY * qglLogicOp )(GLenum opcode); +void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); +void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); +void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param); +void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param); +void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params); +void ( APIENTRY * qglMatrixMode )(GLenum mode); +void ( APIENTRY * qglMultMatrixd )(const GLdouble *m); +void ( APIENTRY * qglMultMatrixf )(const GLfloat *m); +void ( APIENTRY * qglNewList )(GLuint list, GLenum mode); +void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); +void ( APIENTRY * qglNormal3bv )(const GLbyte *v); +void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); +void ( APIENTRY * qglNormal3dv )(const GLdouble *v); +void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); +void ( APIENTRY * qglNormal3fv )(const GLfloat *v); +void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz); +void ( APIENTRY * qglNormal3iv )(const GLint *v); +void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz); +void ( APIENTRY * qglNormal3sv )(const GLshort *v); +void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +void ( APIENTRY * qglPassThrough )(GLfloat token); +void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); +void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); +void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); +void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param); +void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param); +void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param); +void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param); +void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor); +void ( APIENTRY * qglPointSize )(GLfloat size); +void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode); +void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units); +void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask); +void ( APIENTRY * qglPopAttrib )(void); +void ( APIENTRY * qglPopClientAttrib )(void); +void ( APIENTRY * qglPopMatrix )(void); +void ( APIENTRY * qglPopName )(void); +void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); +void ( APIENTRY * qglPushAttrib )(GLbitfield mask); +void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask); +void ( APIENTRY * qglPushMatrix )(void); +void ( APIENTRY * qglPushName )(GLuint name); +void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y); +void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v); +void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y); +void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v); +void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y); +void ( APIENTRY * qglRasterPos2iv )(const GLint *v); +void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y); +void ( APIENTRY * qglRasterPos2sv )(const GLshort *v); +void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v); +void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v); +void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z); +void ( APIENTRY * qglRasterPos3iv )(const GLint *v); +void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z); +void ( APIENTRY * qglRasterPos3sv )(const GLshort *v); +void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v); +void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v); +void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w); +void ( APIENTRY * qglRasterPos4iv )(const GLint *v); +void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); +void ( APIENTRY * qglRasterPos4sv )(const GLshort *v); +void ( APIENTRY * qglReadBuffer )(GLenum mode); +void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2); +void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2); +void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2); +void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2); +void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2); +GLint ( APIENTRY * qglRenderMode )(GLenum mode); +void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height); +void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer); +void ( APIENTRY * qglShadeModel )(GLenum mode); +void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask); +void ( APIENTRY * qglStencilMask )(GLuint mask); +void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); +void ( APIENTRY * qglTexCoord1d )(GLdouble s); +void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord1f )(GLfloat s); +void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord1i )(GLint s); +void ( APIENTRY * qglTexCoord1iv )(const GLint *v); +void ( APIENTRY * qglTexCoord1s )(GLshort s); +void ( APIENTRY * qglTexCoord1sv )(const GLshort *v); +void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t); +void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t); +void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t); +void ( APIENTRY * qglTexCoord2iv )(const GLint *v); +void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t); +void ( APIENTRY * qglTexCoord2sv )(const GLshort *v); +void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); +void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); +void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r); +void ( APIENTRY * qglTexCoord3iv )(const GLint *v); +void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r); +void ( APIENTRY * qglTexCoord3sv )(const GLshort *v); +void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q); +void ( APIENTRY * qglTexCoord4iv )(const GLint *v); +void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); +void ( APIENTRY * qglTexCoord4sv )(const GLshort *v); +void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param); +void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param); +void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params); +void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param); +void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); +void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param); +void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param); +void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params); +void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param); +void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param); +void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params); +void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y); +void ( APIENTRY * qglVertex2dv )(const GLdouble *v); +void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y); +void ( APIENTRY * qglVertex2fv )(const GLfloat *v); +void ( APIENTRY * qglVertex2i )(GLint x, GLint y); +void ( APIENTRY * qglVertex2iv )(const GLint *v); +void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y); +void ( APIENTRY * qglVertex2sv )(const GLshort *v); +void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglVertex3dv )(const GLdouble *v); +void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglVertex3fv )(const GLfloat *v); +void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z); +void ( APIENTRY * qglVertex3iv )(const GLint *v); +void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z); +void ( APIENTRY * qglVertex3sv )(const GLshort *v); +void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +void ( APIENTRY * qglVertex4dv )(const GLdouble *v); +void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +void ( APIENTRY * qglVertex4fv )(const GLfloat *v); +void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w); +void ( APIENTRY * qglVertex4iv )(const GLint *v); +void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); +void ( APIENTRY * qglVertex4sv )(const GLshort *v); +void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height); + +void ( APIENTRY * qglLockArraysEXT)( int, int); +void ( APIENTRY * qglUnlockArraysEXT) ( void ); + +BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval ); +BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * ); +BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *, const unsigned char * ); +void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value ); +void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value ); +void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * ); +void ( APIENTRY * qglSelectTextureSGIS)( GLenum ); +void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat ); + +static void ( APIENTRY * dllAccum )(GLenum op, GLfloat value); +static void ( APIENTRY * dllAlphaFunc )(GLenum func, GLclampf ref); +GLboolean ( APIENTRY * dllAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); +static void ( APIENTRY * dllArrayElement )(GLint i); +static void ( APIENTRY * dllBegin )(GLenum mode); +static void ( APIENTRY * dllBindTexture )(GLenum target, GLuint texture); +static void ( APIENTRY * dllBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +static void ( APIENTRY * dllBlendFunc )(GLenum sfactor, GLenum dfactor); +static void ( APIENTRY * dllCallList )(GLuint list); +static void ( APIENTRY * dllCallLists )(GLsizei n, GLenum type, const GLvoid *lists); +static void ( APIENTRY * dllClear )(GLbitfield mask); +static void ( APIENTRY * dllClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +static void ( APIENTRY * dllClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +static void ( APIENTRY * dllClearDepth )(GLclampd depth); +static void ( APIENTRY * dllClearIndex )(GLfloat c); +static void ( APIENTRY * dllClearStencil )(GLint s); +static void ( APIENTRY * dllClipPlane )(GLenum plane, const GLdouble *equation); +static void ( APIENTRY * dllColor3b )(GLbyte red, GLbyte green, GLbyte blue); +static void ( APIENTRY * dllColor3bv )(const GLbyte *v); +static void ( APIENTRY * dllColor3d )(GLdouble red, GLdouble green, GLdouble blue); +static void ( APIENTRY * dllColor3dv )(const GLdouble *v); +static void ( APIENTRY * dllColor3f )(GLfloat red, GLfloat green, GLfloat blue); +static void ( APIENTRY * dllColor3fv )(const GLfloat *v); +static void ( APIENTRY * dllColor3i )(GLint red, GLint green, GLint blue); +static void ( APIENTRY * dllColor3iv )(const GLint *v); +static void ( APIENTRY * dllColor3s )(GLshort red, GLshort green, GLshort blue); +static void ( APIENTRY * dllColor3sv )(const GLshort *v); +static void ( APIENTRY * dllColor3ub )(GLubyte red, GLubyte green, GLubyte blue); +static void ( APIENTRY * dllColor3ubv )(const GLubyte *v); +static void ( APIENTRY * dllColor3ui )(GLuint red, GLuint green, GLuint blue); +static void ( APIENTRY * dllColor3uiv )(const GLuint *v); +static void ( APIENTRY * dllColor3us )(GLushort red, GLushort green, GLushort blue); +static void ( APIENTRY * dllColor3usv )(const GLushort *v); +static void ( APIENTRY * dllColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +static void ( APIENTRY * dllColor4bv )(const GLbyte *v); +static void ( APIENTRY * dllColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +static void ( APIENTRY * dllColor4dv )(const GLdouble *v); +static void ( APIENTRY * dllColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +static void ( APIENTRY * dllColor4fv )(const GLfloat *v); +static void ( APIENTRY * dllColor4i )(GLint red, GLint green, GLint blue, GLint alpha); +static void ( APIENTRY * dllColor4iv )(const GLint *v); +static void ( APIENTRY * dllColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); +static void ( APIENTRY * dllColor4sv )(const GLshort *v); +static void ( APIENTRY * dllColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +static void ( APIENTRY * dllColor4ubv )(const GLubyte *v); +static void ( APIENTRY * dllColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); +static void ( APIENTRY * dllColor4uiv )(const GLuint *v); +static void ( APIENTRY * dllColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); +static void ( APIENTRY * dllColor4usv )(const GLushort *v); +static void ( APIENTRY * dllColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +static void ( APIENTRY * dllColorMaterial )(GLenum face, GLenum mode); +static void ( APIENTRY * dllColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +static void ( APIENTRY * dllCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +static void ( APIENTRY * dllCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +static void ( APIENTRY * dllCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +static void ( APIENTRY * dllCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +static void ( APIENTRY * dllCullFace )(GLenum mode); +static void ( APIENTRY * dllDeleteLists )(GLuint list, GLsizei range); +static void ( APIENTRY * dllDeleteTextures )(GLsizei n, const GLuint *textures); +static void ( APIENTRY * dllDepthFunc )(GLenum func); +static void ( APIENTRY * dllDepthMask )(GLboolean flag); +static void ( APIENTRY * dllDepthRange )(GLclampd zNear, GLclampd zFar); +static void ( APIENTRY * dllDisable )(GLenum cap); +static void ( APIENTRY * dllDisableClientState )(GLenum array); +static void ( APIENTRY * dllDrawArrays )(GLenum mode, GLint first, GLsizei count); +static void ( APIENTRY * dllDrawBuffer )(GLenum mode); +static void ( APIENTRY * dllDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +static void ( APIENTRY * dllDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllEdgeFlag )(GLboolean flag); +static void ( APIENTRY * dllEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllEdgeFlagv )(const GLboolean *flag); +static void ( APIENTRY * dllEnable )(GLenum cap); +static void ( APIENTRY * dllEnableClientState )(GLenum array); +static void ( APIENTRY * dllEnd )(void); +static void ( APIENTRY * dllEndList )(void); +static void ( APIENTRY * dllEvalCoord1d )(GLdouble u); +static void ( APIENTRY * dllEvalCoord1dv )(const GLdouble *u); +static void ( APIENTRY * dllEvalCoord1f )(GLfloat u); +static void ( APIENTRY * dllEvalCoord1fv )(const GLfloat *u); +static void ( APIENTRY * dllEvalCoord2d )(GLdouble u, GLdouble v); +static void ( APIENTRY * dllEvalCoord2dv )(const GLdouble *u); +static void ( APIENTRY * dllEvalCoord2f )(GLfloat u, GLfloat v); +static void ( APIENTRY * dllEvalCoord2fv )(const GLfloat *u); +static void ( APIENTRY * dllEvalMesh1 )(GLenum mode, GLint i1, GLint i2); +static void ( APIENTRY * dllEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +static void ( APIENTRY * dllEvalPoint1 )(GLint i); +static void ( APIENTRY * dllEvalPoint2 )(GLint i, GLint j); +static void ( APIENTRY * dllFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); +static void ( APIENTRY * dllFinish )(void); +static void ( APIENTRY * dllFlush )(void); +static void ( APIENTRY * dllFogf )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllFogfv )(GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllFogi )(GLenum pname, GLint param); +static void ( APIENTRY * dllFogiv )(GLenum pname, const GLint *params); +static void ( APIENTRY * dllFrontFace )(GLenum mode); +static void ( APIENTRY * dllFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLuint ( APIENTRY * dllGenLists )(GLsizei range); +static void ( APIENTRY * dllGenTextures )(GLsizei n, GLuint *textures); +static void ( APIENTRY * dllGetBooleanv )(GLenum pname, GLboolean *params); +static void ( APIENTRY * dllGetClipPlane )(GLenum plane, GLdouble *equation); +static void ( APIENTRY * dllGetDoublev )(GLenum pname, GLdouble *params); +GLenum ( APIENTRY * dllGetError )(void); +static void ( APIENTRY * dllGetFloatv )(GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetIntegerv )(GLenum pname, GLint *params); +static void ( APIENTRY * dllGetLightfv )(GLenum light, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetLightiv )(GLenum light, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetMapdv )(GLenum target, GLenum query, GLdouble *v); +static void ( APIENTRY * dllGetMapfv )(GLenum target, GLenum query, GLfloat *v); +static void ( APIENTRY * dllGetMapiv )(GLenum target, GLenum query, GLint *v); +static void ( APIENTRY * dllGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetMaterialiv )(GLenum face, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetPixelMapfv )(GLenum map, GLfloat *values); +static void ( APIENTRY * dllGetPixelMapuiv )(GLenum map, GLuint *values); +static void ( APIENTRY * dllGetPixelMapusv )(GLenum map, GLushort *values); +static void ( APIENTRY * dllGetPointerv )(GLenum pname, GLvoid* *params); +static void ( APIENTRY * dllGetPolygonStipple )(GLubyte *mask); +const GLubyte * ( APIENTRY * dllGetString )(GLenum name); +static void ( APIENTRY * dllGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexEnviv )(GLenum target, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); +static void ( APIENTRY * dllGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +static void ( APIENTRY * dllGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); +static void ( APIENTRY * dllHint )(GLenum target, GLenum mode); +static void ( APIENTRY * dllIndexMask )(GLuint mask); +static void ( APIENTRY * dllIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllIndexd )(GLdouble c); +static void ( APIENTRY * dllIndexdv )(const GLdouble *c); +static void ( APIENTRY * dllIndexf )(GLfloat c); +static void ( APIENTRY * dllIndexfv )(const GLfloat *c); +static void ( APIENTRY * dllIndexi )(GLint c); +static void ( APIENTRY * dllIndexiv )(const GLint *c); +static void ( APIENTRY * dllIndexs )(GLshort c); +static void ( APIENTRY * dllIndexsv )(const GLshort *c); +static void ( APIENTRY * dllIndexub )(GLubyte c); +static void ( APIENTRY * dllIndexubv )(const GLubyte *c); +static void ( APIENTRY * dllInitNames )(void); +static void ( APIENTRY * dllInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); +GLboolean ( APIENTRY * dllIsEnabled )(GLenum cap); +GLboolean ( APIENTRY * dllIsList )(GLuint list); +GLboolean ( APIENTRY * dllIsTexture )(GLuint texture); +static void ( APIENTRY * dllLightModelf )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllLightModelfv )(GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllLightModeli )(GLenum pname, GLint param); +static void ( APIENTRY * dllLightModeliv )(GLenum pname, const GLint *params); +static void ( APIENTRY * dllLightf )(GLenum light, GLenum pname, GLfloat param); +static void ( APIENTRY * dllLightfv )(GLenum light, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllLighti )(GLenum light, GLenum pname, GLint param); +static void ( APIENTRY * dllLightiv )(GLenum light, GLenum pname, const GLint *params); +static void ( APIENTRY * dllLineStipple )(GLint factor, GLushort pattern); +static void ( APIENTRY * dllLineWidth )(GLfloat width); +static void ( APIENTRY * dllListBase )(GLuint base); +static void ( APIENTRY * dllLoadIdentity )(void); +static void ( APIENTRY * dllLoadMatrixd )(const GLdouble *m); +static void ( APIENTRY * dllLoadMatrixf )(const GLfloat *m); +static void ( APIENTRY * dllLoadName )(GLuint name); +static void ( APIENTRY * dllLogicOp )(GLenum opcode); +static void ( APIENTRY * dllMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +static void ( APIENTRY * dllMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +static void ( APIENTRY * dllMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +static void ( APIENTRY * dllMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +static void ( APIENTRY * dllMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); +static void ( APIENTRY * dllMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); +static void ( APIENTRY * dllMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +static void ( APIENTRY * dllMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +static void ( APIENTRY * dllMaterialf )(GLenum face, GLenum pname, GLfloat param); +static void ( APIENTRY * dllMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllMateriali )(GLenum face, GLenum pname, GLint param); +static void ( APIENTRY * dllMaterialiv )(GLenum face, GLenum pname, const GLint *params); +static void ( APIENTRY * dllMatrixMode )(GLenum mode); +static void ( APIENTRY * dllMultMatrixd )(const GLdouble *m); +static void ( APIENTRY * dllMultMatrixf )(const GLfloat *m); +static void ( APIENTRY * dllNewList )(GLuint list, GLenum mode); +static void ( APIENTRY * dllNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); +static void ( APIENTRY * dllNormal3bv )(const GLbyte *v); +static void ( APIENTRY * dllNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); +static void ( APIENTRY * dllNormal3dv )(const GLdouble *v); +static void ( APIENTRY * dllNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); +static void ( APIENTRY * dllNormal3fv )(const GLfloat *v); +static void ( APIENTRY * dllNormal3i )(GLint nx, GLint ny, GLint nz); +static void ( APIENTRY * dllNormal3iv )(const GLint *v); +static void ( APIENTRY * dllNormal3s )(GLshort nx, GLshort ny, GLshort nz); +static void ( APIENTRY * dllNormal3sv )(const GLshort *v); +static void ( APIENTRY * dllNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +static void ( APIENTRY * dllPassThrough )(GLfloat token); +static void ( APIENTRY * dllPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); +static void ( APIENTRY * dllPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); +static void ( APIENTRY * dllPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); +static void ( APIENTRY * dllPixelStoref )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllPixelStorei )(GLenum pname, GLint param); +static void ( APIENTRY * dllPixelTransferf )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllPixelTransferi )(GLenum pname, GLint param); +static void ( APIENTRY * dllPixelZoom )(GLfloat xfactor, GLfloat yfactor); +static void ( APIENTRY * dllPointSize )(GLfloat size); +static void ( APIENTRY * dllPolygonMode )(GLenum face, GLenum mode); +static void ( APIENTRY * dllPolygonOffset )(GLfloat factor, GLfloat units); +static void ( APIENTRY * dllPolygonStipple )(const GLubyte *mask); +static void ( APIENTRY * dllPopAttrib )(void); +static void ( APIENTRY * dllPopClientAttrib )(void); +static void ( APIENTRY * dllPopMatrix )(void); +static void ( APIENTRY * dllPopName )(void); +static void ( APIENTRY * dllPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); +static void ( APIENTRY * dllPushAttrib )(GLbitfield mask); +static void ( APIENTRY * dllPushClientAttrib )(GLbitfield mask); +static void ( APIENTRY * dllPushMatrix )(void); +static void ( APIENTRY * dllPushName )(GLuint name); +static void ( APIENTRY * dllRasterPos2d )(GLdouble x, GLdouble y); +static void ( APIENTRY * dllRasterPos2dv )(const GLdouble *v); +static void ( APIENTRY * dllRasterPos2f )(GLfloat x, GLfloat y); +static void ( APIENTRY * dllRasterPos2fv )(const GLfloat *v); +static void ( APIENTRY * dllRasterPos2i )(GLint x, GLint y); +static void ( APIENTRY * dllRasterPos2iv )(const GLint *v); +static void ( APIENTRY * dllRasterPos2s )(GLshort x, GLshort y); +static void ( APIENTRY * dllRasterPos2sv )(const GLshort *v); +static void ( APIENTRY * dllRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllRasterPos3dv )(const GLdouble *v); +static void ( APIENTRY * dllRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllRasterPos3fv )(const GLfloat *v); +static void ( APIENTRY * dllRasterPos3i )(GLint x, GLint y, GLint z); +static void ( APIENTRY * dllRasterPos3iv )(const GLint *v); +static void ( APIENTRY * dllRasterPos3s )(GLshort x, GLshort y, GLshort z); +static void ( APIENTRY * dllRasterPos3sv )(const GLshort *v); +static void ( APIENTRY * dllRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +static void ( APIENTRY * dllRasterPos4dv )(const GLdouble *v); +static void ( APIENTRY * dllRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +static void ( APIENTRY * dllRasterPos4fv )(const GLfloat *v); +static void ( APIENTRY * dllRasterPos4i )(GLint x, GLint y, GLint z, GLint w); +static void ( APIENTRY * dllRasterPos4iv )(const GLint *v); +static void ( APIENTRY * dllRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); +static void ( APIENTRY * dllRasterPos4sv )(const GLshort *v); +static void ( APIENTRY * dllReadBuffer )(GLenum mode); +static void ( APIENTRY * dllReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +static void ( APIENTRY * dllRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +static void ( APIENTRY * dllRectdv )(const GLdouble *v1, const GLdouble *v2); +static void ( APIENTRY * dllRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +static void ( APIENTRY * dllRectfv )(const GLfloat *v1, const GLfloat *v2); +static void ( APIENTRY * dllRecti )(GLint x1, GLint y1, GLint x2, GLint y2); +static void ( APIENTRY * dllRectiv )(const GLint *v1, const GLint *v2); +static void ( APIENTRY * dllRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +static void ( APIENTRY * dllRectsv )(const GLshort *v1, const GLshort *v2); +GLint ( APIENTRY * dllRenderMode )(GLenum mode); +static void ( APIENTRY * dllRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllScaled )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllScalef )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllScissor )(GLint x, GLint y, GLsizei width, GLsizei height); +static void ( APIENTRY * dllSelectBuffer )(GLsizei size, GLuint *buffer); +static void ( APIENTRY * dllShadeModel )(GLenum mode); +static void ( APIENTRY * dllStencilFunc )(GLenum func, GLint ref, GLuint mask); +static void ( APIENTRY * dllStencilMask )(GLuint mask); +static void ( APIENTRY * dllStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); +static void ( APIENTRY * dllTexCoord1d )(GLdouble s); +static void ( APIENTRY * dllTexCoord1dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord1f )(GLfloat s); +static void ( APIENTRY * dllTexCoord1fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord1i )(GLint s); +static void ( APIENTRY * dllTexCoord1iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord1s )(GLshort s); +static void ( APIENTRY * dllTexCoord1sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoord2d )(GLdouble s, GLdouble t); +static void ( APIENTRY * dllTexCoord2dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord2f )(GLfloat s, GLfloat t); +static void ( APIENTRY * dllTexCoord2fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord2i )(GLint s, GLint t); +static void ( APIENTRY * dllTexCoord2iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord2s )(GLshort s, GLshort t); +static void ( APIENTRY * dllTexCoord2sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); +static void ( APIENTRY * dllTexCoord3dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); +static void ( APIENTRY * dllTexCoord3fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord3i )(GLint s, GLint t, GLint r); +static void ( APIENTRY * dllTexCoord3iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord3s )(GLshort s, GLshort t, GLshort r); +static void ( APIENTRY * dllTexCoord3sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +static void ( APIENTRY * dllTexCoord4dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +static void ( APIENTRY * dllTexCoord4fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord4i )(GLint s, GLint t, GLint r, GLint q); +static void ( APIENTRY * dllTexCoord4iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); +static void ( APIENTRY * dllTexCoord4sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllTexEnvf )(GLenum target, GLenum pname, GLfloat param); +static void ( APIENTRY * dllTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllTexEnvi )(GLenum target, GLenum pname, GLint param); +static void ( APIENTRY * dllTexEnviv )(GLenum target, GLenum pname, const GLint *params); +static void ( APIENTRY * dllTexGend )(GLenum coord, GLenum pname, GLdouble param); +static void ( APIENTRY * dllTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); +static void ( APIENTRY * dllTexGenf )(GLenum coord, GLenum pname, GLfloat param); +static void ( APIENTRY * dllTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllTexGeni )(GLenum coord, GLenum pname, GLint param); +static void ( APIENTRY * dllTexGeniv )(GLenum coord, GLenum pname, const GLint *params); +static void ( APIENTRY * dllTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTexParameterf )(GLenum target, GLenum pname, GLfloat param); +static void ( APIENTRY * dllTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllTexParameteri )(GLenum target, GLenum pname, GLint param); +static void ( APIENTRY * dllTexParameteriv )(GLenum target, GLenum pname, const GLint *params); +static void ( APIENTRY * dllTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTranslated )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllTranslatef )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllVertex2d )(GLdouble x, GLdouble y); +static void ( APIENTRY * dllVertex2dv )(const GLdouble *v); +static void ( APIENTRY * dllVertex2f )(GLfloat x, GLfloat y); +static void ( APIENTRY * dllVertex2fv )(const GLfloat *v); +static void ( APIENTRY * dllVertex2i )(GLint x, GLint y); +static void ( APIENTRY * dllVertex2iv )(const GLint *v); +static void ( APIENTRY * dllVertex2s )(GLshort x, GLshort y); +static void ( APIENTRY * dllVertex2sv )(const GLshort *v); +static void ( APIENTRY * dllVertex3d )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllVertex3dv )(const GLdouble *v); +static void ( APIENTRY * dllVertex3f )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllVertex3fv )(const GLfloat *v); +static void ( APIENTRY * dllVertex3i )(GLint x, GLint y, GLint z); +static void ( APIENTRY * dllVertex3iv )(const GLint *v); +static void ( APIENTRY * dllVertex3s )(GLshort x, GLshort y, GLshort z); +static void ( APIENTRY * dllVertex3sv )(const GLshort *v); +static void ( APIENTRY * dllVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +static void ( APIENTRY * dllVertex4dv )(const GLdouble *v); +static void ( APIENTRY * dllVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +static void ( APIENTRY * dllVertex4fv )(const GLfloat *v); +static void ( APIENTRY * dllVertex4i )(GLint x, GLint y, GLint z, GLint w); +static void ( APIENTRY * dllVertex4iv )(const GLint *v); +static void ( APIENTRY * dllVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); +static void ( APIENTRY * dllVertex4sv )(const GLshort *v); +static void ( APIENTRY * dllVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllViewport )(GLint x, GLint y, GLsizei width, GLsizei height); + +static void APIENTRY logAccum(GLenum op, GLfloat value) +{ + fprintf( glw_state.log_fp, "glAccum\n" ); + dllAccum( op, value ); +} + +static void APIENTRY logAlphaFunc(GLenum func, GLclampf ref) +{ + fprintf( glw_state.log_fp, "glAlphaFunc( 0x%x, %f )\n", func, ref ); + dllAlphaFunc( func, ref ); +} + +static GLboolean APIENTRY logAreTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences) +{ + fprintf( glw_state.log_fp, "glAreTexturesResident\n" ); + return dllAreTexturesResident( n, textures, residences ); +} + +static void APIENTRY logArrayElement(GLint i) +{ + fprintf( glw_state.log_fp, "glArrayElement\n" ); + dllArrayElement( i ); +} + +static void APIENTRY logBegin(GLenum mode) +{ + fprintf( glw_state.log_fp, "glBegin( 0x%x )\n", mode ); + dllBegin( mode ); +} + +static void APIENTRY logBindTexture(GLenum target, GLuint texture) +{ + fprintf( glw_state.log_fp, "glBindTexture( 0x%x, %u )\n", target, texture ); + dllBindTexture( target, texture ); +} + +static void APIENTRY logBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) +{ + fprintf( glw_state.log_fp, "glBitmap\n" ); + dllBitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); +} + +static void APIENTRY logBlendFunc(GLenum sfactor, GLenum dfactor) +{ + fprintf( glw_state.log_fp, "glBlendFunc( 0x%x, 0x%x )\n", sfactor, dfactor ); + dllBlendFunc( sfactor, dfactor ); +} + +static void APIENTRY logCallList(GLuint list) +{ + fprintf( glw_state.log_fp, "glCallList( %u )\n", list ); + dllCallList( list ); +} + +static void APIENTRY logCallLists(GLsizei n, GLenum type, const void *lists) +{ + fprintf( glw_state.log_fp, "glCallLists\n" ); + dllCallLists( n, type, lists ); +} + +static void APIENTRY logClear(GLbitfield mask) +{ + fprintf( glw_state.log_fp, "glClear\n" ); + dllClear( mask ); +} + +static void APIENTRY logClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + fprintf( glw_state.log_fp, "glClearAccum\n" ); + dllClearAccum( red, green, blue, alpha ); +} + +static void APIENTRY logClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + fprintf( glw_state.log_fp, "glClearColor\n" ); + dllClearColor( red, green, blue, alpha ); +} + +static void APIENTRY logClearDepth(GLclampd depth) +{ + fprintf( glw_state.log_fp, "glClearDepth\n" ); + dllClearDepth( depth ); +} + +static void APIENTRY logClearIndex(GLfloat c) +{ + fprintf( glw_state.log_fp, "glClearIndex\n" ); + dllClearIndex( c ); +} + +static void APIENTRY logClearStencil(GLint s) +{ + fprintf( glw_state.log_fp, "glClearStencil\n" ); + dllClearStencil( s ); +} + +static void APIENTRY logClipPlane(GLenum plane, const GLdouble *equation) +{ + fprintf( glw_state.log_fp, "glClipPlane\n" ); + dllClipPlane( plane, equation ); +} + +static void APIENTRY logColor3b(GLbyte red, GLbyte green, GLbyte blue) +{ + fprintf( glw_state.log_fp, "glColor3b\n" ); + dllColor3b( red, green, blue ); +} + +static void APIENTRY logColor3bv(const GLbyte *v) +{ + fprintf( glw_state.log_fp, "glColor3bv\n" ); + dllColor3bv( v ); +} + +static void APIENTRY logColor3d(GLdouble red, GLdouble green, GLdouble blue) +{ + fprintf( glw_state.log_fp, "glColor3d\n" ); + dllColor3d( red, green, blue ); +} + +static void APIENTRY logColor3dv(const GLdouble *v) +{ + fprintf( glw_state.log_fp, "glColor3dv\n" ); + dllColor3dv( v ); +} + +static void APIENTRY logColor3f(GLfloat red, GLfloat green, GLfloat blue) +{ + fprintf( glw_state.log_fp, "glColor3f\n" ); + dllColor3f( red, green, blue ); +} + +static void APIENTRY logColor3fv(const GLfloat *v) +{ + fprintf( glw_state.log_fp, "glColor3fv\n" ); + dllColor3fv( v ); +} + +static void APIENTRY logColor3i(GLint red, GLint green, GLint blue) +{ + fprintf( glw_state.log_fp, "glColor3i\n" ); + dllColor3i( red, green, blue ); +} + +static void APIENTRY logColor3iv(const GLint *v) +{ + fprintf( glw_state.log_fp, "glColor3iv\n" ); + dllColor3iv( v ); +} + +static void APIENTRY logColor3s(GLshort red, GLshort green, GLshort blue) +{ + fprintf( glw_state.log_fp, "glColor3s\n" ); + dllColor3s( red, green, blue ); +} + +static void APIENTRY logColor3sv(const GLshort *v) +{ + fprintf( glw_state.log_fp, "glColor3sv\n" ); + dllColor3sv( v ); +} + +static void APIENTRY logColor3ub(GLubyte red, GLubyte green, GLubyte blue) +{ + fprintf( glw_state.log_fp, "glColor3ub\n" ); + dllColor3ub( red, green, blue ); +} + +static void APIENTRY logColor3ubv(const GLubyte *v) +{ + fprintf( glw_state.log_fp, "glColor3ubv\n" ); + dllColor3ubv( v ); +} + +#define SIG( x ) fprintf( glw_state.log_fp, x "\n" ) + +static void APIENTRY logColor3ui(GLuint red, GLuint green, GLuint blue) +{ + SIG( "glColor3ui" ); + dllColor3ui( red, green, blue ); +} + +static void APIENTRY logColor3uiv(const GLuint *v) +{ + SIG( "glColor3uiv" ); + dllColor3uiv( v ); +} + +static void APIENTRY logColor3us(GLushort red, GLushort green, GLushort blue) +{ + SIG( "glColor3us" ); + dllColor3us( red, green, blue ); +} + +static void APIENTRY logColor3usv(const GLushort *v) +{ + SIG( "glColor3usv" ); + dllColor3usv( v ); +} + +static void APIENTRY logColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) +{ + SIG( "glColor4b" ); + dllColor4b( red, green, blue, alpha ); +} + +static void APIENTRY logColor4bv(const GLbyte *v) +{ + SIG( "glColor4bv" ); + dllColor4bv( v ); +} + +static void APIENTRY logColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) +{ + SIG( "glColor4d" ); + dllColor4d( red, green, blue, alpha ); +} +static void APIENTRY logColor4dv(const GLdouble *v) +{ + SIG( "glColor4dv" ); + dllColor4dv( v ); +} +static void APIENTRY logColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + fprintf( glw_state.log_fp, "glColor4f( %f,%f,%f,%f )\n", red, green, blue, alpha ); + dllColor4f( red, green, blue, alpha ); +} +static void APIENTRY logColor4fv(const GLfloat *v) +{ + fprintf( glw_state.log_fp, "glColor4fv( %f,%f,%f,%f )\n", v[0], v[1], v[2], v[3] ); + dllColor4fv( v ); +} +static void APIENTRY logColor4i(GLint red, GLint green, GLint blue, GLint alpha) +{ + SIG( "glColor4i" ); + dllColor4i( red, green, blue, alpha ); +} +static void APIENTRY logColor4iv(const GLint *v) +{ + SIG( "glColor4iv" ); + dllColor4iv( v ); +} +static void APIENTRY logColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) +{ + SIG( "glColor4s" ); + dllColor4s( red, green, blue, alpha ); +} +static void APIENTRY logColor4sv(const GLshort *v) +{ + SIG( "glColor4sv" ); + dllColor4sv( v ); +} +static void APIENTRY logColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +{ + SIG( "glColor4b" ); + dllColor4b( red, green, blue, alpha ); +} +static void APIENTRY logColor4ubv(const GLubyte *v) +{ + SIG( "glColor4ubv" ); + dllColor4ubv( v ); +} +static void APIENTRY logColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha) +{ + SIG( "glColor4ui" ); + dllColor4ui( red, green, blue, alpha ); +} +static void APIENTRY logColor4uiv(const GLuint *v) +{ + SIG( "glColor4uiv" ); + dllColor4uiv( v ); +} +static void APIENTRY logColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha) +{ + SIG( "glColor4us" ); + dllColor4us( red, green, blue, alpha ); +} +static void APIENTRY logColor4usv(const GLushort *v) +{ + SIG( "glColor4usv" ); + dllColor4usv( v ); +} +static void APIENTRY logColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + SIG( "glColorMask" ); + dllColorMask( red, green, blue, alpha ); +} +static void APIENTRY logColorMaterial(GLenum face, GLenum mode) +{ + SIG( "glColorMaterial" ); + dllColorMaterial( face, mode ); +} + +static void APIENTRY logColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glColorPointer" ); + dllColorPointer( size, type, stride, pointer ); +} + +static void APIENTRY logCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) +{ + SIG( "glCopyPixels" ); + dllCopyPixels( x, y, width, height, type ); +} + +static void APIENTRY logCopyTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border) +{ + SIG( "glCopyTexImage1D" ); + dllCopyTexImage1D( target, level, internalFormat, x, y, width, border ); +} + +static void APIENTRY logCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + SIG( "glCopyTexImage2D" ); + dllCopyTexImage2D( target, level, internalFormat, x, y, width, height, border ); +} + +static void APIENTRY logCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) +{ + SIG( "glCopyTexSubImage1D" ); + dllCopyTexSubImage1D( target, level, xoffset, x, y, width ); +} + +static void APIENTRY logCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + SIG( "glCopyTexSubImage2D" ); + dllCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height ); +} + +static void APIENTRY logCullFace(GLenum mode) +{ + SIG( "glCullFace" ); + dllCullFace( mode ); +} + +static void APIENTRY logDeleteLists(GLuint list, GLsizei range) +{ + SIG( "glDeleteLists" ); + dllDeleteLists( list, range ); +} + +static void APIENTRY logDeleteTextures(GLsizei n, const GLuint *textures) +{ + SIG( "glDeleteTextures" ); + dllDeleteTextures( n, textures ); +} + +static void APIENTRY logDepthFunc(GLenum func) +{ + SIG( "glDepthFunc" ); + dllDepthFunc( func ); +} + +static void APIENTRY logDepthMask(GLboolean flag) +{ + SIG( "glDepthMask" ); + dllDepthMask( flag ); +} + +static void APIENTRY logDepthRange(GLclampd zNear, GLclampd zFar) +{ + SIG( "glDepthRange" ); + dllDepthRange( zNear, zFar ); +} + +static void APIENTRY logDisable(GLenum cap) +{ + fprintf( glw_state.log_fp, "glDisable( 0x%x )\n", cap ); + dllDisable( cap ); +} + +static void APIENTRY logDisableClientState(GLenum array) +{ + SIG( "glDisableClientState" ); + dllDisableClientState( array ); +} + +static void APIENTRY logDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + SIG( "glDrawArrays" ); + dllDrawArrays( mode, first, count ); +} + +static void APIENTRY logDrawBuffer(GLenum mode) +{ + SIG( "glDrawBuffer" ); + dllDrawBuffer( mode ); +} + +static void APIENTRY logDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) +{ + SIG( "glDrawElements" ); + dllDrawElements( mode, count, type, indices ); +} + +static void APIENTRY logDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glDrawPixels" ); + dllDrawPixels( width, height, format, type, pixels ); +} + +static void APIENTRY logEdgeFlag(GLboolean flag) +{ + SIG( "glEdgeFlag" ); + dllEdgeFlag( flag ); +} + +static void APIENTRY logEdgeFlagPointer(GLsizei stride, const void *pointer) +{ + SIG( "glEdgeFlagPointer" ); + dllEdgeFlagPointer( stride, pointer ); +} + +static void APIENTRY logEdgeFlagv(const GLboolean *flag) +{ + SIG( "glEdgeFlagv" ); + dllEdgeFlagv( flag ); +} + +static void APIENTRY logEnable(GLenum cap) +{ + fprintf( glw_state.log_fp, "glEnable( 0x%x )\n", cap ); + dllEnable( cap ); +} + +static void APIENTRY logEnableClientState(GLenum array) +{ + SIG( "glEnableClientState" ); + dllEnableClientState( array ); +} + +static void APIENTRY logEnd(void) +{ + SIG( "glEnd" ); + dllEnd(); +} + +static void APIENTRY logEndList(void) +{ + SIG( "glEndList" ); + dllEndList(); +} + +static void APIENTRY logEvalCoord1d(GLdouble u) +{ + SIG( "glEvalCoord1d" ); + dllEvalCoord1d( u ); +} + +static void APIENTRY logEvalCoord1dv(const GLdouble *u) +{ + SIG( "glEvalCoord1dv" ); + dllEvalCoord1dv( u ); +} + +static void APIENTRY logEvalCoord1f(GLfloat u) +{ + SIG( "glEvalCoord1f" ); + dllEvalCoord1f( u ); +} + +static void APIENTRY logEvalCoord1fv(const GLfloat *u) +{ + SIG( "glEvalCoord1fv" ); + dllEvalCoord1fv( u ); +} +static void APIENTRY logEvalCoord2d(GLdouble u, GLdouble v) +{ + SIG( "glEvalCoord2d" ); + dllEvalCoord2d( u, v ); +} +static void APIENTRY logEvalCoord2dv(const GLdouble *u) +{ + SIG( "glEvalCoord2dv" ); + dllEvalCoord2dv( u ); +} +static void APIENTRY logEvalCoord2f(GLfloat u, GLfloat v) +{ + SIG( "glEvalCoord2f" ); + dllEvalCoord2f( u, v ); +} +static void APIENTRY logEvalCoord2fv(const GLfloat *u) +{ + SIG( "glEvalCoord2fv" ); + dllEvalCoord2fv( u ); +} + +static void APIENTRY logEvalMesh1(GLenum mode, GLint i1, GLint i2) +{ + SIG( "glEvalMesh1" ); + dllEvalMesh1( mode, i1, i2 ); +} +static void APIENTRY logEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) +{ + SIG( "glEvalMesh2" ); + dllEvalMesh2( mode, i1, i2, j1, j2 ); +} +static void APIENTRY logEvalPoint1(GLint i) +{ + SIG( "glEvalPoint1" ); + dllEvalPoint1( i ); +} +static void APIENTRY logEvalPoint2(GLint i, GLint j) +{ + SIG( "glEvalPoint2" ); + dllEvalPoint2( i, j ); +} + +static void APIENTRY logFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer) +{ + SIG( "glFeedbackBuffer" ); + dllFeedbackBuffer( size, type, buffer ); +} + +static void APIENTRY logFinish(void) +{ + SIG( "glFinish" ); + dllFinish(); +} + +static void APIENTRY logFlush(void) +{ + SIG( "glFlush" ); + dllFlush(); +} + +static void APIENTRY logFogf(GLenum pname, GLfloat param) +{ + SIG( "glFogf" ); + dllFogf( pname, param ); +} + +static void APIENTRY logFogfv(GLenum pname, const GLfloat *params) +{ + SIG( "glFogfv" ); + dllFogfv( pname, params ); +} + +static void APIENTRY logFogi(GLenum pname, GLint param) +{ + SIG( "glFogi" ); + dllFogi( pname, param ); +} + +static void APIENTRY logFogiv(GLenum pname, const GLint *params) +{ + SIG( "glFogiv" ); + dllFogiv( pname, params ); +} + +static void APIENTRY logFrontFace(GLenum mode) +{ + SIG( "glFrontFace" ); + dllFrontFace( mode ); +} + +static void APIENTRY logFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) +{ + SIG( "glFrustum" ); + dllFrustum( left, right, bottom, top, zNear, zFar ); +} + +static GLuint APIENTRY logGenLists(GLsizei range) +{ + SIG( "glGenLists" ); + return dllGenLists( range ); +} + +static void APIENTRY logGenTextures(GLsizei n, GLuint *textures) +{ + SIG( "glGenTextures" ); + dllGenTextures( n, textures ); +} + +static void APIENTRY logGetBooleanv(GLenum pname, GLboolean *params) +{ + SIG( "glGetBooleanv" ); + dllGetBooleanv( pname, params ); +} + +static void APIENTRY logGetClipPlane(GLenum plane, GLdouble *equation) +{ + SIG( "glGetClipPlane" ); + dllGetClipPlane( plane, equation ); +} + +static void APIENTRY logGetDoublev(GLenum pname, GLdouble *params) +{ + SIG( "glGetDoublev" ); + dllGetDoublev( pname, params ); +} + +static GLenum APIENTRY logGetError(void) +{ + SIG( "glGetError" ); + return dllGetError(); +} + +static void APIENTRY logGetFloatv(GLenum pname, GLfloat *params) +{ + SIG( "glGetFloatv" ); + dllGetFloatv( pname, params ); +} + +static void APIENTRY logGetIntegerv(GLenum pname, GLint *params) +{ + SIG( "glGetIntegerv" ); + dllGetIntegerv( pname, params ); +} + +static void APIENTRY logGetLightfv(GLenum light, GLenum pname, GLfloat *params) +{ + SIG( "glGetLightfv" ); + dllGetLightfv( light, pname, params ); +} + +static void APIENTRY logGetLightiv(GLenum light, GLenum pname, GLint *params) +{ + SIG( "glGetLightiv" ); + dllGetLightiv( light, pname, params ); +} + +static void APIENTRY logGetMapdv(GLenum target, GLenum query, GLdouble *v) +{ + SIG( "glGetMapdv" ); + dllGetMapdv( target, query, v ); +} + +static void APIENTRY logGetMapfv(GLenum target, GLenum query, GLfloat *v) +{ + SIG( "glGetMapfv" ); + dllGetMapfv( target, query, v ); +} + +static void APIENTRY logGetMapiv(GLenum target, GLenum query, GLint *v) +{ + SIG( "glGetMapiv" ); + dllGetMapiv( target, query, v ); +} + +static void APIENTRY logGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) +{ + SIG( "glGetMaterialfv" ); + dllGetMaterialfv( face, pname, params ); +} + +static void APIENTRY logGetMaterialiv(GLenum face, GLenum pname, GLint *params) +{ + SIG( "glGetMaterialiv" ); + dllGetMaterialiv( face, pname, params ); +} + +static void APIENTRY logGetPixelMapfv(GLenum map, GLfloat *values) +{ + SIG( "glGetPixelMapfv" ); + dllGetPixelMapfv( map, values ); +} + +static void APIENTRY logGetPixelMapuiv(GLenum map, GLuint *values) +{ + SIG( "glGetPixelMapuiv" ); + dllGetPixelMapuiv( map, values ); +} + +static void APIENTRY logGetPixelMapusv(GLenum map, GLushort *values) +{ + SIG( "glGetPixelMapusv" ); + dllGetPixelMapusv( map, values ); +} + +static void APIENTRY logGetPointerv(GLenum pname, GLvoid* *params) +{ + SIG( "glGetPointerv" ); + dllGetPointerv( pname, params ); +} + +static void APIENTRY logGetPolygonStipple(GLubyte *mask) +{ + SIG( "glGetPolygonStipple" ); + dllGetPolygonStipple( mask ); +} + +static const GLubyte * APIENTRY logGetString(GLenum name) +{ + SIG( "glGetString" ); + return dllGetString( name ); +} + +static void APIENTRY logGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) +{ + SIG( "glGetTexEnvfv" ); + dllGetTexEnvfv( target, pname, params ); +} + +static void APIENTRY logGetTexEnviv(GLenum target, GLenum pname, GLint *params) +{ + SIG( "glGetTexEnviv" ); + dllGetTexEnviv( target, pname, params ); +} + +static void APIENTRY logGetTexGendv(GLenum coord, GLenum pname, GLdouble *params) +{ + SIG( "glGetTexGendv" ); + dllGetTexGendv( coord, pname, params ); +} + +static void APIENTRY logGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) +{ + SIG( "glGetTexGenfv" ); + dllGetTexGenfv( coord, pname, params ); +} + +static void APIENTRY logGetTexGeniv(GLenum coord, GLenum pname, GLint *params) +{ + SIG( "glGetTexGeniv" ); + dllGetTexGeniv( coord, pname, params ); +} + +static void APIENTRY logGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void *pixels) +{ + SIG( "glGetTexImage" ); + dllGetTexImage( target, level, format, type, pixels ); +} +static void APIENTRY logGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params ) +{ + SIG( "glGetTexLevelParameterfv" ); + dllGetTexLevelParameterfv( target, level, pname, params ); +} + +static void APIENTRY logGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) +{ + SIG( "glGetTexLevelParameteriv" ); + dllGetTexLevelParameteriv( target, level, pname, params ); +} + +static void APIENTRY logGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + SIG( "glGetTexParameterfv" ); + dllGetTexParameterfv( target, pname, params ); +} + +static void APIENTRY logGetTexParameteriv(GLenum target, GLenum pname, GLint *params) +{ + SIG( "glGetTexParameteriv" ); + dllGetTexParameteriv( target, pname, params ); +} + +static void APIENTRY logHint(GLenum target, GLenum mode) +{ + fprintf( glw_state.log_fp, "glHint( 0x%x, 0x%x )\n", target, mode ); + dllHint( target, mode ); +} + +static void APIENTRY logIndexMask(GLuint mask) +{ + SIG( "glIndexMask" ); + dllIndexMask( mask ); +} + +static void APIENTRY logIndexPointer(GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glIndexPointer" ); + dllIndexPointer( type, stride, pointer ); +} + +static void APIENTRY logIndexd(GLdouble c) +{ + SIG( "glIndexd" ); + dllIndexd( c ); +} + +static void APIENTRY logIndexdv(const GLdouble *c) +{ + SIG( "glIndexdv" ); + dllIndexdv( c ); +} + +static void APIENTRY logIndexf(GLfloat c) +{ + SIG( "glIndexf" ); + dllIndexf( c ); +} + +static void APIENTRY logIndexfv(const GLfloat *c) +{ + SIG( "glIndexfv" ); + dllIndexfv( c ); +} + +static void APIENTRY logIndexi(GLint c) +{ + SIG( "glIndexi" ); + dllIndexi( c ); +} + +static void APIENTRY logIndexiv(const GLint *c) +{ + SIG( "glIndexiv" ); + dllIndexiv( c ); +} + +static void APIENTRY logIndexs(GLshort c) +{ + SIG( "glIndexs" ); + dllIndexs( c ); +} + +static void APIENTRY logIndexsv(const GLshort *c) +{ + SIG( "glIndexsv" ); + dllIndexsv( c ); +} + +static void APIENTRY logIndexub(GLubyte c) +{ + SIG( "glIndexub" ); + dllIndexub( c ); +} + +static void APIENTRY logIndexubv(const GLubyte *c) +{ + SIG( "glIndexubv" ); + dllIndexubv( c ); +} + +static void APIENTRY logInitNames(void) +{ + SIG( "glInitNames" ); + dllInitNames(); +} + +static void APIENTRY logInterleavedArrays(GLenum format, GLsizei stride, const void *pointer) +{ + SIG( "glInterleavedArrays" ); + dllInterleavedArrays( format, stride, pointer ); +} + +static GLboolean APIENTRY logIsEnabled(GLenum cap) +{ + SIG( "glIsEnabled" ); + return dllIsEnabled( cap ); +} +static GLboolean APIENTRY logIsList(GLuint list) +{ + SIG( "glIsList" ); + return dllIsList( list ); +} +static GLboolean APIENTRY logIsTexture(GLuint texture) +{ + SIG( "glIsTexture" ); + return dllIsTexture( texture ); +} + +static void APIENTRY logLightModelf(GLenum pname, GLfloat param) +{ + SIG( "glLightModelf" ); + dllLightModelf( pname, param ); +} + +static void APIENTRY logLightModelfv(GLenum pname, const GLfloat *params) +{ + SIG( "glLightModelfv" ); + dllLightModelfv( pname, params ); +} + +static void APIENTRY logLightModeli(GLenum pname, GLint param) +{ + SIG( "glLightModeli" ); + dllLightModeli( pname, param ); + +} + +static void APIENTRY logLightModeliv(GLenum pname, const GLint *params) +{ + SIG( "glLightModeliv" ); + dllLightModeliv( pname, params ); +} + +static void APIENTRY logLightf(GLenum light, GLenum pname, GLfloat param) +{ + SIG( "glLightf" ); + dllLightf( light, pname, param ); +} + +static void APIENTRY logLightfv(GLenum light, GLenum pname, const GLfloat *params) +{ + SIG( "glLightfv" ); + dllLightfv( light, pname, params ); +} + +static void APIENTRY logLighti(GLenum light, GLenum pname, GLint param) +{ + SIG( "glLighti" ); + dllLighti( light, pname, param ); +} + +static void APIENTRY logLightiv(GLenum light, GLenum pname, const GLint *params) +{ + SIG( "glLightiv" ); + dllLightiv( light, pname, params ); +} + +static void APIENTRY logLineStipple(GLint factor, GLushort pattern) +{ + SIG( "glLineStipple" ); + dllLineStipple( factor, pattern ); +} + +static void APIENTRY logLineWidth(GLfloat width) +{ + SIG( "glLineWidth" ); + dllLineWidth( width ); +} + +static void APIENTRY logListBase(GLuint base) +{ + SIG( "glListBase" ); + dllListBase( base ); +} + +static void APIENTRY logLoadIdentity(void) +{ + SIG( "glLoadIdentity" ); + dllLoadIdentity(); +} + +static void APIENTRY logLoadMatrixd(const GLdouble *m) +{ + SIG( "glLoadMatrixd" ); + dllLoadMatrixd( m ); +} + +static void APIENTRY logLoadMatrixf(const GLfloat *m) +{ + SIG( "glLoadMatrixf" ); + dllLoadMatrixf( m ); +} + +static void APIENTRY logLoadName(GLuint name) +{ + SIG( "glLoadName" ); + dllLoadName( name ); +} + +static void APIENTRY logLogicOp(GLenum opcode) +{ + SIG( "glLogicOp" ); + dllLogicOp( opcode ); +} + +static void APIENTRY logMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) +{ + SIG( "glMap1d" ); + dllMap1d( target, u1, u2, stride, order, points ); +} + +static void APIENTRY logMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) +{ + SIG( "glMap1f" ); + dllMap1f( target, u1, u2, stride, order, points ); +} + +static void APIENTRY logMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) +{ + SIG( "glMap2d" ); + dllMap2d( target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points ); +} + +static void APIENTRY logMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) +{ + SIG( "glMap2f" ); + dllMap2f( target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points ); +} + +static void APIENTRY logMapGrid1d(GLint un, GLdouble u1, GLdouble u2) +{ + SIG( "glMapGrid1d" ); + dllMapGrid1d( un, u1, u2 ); +} + +static void APIENTRY logMapGrid1f(GLint un, GLfloat u1, GLfloat u2) +{ + SIG( "glMapGrid1f" ); + dllMapGrid1f( un, u1, u2 ); +} + +static void APIENTRY logMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) +{ + SIG( "glMapGrid2d" ); + dllMapGrid2d( un, u1, u2, vn, v1, v2 ); +} +static void APIENTRY logMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) +{ + SIG( "glMapGrid2f" ); + dllMapGrid2f( un, u1, u2, vn, v1, v2 ); +} +static void APIENTRY logMaterialf(GLenum face, GLenum pname, GLfloat param) +{ + SIG( "glMaterialf" ); + dllMaterialf( face, pname, param ); +} +static void APIENTRY logMaterialfv(GLenum face, GLenum pname, const GLfloat *params) +{ + SIG( "glMaterialfv" ); + dllMaterialfv( face, pname, params ); +} + +static void APIENTRY logMateriali(GLenum face, GLenum pname, GLint param) +{ + SIG( "glMateriali" ); + dllMateriali( face, pname, param ); +} + +static void APIENTRY logMaterialiv(GLenum face, GLenum pname, const GLint *params) +{ + SIG( "glMaterialiv" ); + dllMaterialiv( face, pname, params ); +} + +static void APIENTRY logMatrixMode(GLenum mode) +{ + SIG( "glMatrixMode" ); + dllMatrixMode( mode ); +} + +static void APIENTRY logMultMatrixd(const GLdouble *m) +{ + SIG( "glMultMatrixd" ); + dllMultMatrixd( m ); +} + +static void APIENTRY logMultMatrixf(const GLfloat *m) +{ + SIG( "glMultMatrixf" ); + dllMultMatrixf( m ); +} + +static void APIENTRY logNewList(GLuint list, GLenum mode) +{ + SIG( "glNewList" ); + dllNewList( list, mode ); +} + +static void APIENTRY logNormal3b(GLbyte nx, GLbyte ny, GLbyte nz) +{ + SIG ("glNormal3b" ); + dllNormal3b( nx, ny, nz ); +} + +static void APIENTRY logNormal3bv(const GLbyte *v) +{ + SIG( "glNormal3bv" ); + dllNormal3bv( v ); +} + +static void APIENTRY logNormal3d(GLdouble nx, GLdouble ny, GLdouble nz) +{ + SIG( "glNormal3d" ); + dllNormal3d( nx, ny, nz ); +} + +static void APIENTRY logNormal3dv(const GLdouble *v) +{ + SIG( "glNormal3dv" ); + dllNormal3dv( v ); +} + +static void APIENTRY logNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) +{ + SIG( "glNormal3f" ); + dllNormal3f( nx, ny, nz ); +} + +static void APIENTRY logNormal3fv(const GLfloat *v) +{ + SIG( "glNormal3fv" ); + dllNormal3fv( v ); +} +static void APIENTRY logNormal3i(GLint nx, GLint ny, GLint nz) +{ + SIG( "glNormal3i" ); + dllNormal3i( nx, ny, nz ); +} +static void APIENTRY logNormal3iv(const GLint *v) +{ + SIG( "glNormal3iv" ); + dllNormal3iv( v ); +} +static void APIENTRY logNormal3s(GLshort nx, GLshort ny, GLshort nz) +{ + SIG( "glNormal3s" ); + dllNormal3s( nx, ny, nz ); +} +static void APIENTRY logNormal3sv(const GLshort *v) +{ + SIG( "glNormal3sv" ); + dllNormal3sv( v ); +} +static void APIENTRY logNormalPointer(GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glNormalPointer" ); + dllNormalPointer( type, stride, pointer ); +} +static void APIENTRY logOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) +{ + SIG( "glOrtho" ); + dllOrtho( left, right, bottom, top, zNear, zFar ); +} + +static void APIENTRY logPassThrough(GLfloat token) +{ + SIG( "glPassThrough" ); + dllPassThrough( token ); +} + +static void APIENTRY logPixelMapfv(GLenum map, GLsizei mapsize, const GLfloat *values) +{ + SIG( "glPixelMapfv" ); + dllPixelMapfv( map, mapsize, values ); +} + +static void APIENTRY logPixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values) +{ + SIG( "glPixelMapuiv" ); + dllPixelMapuiv( map, mapsize, values ); +} + +static void APIENTRY logPixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values) +{ + SIG( "glPixelMapusv" ); + dllPixelMapusv( map, mapsize, values ); +} +static void APIENTRY logPixelStoref(GLenum pname, GLfloat param) +{ + SIG( "glPixelStoref" ); + dllPixelStoref( pname, param ); +} +static void APIENTRY logPixelStorei(GLenum pname, GLint param) +{ + SIG( "glPixelStorei" ); + dllPixelStorei( pname, param ); +} +static void APIENTRY logPixelTransferf(GLenum pname, GLfloat param) +{ + SIG( "glPixelTransferf" ); + dllPixelTransferf( pname, param ); +} + +static void APIENTRY logPixelTransferi(GLenum pname, GLint param) +{ + SIG( "glPixelTransferi" ); + dllPixelTransferi( pname, param ); +} + +static void APIENTRY logPixelZoom(GLfloat xfactor, GLfloat yfactor) +{ + SIG( "glPixelZoom" ); + dllPixelZoom( xfactor, yfactor ); +} + +static void APIENTRY logPointSize(GLfloat size) +{ + SIG( "glPointSize" ); + dllPointSize( size ); +} + +static void APIENTRY logPolygonMode(GLenum face, GLenum mode) +{ + fprintf( glw_state.log_fp, "glPolygonMode( 0x%x, 0x%x )\n", face, mode ); + dllPolygonMode( face, mode ); +} + +static void APIENTRY logPolygonOffset(GLfloat factor, GLfloat units) +{ + SIG( "glPolygonOffset" ); + dllPolygonOffset( factor, units ); +} +static void APIENTRY logPolygonStipple(const GLubyte *mask ) +{ + SIG( "glPolygonStipple" ); + dllPolygonStipple( mask ); +} +static void APIENTRY logPopAttrib(void) +{ + SIG( "glPopAttrib" ); + dllPopAttrib(); +} + +static void APIENTRY logPopClientAttrib(void) +{ + SIG( "glPopClientAttrib" ); + dllPopClientAttrib(); +} + +static void APIENTRY logPopMatrix(void) +{ + SIG( "glPopMatrix" ); + dllPopMatrix(); +} + +static void APIENTRY logPopName(void) +{ + SIG( "glPopName" ); + dllPopName(); +} + +static void APIENTRY logPrioritizeTextures(GLsizei n, const GLuint *textures, const GLclampf *priorities) +{ + SIG( "glPrioritizeTextures" ); + dllPrioritizeTextures( n, textures, priorities ); +} + +static void APIENTRY logPushAttrib(GLbitfield mask) +{ + SIG( "glPushAttrib" ); + dllPushAttrib( mask ); +} + +static void APIENTRY logPushClientAttrib(GLbitfield mask) +{ + SIG( "glPushClientAttrib" ); + dllPushClientAttrib( mask ); +} + +static void APIENTRY logPushMatrix(void) +{ + SIG( "glPushMatrix" ); + dllPushMatrix(); +} + +static void APIENTRY logPushName(GLuint name) +{ + SIG( "glPushName" ); + dllPushName( name ); +} + +static void APIENTRY logRasterPos2d(GLdouble x, GLdouble y) +{ + SIG ("glRasterPot2d" ); + dllRasterPos2d( x, y ); +} + +static void APIENTRY logRasterPos2dv(const GLdouble *v) +{ + SIG( "glRasterPos2dv" ); + dllRasterPos2dv( v ); +} + +static void APIENTRY logRasterPos2f(GLfloat x, GLfloat y) +{ + SIG( "glRasterPos2f" ); + dllRasterPos2f( x, y ); +} +static void APIENTRY logRasterPos2fv(const GLfloat *v) +{ + SIG( "glRasterPos2dv" ); + dllRasterPos2fv( v ); +} +static void APIENTRY logRasterPos2i(GLint x, GLint y) +{ + SIG( "glRasterPos2if" ); + dllRasterPos2i( x, y ); +} +static void APIENTRY logRasterPos2iv(const GLint *v) +{ + SIG( "glRasterPos2iv" ); + dllRasterPos2iv( v ); +} +static void APIENTRY logRasterPos2s(GLshort x, GLshort y) +{ + SIG( "glRasterPos2s" ); + dllRasterPos2s( x, y ); +} +static void APIENTRY logRasterPos2sv(const GLshort *v) +{ + SIG( "glRasterPos2sv" ); + dllRasterPos2sv( v ); +} +static void APIENTRY logRasterPos3d(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glRasterPos3d" ); + dllRasterPos3d( x, y, z ); +} +static void APIENTRY logRasterPos3dv(const GLdouble *v) +{ + SIG( "glRasterPos3dv" ); + dllRasterPos3dv( v ); +} +static void APIENTRY logRasterPos3f(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glRasterPos3f" ); + dllRasterPos3f( x, y, z ); +} +static void APIENTRY logRasterPos3fv(const GLfloat *v) +{ + SIG( "glRasterPos3fv" ); + dllRasterPos3fv( v ); +} +static void APIENTRY logRasterPos3i(GLint x, GLint y, GLint z) +{ + SIG( "glRasterPos3i" ); + dllRasterPos3i( x, y, z ); +} +static void APIENTRY logRasterPos3iv(const GLint *v) +{ + SIG( "glRasterPos3iv" ); + dllRasterPos3iv( v ); +} +static void APIENTRY logRasterPos3s(GLshort x, GLshort y, GLshort z) +{ + SIG( "glRasterPos3s" ); + dllRasterPos3s( x, y, z ); +} +static void APIENTRY logRasterPos3sv(const GLshort *v) +{ + SIG( "glRasterPos3sv" ); + dllRasterPos3sv( v ); +} +static void APIENTRY logRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + SIG( "glRasterPos4d" ); + dllRasterPos4d( x, y, z, w ); +} +static void APIENTRY logRasterPos4dv(const GLdouble *v) +{ + SIG( "glRasterPos4dv" ); + dllRasterPos4dv( v ); +} +static void APIENTRY logRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + SIG( "glRasterPos4f" ); + dllRasterPos4f( x, y, z, w ); +} +static void APIENTRY logRasterPos4fv(const GLfloat *v) +{ + SIG( "glRasterPos4fv" ); + dllRasterPos4fv( v ); +} +static void APIENTRY logRasterPos4i(GLint x, GLint y, GLint z, GLint w) +{ + SIG( "glRasterPos4i" ); + dllRasterPos4i( x, y, z, w ); +} +static void APIENTRY logRasterPos4iv(const GLint *v) +{ + SIG( "glRasterPos4iv" ); + dllRasterPos4iv( v ); +} +static void APIENTRY logRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + SIG( "glRasterPos4s" ); + dllRasterPos4s( x, y, z, w ); +} +static void APIENTRY logRasterPos4sv(const GLshort *v) +{ + SIG( "glRasterPos4sv" ); + dllRasterPos4sv( v ); +} +static void APIENTRY logReadBuffer(GLenum mode) +{ + SIG( "glReadBuffer" ); + dllReadBuffer( mode ); +} +static void APIENTRY logReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) +{ + SIG( "glReadPixels" ); + dllReadPixels( x, y, width, height, format, type, pixels ); +} + +static void APIENTRY logRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) +{ + SIG( "glRectd" ); + dllRectd( x1, y1, x2, y2 ); +} + +static void APIENTRY logRectdv(const GLdouble *v1, const GLdouble *v2) +{ + SIG( "glRectdv" ); + dllRectdv( v1, v2 ); +} + +static void APIENTRY logRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) +{ + SIG( "glRectf" ); + dllRectf( x1, y1, x2, y2 ); +} + +static void APIENTRY logRectfv(const GLfloat *v1, const GLfloat *v2) +{ + SIG( "glRectfv" ); + dllRectfv( v1, v2 ); +} +static void APIENTRY logRecti(GLint x1, GLint y1, GLint x2, GLint y2) +{ + SIG( "glRecti" ); + dllRecti( x1, y1, x2, y2 ); +} +static void APIENTRY logRectiv(const GLint *v1, const GLint *v2) +{ + SIG( "glRectiv" ); + dllRectiv( v1, v2 ); +} +static void APIENTRY logRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) +{ + SIG( "glRects" ); + dllRects( x1, y1, x2, y2 ); +} +static void APIENTRY logRectsv(const GLshort *v1, const GLshort *v2) +{ + SIG( "glRectsv" ); + dllRectsv( v1, v2 ); +} +static GLint APIENTRY logRenderMode(GLenum mode) +{ + SIG( "glRenderMode" ); + return dllRenderMode( mode ); +} +static void APIENTRY logRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glRotated" ); + dllRotated( angle, x, y, z ); +} + +static void APIENTRY logRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glRotatef" ); + dllRotatef( angle, x, y, z ); +} + +static void APIENTRY logScaled(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glScaled" ); + dllScaled( x, y, z ); +} + +static void APIENTRY logScalef(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glScalef" ); + dllScalef( x, y, z ); +} + +static void APIENTRY logScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + SIG( "glScissor" ); + dllScissor( x, y, width, height ); +} + +static void APIENTRY logSelectBuffer(GLsizei size, GLuint *buffer) +{ + SIG( "glSelectBuffer" ); + dllSelectBuffer( size, buffer ); +} + +static void APIENTRY logShadeModel(GLenum mode) +{ + SIG( "glShadeModel" ); + dllShadeModel( mode ); +} + +static void APIENTRY logStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + SIG( "glStencilFunc" ); + dllStencilFunc( func, ref, mask ); +} + +static void APIENTRY logStencilMask(GLuint mask) +{ + SIG( "glStencilMask" ); + dllStencilMask( mask ); +} + +static void APIENTRY logStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + SIG( "glStencilOp" ); + dllStencilOp( fail, zfail, zpass ); +} + +static void APIENTRY logTexCoord1d(GLdouble s) +{ + SIG( "glTexCoord1d" ); + dllTexCoord1d( s ); +} + +static void APIENTRY logTexCoord1dv(const GLdouble *v) +{ + SIG( "glTexCoord1dv" ); + dllTexCoord1dv( v ); +} + +static void APIENTRY logTexCoord1f(GLfloat s) +{ + SIG( "glTexCoord1f" ); + dllTexCoord1f( s ); +} +static void APIENTRY logTexCoord1fv(const GLfloat *v) +{ + SIG( "glTexCoord1fv" ); + dllTexCoord1fv( v ); +} +static void APIENTRY logTexCoord1i(GLint s) +{ + SIG( "glTexCoord1i" ); + dllTexCoord1i( s ); +} +static void APIENTRY logTexCoord1iv(const GLint *v) +{ + SIG( "glTexCoord1iv" ); + dllTexCoord1iv( v ); +} +static void APIENTRY logTexCoord1s(GLshort s) +{ + SIG( "glTexCoord1s" ); + dllTexCoord1s( s ); +} +static void APIENTRY logTexCoord1sv(const GLshort *v) +{ + SIG( "glTexCoord1sv" ); + dllTexCoord1sv( v ); +} +static void APIENTRY logTexCoord2d(GLdouble s, GLdouble t) +{ + SIG( "glTexCoord2d" ); + dllTexCoord2d( s, t ); +} + +static void APIENTRY logTexCoord2dv(const GLdouble *v) +{ + SIG( "glTexCoord2dv" ); + dllTexCoord2dv( v ); +} +static void APIENTRY logTexCoord2f(GLfloat s, GLfloat t) +{ + SIG( "glTexCoord2f" ); + dllTexCoord2f( s, t ); +} +static void APIENTRY logTexCoord2fv(const GLfloat *v) +{ + SIG( "glTexCoord2fv" ); + dllTexCoord2fv( v ); +} +static void APIENTRY logTexCoord2i(GLint s, GLint t) +{ + SIG( "glTexCoord2i" ); + dllTexCoord2i( s, t ); +} +static void APIENTRY logTexCoord2iv(const GLint *v) +{ + SIG( "glTexCoord2iv" ); + dllTexCoord2iv( v ); +} +static void APIENTRY logTexCoord2s(GLshort s, GLshort t) +{ + SIG( "glTexCoord2s" ); + dllTexCoord2s( s, t ); +} +static void APIENTRY logTexCoord2sv(const GLshort *v) +{ + SIG( "glTexCoord2sv" ); + dllTexCoord2sv( v ); +} +static void APIENTRY logTexCoord3d(GLdouble s, GLdouble t, GLdouble r) +{ + SIG( "glTexCoord3d" ); + dllTexCoord3d( s, t, r ); +} +static void APIENTRY logTexCoord3dv(const GLdouble *v) +{ + SIG( "glTexCoord3dv" ); + dllTexCoord3dv( v ); +} +static void APIENTRY logTexCoord3f(GLfloat s, GLfloat t, GLfloat r) +{ + SIG( "glTexCoord3f" ); + dllTexCoord3f( s, t, r ); +} +static void APIENTRY logTexCoord3fv(const GLfloat *v) +{ + SIG( "glTexCoord3fv" ); + dllTexCoord3fv( v ); +} +static void APIENTRY logTexCoord3i(GLint s, GLint t, GLint r) +{ + SIG( "glTexCoord3i" ); + dllTexCoord3i( s, t, r ); +} +static void APIENTRY logTexCoord3iv(const GLint *v) +{ + SIG( "glTexCoord3iv" ); + dllTexCoord3iv( v ); +} +static void APIENTRY logTexCoord3s(GLshort s, GLshort t, GLshort r) +{ + SIG( "glTexCoord3s" ); + dllTexCoord3s( s, t, r ); +} +static void APIENTRY logTexCoord3sv(const GLshort *v) +{ + SIG( "glTexCoord3sv" ); + dllTexCoord3sv( v ); +} +static void APIENTRY logTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + SIG( "glTexCoord4d" ); + dllTexCoord4d( s, t, r, q ); +} +static void APIENTRY logTexCoord4dv(const GLdouble *v) +{ + SIG( "glTexCoord4dv" ); + dllTexCoord4dv( v ); +} +static void APIENTRY logTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + SIG( "glTexCoord4f" ); + dllTexCoord4f( s, t, r, q ); +} +static void APIENTRY logTexCoord4fv(const GLfloat *v) +{ + SIG( "glTexCoord4fv" ); + dllTexCoord4fv( v ); +} +static void APIENTRY logTexCoord4i(GLint s, GLint t, GLint r, GLint q) +{ + SIG( "glTexCoord4i" ); + dllTexCoord4i( s, t, r, q ); +} +static void APIENTRY logTexCoord4iv(const GLint *v) +{ + SIG( "glTexCoord4iv" ); + dllTexCoord4iv( v ); +} +static void APIENTRY logTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q) +{ + SIG( "glTexCoord4s" ); + dllTexCoord4s( s, t, r, q ); +} +static void APIENTRY logTexCoord4sv(const GLshort *v) +{ + SIG( "glTexCoord4sv" ); + dllTexCoord4sv( v ); +} +static void APIENTRY logTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glTexCoordPointer" ); + dllTexCoordPointer( size, type, stride, pointer ); +} + +static void APIENTRY logTexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + fprintf( glw_state.log_fp, "glTexEnvf( 0x%x, 0x%x, %f )\n", target, pname, param ); + dllTexEnvf( target, pname, param ); +} + +static void APIENTRY logTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) +{ + SIG( "glTexEnvfv" ); + dllTexEnvfv( target, pname, params ); +} + +static void APIENTRY logTexEnvi(GLenum target, GLenum pname, GLint param) +{ + fprintf( glw_state.log_fp, "glTexEnvi( 0x%x, 0x%x, 0x%x )\n", target, pname, param ); + dllTexEnvi( target, pname, param ); +} +static void APIENTRY logTexEnviv(GLenum target, GLenum pname, const GLint *params) +{ + SIG( "glTexEnviv" ); + dllTexEnviv( target, pname, params ); +} + +static void APIENTRY logTexGend(GLenum coord, GLenum pname, GLdouble param) +{ + SIG( "glTexGend" ); + dllTexGend( coord, pname, param ); +} + +static void APIENTRY logTexGendv(GLenum coord, GLenum pname, const GLdouble *params) +{ + SIG( "glTexGendv" ); + dllTexGendv( coord, pname, params ); +} + +static void APIENTRY logTexGenf(GLenum coord, GLenum pname, GLfloat param) +{ + SIG( "glTexGenf" ); + dllTexGenf( coord, pname, param ); +} +static void APIENTRY logTexGenfv(GLenum coord, GLenum pname, const GLfloat *params) +{ + SIG( "glTexGenfv" ); + dllTexGenfv( coord, pname, params ); +} +static void APIENTRY logTexGeni(GLenum coord, GLenum pname, GLint param) +{ + SIG( "glTexGeni" ); + dllTexGeni( coord, pname, param ); +} +static void APIENTRY logTexGeniv(GLenum coord, GLenum pname, const GLint *params) +{ + SIG( "glTexGeniv" ); + dllTexGeniv( coord, pname, params ); +} +static void APIENTRY logTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexImage1D" ); + dllTexImage1D( target, level, internalformat, width, border, format, type, pixels ); +} +static void APIENTRY logTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexImage2D" ); + dllTexImage2D( target, level, internalformat, width, height, border, format, type, pixels ); +} + +static void APIENTRY logTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + fprintf( glw_state.log_fp, "glTexParameterf( 0x%x, 0x%x, %f )\n", target, pname, param ); + dllTexParameterf( target, pname, param ); +} + +static void APIENTRY logTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + SIG( "glTexParameterfv" ); + dllTexParameterfv( target, pname, params ); +} +static void APIENTRY logTexParameteri(GLenum target, GLenum pname, GLint param) +{ + fprintf( glw_state.log_fp, "glTexParameteri( 0x%x, 0x%x, 0x%x )\n", target, pname, param ); + dllTexParameteri( target, pname, param ); +} +static void APIENTRY logTexParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + SIG( "glTexParameteriv" ); + dllTexParameteriv( target, pname, params ); +} +static void APIENTRY logTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexSubImage1D" ); + dllTexSubImage1D( target, level, xoffset, width, format, type, pixels ); +} +static void APIENTRY logTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexSubImage2D" ); + dllTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels ); +} +static void APIENTRY logTranslated(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glTranslated" ); + dllTranslated( x, y, z ); +} + +static void APIENTRY logTranslatef(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glTranslatef" ); + dllTranslatef( x, y, z ); +} + +static void APIENTRY logVertex2d(GLdouble x, GLdouble y) +{ + SIG( "glVertex2d" ); + dllVertex2d( x, y ); +} + +static void APIENTRY logVertex2dv(const GLdouble *v) +{ + SIG( "glVertex2dv" ); + dllVertex2dv( v ); +} +static void APIENTRY logVertex2f(GLfloat x, GLfloat y) +{ + SIG( "glVertex2f" ); + dllVertex2f( x, y ); +} +static void APIENTRY logVertex2fv(const GLfloat *v) +{ + SIG( "glVertex2fv" ); + dllVertex2fv( v ); +} +static void APIENTRY logVertex2i(GLint x, GLint y) +{ + SIG( "glVertex2i" ); + dllVertex2i( x, y ); +} +static void APIENTRY logVertex2iv(const GLint *v) +{ + SIG( "glVertex2iv" ); + dllVertex2iv( v ); +} +static void APIENTRY logVertex2s(GLshort x, GLshort y) +{ + SIG( "glVertex2s" ); + dllVertex2s( x, y ); +} +static void APIENTRY logVertex2sv(const GLshort *v) +{ + SIG( "glVertex2sv" ); + dllVertex2sv( v ); +} +static void APIENTRY logVertex3d(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glVertex3d" ); + dllVertex3d( x, y, z ); +} +static void APIENTRY logVertex3dv(const GLdouble *v) +{ + SIG( "glVertex3dv" ); + dllVertex3dv( v ); +} +static void APIENTRY logVertex3f(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glVertex3f" ); + dllVertex3f( x, y, z ); +} +static void APIENTRY logVertex3fv(const GLfloat *v) +{ + SIG( "glVertex3fv" ); + dllVertex3fv( v ); +} +static void APIENTRY logVertex3i(GLint x, GLint y, GLint z) +{ + SIG( "glVertex3i" ); + dllVertex3i( x, y, z ); +} +static void APIENTRY logVertex3iv(const GLint *v) +{ + SIG( "glVertex3iv" ); + dllVertex3iv( v ); +} +static void APIENTRY logVertex3s(GLshort x, GLshort y, GLshort z) +{ + SIG( "glVertex3s" ); + dllVertex3s( x, y, z ); +} +static void APIENTRY logVertex3sv(const GLshort *v) +{ + SIG( "glVertex3sv" ); + dllVertex3sv( v ); +} +static void APIENTRY logVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + SIG( "glVertex4d" ); + dllVertex4d( x, y, z, w ); +} +static void APIENTRY logVertex4dv(const GLdouble *v) +{ + SIG( "glVertex4dv" ); + dllVertex4dv( v ); +} +static void APIENTRY logVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + SIG( "glVertex4f" ); + dllVertex4f( x, y, z, w ); +} +static void APIENTRY logVertex4fv(const GLfloat *v) +{ + SIG( "glVertex4fv" ); + dllVertex4fv( v ); +} +static void APIENTRY logVertex4i(GLint x, GLint y, GLint z, GLint w) +{ + SIG( "glVertex4i" ); + dllVertex4i( x, y, z, w ); +} +static void APIENTRY logVertex4iv(const GLint *v) +{ + SIG( "glVertex4iv" ); + dllVertex4iv( v ); +} +static void APIENTRY logVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + SIG( "glVertex4s" ); + dllVertex4s( x, y, z, w ); +} +static void APIENTRY logVertex4sv(const GLshort *v) +{ + SIG( "glVertex4sv" ); + dllVertex4sv( v ); +} +static void APIENTRY logVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glVertexPointer" ); + dllVertexPointer( size, type, stride, pointer ); +} +static void APIENTRY logViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + SIG( "glViewport" ); + dllViewport( x, y, width, height ); +} + +/* +** QGL_Shutdown +** +** Unloads the specified DLL then nulls out all the proc pointers. +*/ +void QGL_Shutdown( void ) +{ + if ( glw_state.hinstOpenGL ) + { + FreeLibrary( glw_state.hinstOpenGL ); + glw_state.hinstOpenGL = NULL; + } + + glw_state.hinstOpenGL = NULL; + + qglAccum = NULL; + qglAlphaFunc = NULL; + qglAreTexturesResident = NULL; + qglArrayElement = NULL; + qglBegin = NULL; + qglBindTexture = NULL; + qglBitmap = NULL; + qglBlendFunc = NULL; + qglCallList = NULL; + qglCallLists = NULL; + qglClear = NULL; + qglClearAccum = NULL; + qglClearColor = NULL; + qglClearDepth = NULL; + qglClearIndex = NULL; + qglClearStencil = NULL; + qglClipPlane = NULL; + qglColor3b = NULL; + qglColor3bv = NULL; + qglColor3d = NULL; + qglColor3dv = NULL; + qglColor3f = NULL; + qglColor3fv = NULL; + qglColor3i = NULL; + qglColor3iv = NULL; + qglColor3s = NULL; + qglColor3sv = NULL; + qglColor3ub = NULL; + qglColor3ubv = NULL; + qglColor3ui = NULL; + qglColor3uiv = NULL; + qglColor3us = NULL; + qglColor3usv = NULL; + qglColor4b = NULL; + qglColor4bv = NULL; + qglColor4d = NULL; + qglColor4dv = NULL; + qglColor4f = NULL; + qglColor4fv = NULL; + qglColor4i = NULL; + qglColor4iv = NULL; + qglColor4s = NULL; + qglColor4sv = NULL; + qglColor4ub = NULL; + qglColor4ubv = NULL; + qglColor4ui = NULL; + qglColor4uiv = NULL; + qglColor4us = NULL; + qglColor4usv = NULL; + qglColorMask = NULL; + qglColorMaterial = NULL; + qglColorPointer = NULL; + qglCopyPixels = NULL; + qglCopyTexImage1D = NULL; + qglCopyTexImage2D = NULL; + qglCopyTexSubImage1D = NULL; + qglCopyTexSubImage2D = NULL; + qglCullFace = NULL; + qglDeleteLists = NULL; + qglDeleteTextures = NULL; + qglDepthFunc = NULL; + qglDepthMask = NULL; + qglDepthRange = NULL; + qglDisable = NULL; + qglDisableClientState = NULL; + qglDrawArrays = NULL; + qglDrawBuffer = NULL; + qglDrawElements = NULL; + qglDrawPixels = NULL; + qglEdgeFlag = NULL; + qglEdgeFlagPointer = NULL; + qglEdgeFlagv = NULL; + qglEnable = NULL; + qglEnableClientState = NULL; + qglEnd = NULL; + qglEndList = NULL; + qglEvalCoord1d = NULL; + qglEvalCoord1dv = NULL; + qglEvalCoord1f = NULL; + qglEvalCoord1fv = NULL; + qglEvalCoord2d = NULL; + qglEvalCoord2dv = NULL; + qglEvalCoord2f = NULL; + qglEvalCoord2fv = NULL; + qglEvalMesh1 = NULL; + qglEvalMesh2 = NULL; + qglEvalPoint1 = NULL; + qglEvalPoint2 = NULL; + qglFeedbackBuffer = NULL; + qglFinish = NULL; + qglFlush = NULL; + qglFogf = NULL; + qglFogfv = NULL; + qglFogi = NULL; + qglFogiv = NULL; + qglFrontFace = NULL; + qglFrustum = NULL; + qglGenLists = NULL; + qglGenTextures = NULL; + qglGetBooleanv = NULL; + qglGetClipPlane = NULL; + qglGetDoublev = NULL; + qglGetError = NULL; + qglGetFloatv = NULL; + qglGetIntegerv = NULL; + qglGetLightfv = NULL; + qglGetLightiv = NULL; + qglGetMapdv = NULL; + qglGetMapfv = NULL; + qglGetMapiv = NULL; + qglGetMaterialfv = NULL; + qglGetMaterialiv = NULL; + qglGetPixelMapfv = NULL; + qglGetPixelMapuiv = NULL; + qglGetPixelMapusv = NULL; + qglGetPointerv = NULL; + qglGetPolygonStipple = NULL; + qglGetString = NULL; + qglGetTexEnvfv = NULL; + qglGetTexEnviv = NULL; + qglGetTexGendv = NULL; + qglGetTexGenfv = NULL; + qglGetTexGeniv = NULL; + qglGetTexImage = NULL; + qglGetTexLevelParameterfv = NULL; + qglGetTexLevelParameteriv = NULL; + qglGetTexParameterfv = NULL; + qglGetTexParameteriv = NULL; + qglHint = NULL; + qglIndexMask = NULL; + qglIndexPointer = NULL; + qglIndexd = NULL; + qglIndexdv = NULL; + qglIndexf = NULL; + qglIndexfv = NULL; + qglIndexi = NULL; + qglIndexiv = NULL; + qglIndexs = NULL; + qglIndexsv = NULL; + qglIndexub = NULL; + qglIndexubv = NULL; + qglInitNames = NULL; + qglInterleavedArrays = NULL; + qglIsEnabled = NULL; + qglIsList = NULL; + qglIsTexture = NULL; + qglLightModelf = NULL; + qglLightModelfv = NULL; + qglLightModeli = NULL; + qglLightModeliv = NULL; + qglLightf = NULL; + qglLightfv = NULL; + qglLighti = NULL; + qglLightiv = NULL; + qglLineStipple = NULL; + qglLineWidth = NULL; + qglListBase = NULL; + qglLoadIdentity = NULL; + qglLoadMatrixd = NULL; + qglLoadMatrixf = NULL; + qglLoadName = NULL; + qglLogicOp = NULL; + qglMap1d = NULL; + qglMap1f = NULL; + qglMap2d = NULL; + qglMap2f = NULL; + qglMapGrid1d = NULL; + qglMapGrid1f = NULL; + qglMapGrid2d = NULL; + qglMapGrid2f = NULL; + qglMaterialf = NULL; + qglMaterialfv = NULL; + qglMateriali = NULL; + qglMaterialiv = NULL; + qglMatrixMode = NULL; + qglMultMatrixd = NULL; + qglMultMatrixf = NULL; + qglNewList = NULL; + qglNormal3b = NULL; + qglNormal3bv = NULL; + qglNormal3d = NULL; + qglNormal3dv = NULL; + qglNormal3f = NULL; + qglNormal3fv = NULL; + qglNormal3i = NULL; + qglNormal3iv = NULL; + qglNormal3s = NULL; + qglNormal3sv = NULL; + qglNormalPointer = NULL; + qglOrtho = NULL; + qglPassThrough = NULL; + qglPixelMapfv = NULL; + qglPixelMapuiv = NULL; + qglPixelMapusv = NULL; + qglPixelStoref = NULL; + qglPixelStorei = NULL; + qglPixelTransferf = NULL; + qglPixelTransferi = NULL; + qglPixelZoom = NULL; + qglPointSize = NULL; + qglPolygonMode = NULL; + qglPolygonOffset = NULL; + qglPolygonStipple = NULL; + qglPopAttrib = NULL; + qglPopClientAttrib = NULL; + qglPopMatrix = NULL; + qglPopName = NULL; + qglPrioritizeTextures = NULL; + qglPushAttrib = NULL; + qglPushClientAttrib = NULL; + qglPushMatrix = NULL; + qglPushName = NULL; + qglRasterPos2d = NULL; + qglRasterPos2dv = NULL; + qglRasterPos2f = NULL; + qglRasterPos2fv = NULL; + qglRasterPos2i = NULL; + qglRasterPos2iv = NULL; + qglRasterPos2s = NULL; + qglRasterPos2sv = NULL; + qglRasterPos3d = NULL; + qglRasterPos3dv = NULL; + qglRasterPos3f = NULL; + qglRasterPos3fv = NULL; + qglRasterPos3i = NULL; + qglRasterPos3iv = NULL; + qglRasterPos3s = NULL; + qglRasterPos3sv = NULL; + qglRasterPos4d = NULL; + qglRasterPos4dv = NULL; + qglRasterPos4f = NULL; + qglRasterPos4fv = NULL; + qglRasterPos4i = NULL; + qglRasterPos4iv = NULL; + qglRasterPos4s = NULL; + qglRasterPos4sv = NULL; + qglReadBuffer = NULL; + qglReadPixels = NULL; + qglRectd = NULL; + qglRectdv = NULL; + qglRectf = NULL; + qglRectfv = NULL; + qglRecti = NULL; + qglRectiv = NULL; + qglRects = NULL; + qglRectsv = NULL; + qglRenderMode = NULL; + qglRotated = NULL; + qglRotatef = NULL; + qglScaled = NULL; + qglScalef = NULL; + qglScissor = NULL; + qglSelectBuffer = NULL; + qglShadeModel = NULL; + qglStencilFunc = NULL; + qglStencilMask = NULL; + qglStencilOp = NULL; + qglTexCoord1d = NULL; + qglTexCoord1dv = NULL; + qglTexCoord1f = NULL; + qglTexCoord1fv = NULL; + qglTexCoord1i = NULL; + qglTexCoord1iv = NULL; + qglTexCoord1s = NULL; + qglTexCoord1sv = NULL; + qglTexCoord2d = NULL; + qglTexCoord2dv = NULL; + qglTexCoord2f = NULL; + qglTexCoord2fv = NULL; + qglTexCoord2i = NULL; + qglTexCoord2iv = NULL; + qglTexCoord2s = NULL; + qglTexCoord2sv = NULL; + qglTexCoord3d = NULL; + qglTexCoord3dv = NULL; + qglTexCoord3f = NULL; + qglTexCoord3fv = NULL; + qglTexCoord3i = NULL; + qglTexCoord3iv = NULL; + qglTexCoord3s = NULL; + qglTexCoord3sv = NULL; + qglTexCoord4d = NULL; + qglTexCoord4dv = NULL; + qglTexCoord4f = NULL; + qglTexCoord4fv = NULL; + qglTexCoord4i = NULL; + qglTexCoord4iv = NULL; + qglTexCoord4s = NULL; + qglTexCoord4sv = NULL; + qglTexCoordPointer = NULL; + qglTexEnvf = NULL; + qglTexEnvfv = NULL; + qglTexEnvi = NULL; + qglTexEnviv = NULL; + qglTexGend = NULL; + qglTexGendv = NULL; + qglTexGenf = NULL; + qglTexGenfv = NULL; + qglTexGeni = NULL; + qglTexGeniv = NULL; + qglTexImage1D = NULL; + qglTexImage2D = NULL; + qglTexParameterf = NULL; + qglTexParameterfv = NULL; + qglTexParameteri = NULL; + qglTexParameteriv = NULL; + qglTexSubImage1D = NULL; + qglTexSubImage2D = NULL; + qglTranslated = NULL; + qglTranslatef = NULL; + qglVertex2d = NULL; + qglVertex2dv = NULL; + qglVertex2f = NULL; + qglVertex2fv = NULL; + qglVertex2i = NULL; + qglVertex2iv = NULL; + qglVertex2s = NULL; + qglVertex2sv = NULL; + qglVertex3d = NULL; + qglVertex3dv = NULL; + qglVertex3f = NULL; + qglVertex3fv = NULL; + qglVertex3i = NULL; + qglVertex3iv = NULL; + qglVertex3s = NULL; + qglVertex3sv = NULL; + qglVertex4d = NULL; + qglVertex4dv = NULL; + qglVertex4f = NULL; + qglVertex4fv = NULL; + qglVertex4i = NULL; + qglVertex4iv = NULL; + qglVertex4s = NULL; + qglVertex4sv = NULL; + qglVertexPointer = NULL; + qglViewport = NULL; + + qwglCopyContext = NULL; + qwglCreateContext = NULL; + qwglCreateLayerContext = NULL; + qwglDeleteContext = NULL; + qwglDescribeLayerPlane = NULL; + qwglGetCurrentContext = NULL; + qwglGetCurrentDC = NULL; + qwglGetLayerPaletteEntries = NULL; + qwglGetProcAddress = NULL; + qwglMakeCurrent = NULL; + qwglRealizeLayerPalette = NULL; + qwglSetLayerPaletteEntries = NULL; + qwglShareLists = NULL; + qwglSwapLayerBuffers = NULL; + qwglUseFontBitmaps = NULL; + qwglUseFontOutlines = NULL; + + qwglChoosePixelFormat = NULL; + qwglDescribePixelFormat = NULL; + qwglGetPixelFormat = NULL; + qwglSetPixelFormat = NULL; + qwglSwapBuffers = NULL; + + qwglSwapIntervalEXT = NULL; + + qwglGetDeviceGammaRampEXT = NULL; + qwglSetDeviceGammaRampEXT = NULL; +} + +# pragma warning (disable : 4113 4133 4047 ) +# define GPA( a ) GetProcAddress( glw_state.hinstOpenGL, a ) + +/* +** QGL_Init +** +** This is responsible for binding our qgl function pointers to +** the appropriate GL stuff. In Windows this means doing a +** LoadLibrary and a bunch of calls to GetProcAddress. On other +** operating systems we need to do the right thing, whatever that +** might be. +** +*/ +qboolean QGL_Init( const char *dllname ) +{ + // update 3Dfx gamma irrespective of underlying DLL + { + char envbuffer[1024]; + float g; + + g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F; + Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g ); + putenv( envbuffer ); + Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g ); + putenv( envbuffer ); + } + + if ( ( glw_state.hinstOpenGL = LoadLibrary( dllname ) ) == 0 ) + { + char *buf = NULL; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buf, 0, NULL); + ri.Con_Printf( PRINT_ALL, "%s\n", buf ); + return false; + } + + gl_config.allow_cds = true; + + qglAccum = dllAccum = GPA( "glAccum" ); + qglAlphaFunc = dllAlphaFunc = GPA( "glAlphaFunc" ); + qglAreTexturesResident = dllAreTexturesResident = GPA( "glAreTexturesResident" ); + qglArrayElement = dllArrayElement = GPA( "glArrayElement" ); + qglBegin = dllBegin = GPA( "glBegin" ); + qglBindTexture = dllBindTexture = GPA( "glBindTexture" ); + qglBitmap = dllBitmap = GPA( "glBitmap" ); + qglBlendFunc = dllBlendFunc = GPA( "glBlendFunc" ); + qglCallList = dllCallList = GPA( "glCallList" ); + qglCallLists = dllCallLists = GPA( "glCallLists" ); + qglClear = dllClear = GPA( "glClear" ); + qglClearAccum = dllClearAccum = GPA( "glClearAccum" ); + qglClearColor = dllClearColor = GPA( "glClearColor" ); + qglClearDepth = dllClearDepth = GPA( "glClearDepth" ); + qglClearIndex = dllClearIndex = GPA( "glClearIndex" ); + qglClearStencil = dllClearStencil = GPA( "glClearStencil" ); + qglClipPlane = dllClipPlane = GPA( "glClipPlane" ); + qglColor3b = dllColor3b = GPA( "glColor3b" ); + qglColor3bv = dllColor3bv = GPA( "glColor3bv" ); + qglColor3d = dllColor3d = GPA( "glColor3d" ); + qglColor3dv = dllColor3dv = GPA( "glColor3dv" ); + qglColor3f = dllColor3f = GPA( "glColor3f" ); + qglColor3fv = dllColor3fv = GPA( "glColor3fv" ); + qglColor3i = dllColor3i = GPA( "glColor3i" ); + qglColor3iv = dllColor3iv = GPA( "glColor3iv" ); + qglColor3s = dllColor3s = GPA( "glColor3s" ); + qglColor3sv = dllColor3sv = GPA( "glColor3sv" ); + qglColor3ub = dllColor3ub = GPA( "glColor3ub" ); + qglColor3ubv = dllColor3ubv = GPA( "glColor3ubv" ); + qglColor3ui = dllColor3ui = GPA( "glColor3ui" ); + qglColor3uiv = dllColor3uiv = GPA( "glColor3uiv" ); + qglColor3us = dllColor3us = GPA( "glColor3us" ); + qglColor3usv = dllColor3usv = GPA( "glColor3usv" ); + qglColor4b = dllColor4b = GPA( "glColor4b" ); + qglColor4bv = dllColor4bv = GPA( "glColor4bv" ); + qglColor4d = dllColor4d = GPA( "glColor4d" ); + qglColor4dv = dllColor4dv = GPA( "glColor4dv" ); + qglColor4f = dllColor4f = GPA( "glColor4f" ); + qglColor4fv = dllColor4fv = GPA( "glColor4fv" ); + qglColor4i = dllColor4i = GPA( "glColor4i" ); + qglColor4iv = dllColor4iv = GPA( "glColor4iv" ); + qglColor4s = dllColor4s = GPA( "glColor4s" ); + qglColor4sv = dllColor4sv = GPA( "glColor4sv" ); + qglColor4ub = dllColor4ub = GPA( "glColor4ub" ); + qglColor4ubv = dllColor4ubv = GPA( "glColor4ubv" ); + qglColor4ui = dllColor4ui = GPA( "glColor4ui" ); + qglColor4uiv = dllColor4uiv = GPA( "glColor4uiv" ); + qglColor4us = dllColor4us = GPA( "glColor4us" ); + qglColor4usv = dllColor4usv = GPA( "glColor4usv" ); + qglColorMask = dllColorMask = GPA( "glColorMask" ); + qglColorMaterial = dllColorMaterial = GPA( "glColorMaterial" ); + qglColorPointer = dllColorPointer = GPA( "glColorPointer" ); + qglCopyPixels = dllCopyPixels = GPA( "glCopyPixels" ); + qglCopyTexImage1D = dllCopyTexImage1D = GPA( "glCopyTexImage1D" ); + qglCopyTexImage2D = dllCopyTexImage2D = GPA( "glCopyTexImage2D" ); + qglCopyTexSubImage1D = dllCopyTexSubImage1D = GPA( "glCopyTexSubImage1D" ); + qglCopyTexSubImage2D = dllCopyTexSubImage2D = GPA( "glCopyTexSubImage2D" ); + qglCullFace = dllCullFace = GPA( "glCullFace" ); + qglDeleteLists = dllDeleteLists = GPA( "glDeleteLists" ); + qglDeleteTextures = dllDeleteTextures = GPA( "glDeleteTextures" ); + qglDepthFunc = dllDepthFunc = GPA( "glDepthFunc" ); + qglDepthMask = dllDepthMask = GPA( "glDepthMask" ); + qglDepthRange = dllDepthRange = GPA( "glDepthRange" ); + qglDisable = dllDisable = GPA( "glDisable" ); + qglDisableClientState = dllDisableClientState = GPA( "glDisableClientState" ); + qglDrawArrays = dllDrawArrays = GPA( "glDrawArrays" ); + qglDrawBuffer = dllDrawBuffer = GPA( "glDrawBuffer" ); + qglDrawElements = dllDrawElements = GPA( "glDrawElements" ); + qglDrawPixels = dllDrawPixels = GPA( "glDrawPixels" ); + qglEdgeFlag = dllEdgeFlag = GPA( "glEdgeFlag" ); + qglEdgeFlagPointer = dllEdgeFlagPointer = GPA( "glEdgeFlagPointer" ); + qglEdgeFlagv = dllEdgeFlagv = GPA( "glEdgeFlagv" ); + qglEnable = dllEnable = GPA( "glEnable" ); + qglEnableClientState = dllEnableClientState = GPA( "glEnableClientState" ); + qglEnd = dllEnd = GPA( "glEnd" ); + qglEndList = dllEndList = GPA( "glEndList" ); + qglEvalCoord1d = dllEvalCoord1d = GPA( "glEvalCoord1d" ); + qglEvalCoord1dv = dllEvalCoord1dv = GPA( "glEvalCoord1dv" ); + qglEvalCoord1f = dllEvalCoord1f = GPA( "glEvalCoord1f" ); + qglEvalCoord1fv = dllEvalCoord1fv = GPA( "glEvalCoord1fv" ); + qglEvalCoord2d = dllEvalCoord2d = GPA( "glEvalCoord2d" ); + qglEvalCoord2dv = dllEvalCoord2dv = GPA( "glEvalCoord2dv" ); + qglEvalCoord2f = dllEvalCoord2f = GPA( "glEvalCoord2f" ); + qglEvalCoord2fv = dllEvalCoord2fv = GPA( "glEvalCoord2fv" ); + qglEvalMesh1 = dllEvalMesh1 = GPA( "glEvalMesh1" ); + qglEvalMesh2 = dllEvalMesh2 = GPA( "glEvalMesh2" ); + qglEvalPoint1 = dllEvalPoint1 = GPA( "glEvalPoint1" ); + qglEvalPoint2 = dllEvalPoint2 = GPA( "glEvalPoint2" ); + qglFeedbackBuffer = dllFeedbackBuffer = GPA( "glFeedbackBuffer" ); + qglFinish = dllFinish = GPA( "glFinish" ); + qglFlush = dllFlush = GPA( "glFlush" ); + qglFogf = dllFogf = GPA( "glFogf" ); + qglFogfv = dllFogfv = GPA( "glFogfv" ); + qglFogi = dllFogi = GPA( "glFogi" ); + qglFogiv = dllFogiv = GPA( "glFogiv" ); + qglFrontFace = dllFrontFace = GPA( "glFrontFace" ); + qglFrustum = dllFrustum = GPA( "glFrustum" ); + qglGenLists = dllGenLists = GPA( "glGenLists" ); + qglGenTextures = dllGenTextures = GPA( "glGenTextures" ); + qglGetBooleanv = dllGetBooleanv = GPA( "glGetBooleanv" ); + qglGetClipPlane = dllGetClipPlane = GPA( "glGetClipPlane" ); + qglGetDoublev = dllGetDoublev = GPA( "glGetDoublev" ); + qglGetError = dllGetError = GPA( "glGetError" ); + qglGetFloatv = dllGetFloatv = GPA( "glGetFloatv" ); + qglGetIntegerv = dllGetIntegerv = GPA( "glGetIntegerv" ); + qglGetLightfv = dllGetLightfv = GPA( "glGetLightfv" ); + qglGetLightiv = dllGetLightiv = GPA( "glGetLightiv" ); + qglGetMapdv = dllGetMapdv = GPA( "glGetMapdv" ); + qglGetMapfv = dllGetMapfv = GPA( "glGetMapfv" ); + qglGetMapiv = dllGetMapiv = GPA( "glGetMapiv" ); + qglGetMaterialfv = dllGetMaterialfv = GPA( "glGetMaterialfv" ); + qglGetMaterialiv = dllGetMaterialiv = GPA( "glGetMaterialiv" ); + qglGetPixelMapfv = dllGetPixelMapfv = GPA( "glGetPixelMapfv" ); + qglGetPixelMapuiv = dllGetPixelMapuiv = GPA( "glGetPixelMapuiv" ); + qglGetPixelMapusv = dllGetPixelMapusv = GPA( "glGetPixelMapusv" ); + qglGetPointerv = dllGetPointerv = GPA( "glGetPointerv" ); + qglGetPolygonStipple = dllGetPolygonStipple = GPA( "glGetPolygonStipple" ); + qglGetString = dllGetString = GPA( "glGetString" ); + qglGetTexEnvfv = dllGetTexEnvfv = GPA( "glGetTexEnvfv" ); + qglGetTexEnviv = dllGetTexEnviv = GPA( "glGetTexEnviv" ); + qglGetTexGendv = dllGetTexGendv = GPA( "glGetTexGendv" ); + qglGetTexGenfv = dllGetTexGenfv = GPA( "glGetTexGenfv" ); + qglGetTexGeniv = dllGetTexGeniv = GPA( "glGetTexGeniv" ); + qglGetTexImage = dllGetTexImage = GPA( "glGetTexImage" ); + qglGetTexLevelParameterfv = dllGetTexLevelParameterfv = GPA( "glGetLevelParameterfv" ); + qglGetTexLevelParameteriv = dllGetTexLevelParameteriv = GPA( "glGetLevelParameteriv" ); + qglGetTexParameterfv = dllGetTexParameterfv = GPA( "glGetTexParameterfv" ); + qglGetTexParameteriv = dllGetTexParameteriv = GPA( "glGetTexParameteriv" ); + qglHint = dllHint = GPA( "glHint" ); + qglIndexMask = dllIndexMask = GPA( "glIndexMask" ); + qglIndexPointer = dllIndexPointer = GPA( "glIndexPointer" ); + qglIndexd = dllIndexd = GPA( "glIndexd" ); + qglIndexdv = dllIndexdv = GPA( "glIndexdv" ); + qglIndexf = dllIndexf = GPA( "glIndexf" ); + qglIndexfv = dllIndexfv = GPA( "glIndexfv" ); + qglIndexi = dllIndexi = GPA( "glIndexi" ); + qglIndexiv = dllIndexiv = GPA( "glIndexiv" ); + qglIndexs = dllIndexs = GPA( "glIndexs" ); + qglIndexsv = dllIndexsv = GPA( "glIndexsv" ); + qglIndexub = dllIndexub = GPA( "glIndexub" ); + qglIndexubv = dllIndexubv = GPA( "glIndexubv" ); + qglInitNames = dllInitNames = GPA( "glInitNames" ); + qglInterleavedArrays = dllInterleavedArrays = GPA( "glInterleavedArrays" ); + qglIsEnabled = dllIsEnabled = GPA( "glIsEnabled" ); + qglIsList = dllIsList = GPA( "glIsList" ); + qglIsTexture = dllIsTexture = GPA( "glIsTexture" ); + qglLightModelf = dllLightModelf = GPA( "glLightModelf" ); + qglLightModelfv = dllLightModelfv = GPA( "glLightModelfv" ); + qglLightModeli = dllLightModeli = GPA( "glLightModeli" ); + qglLightModeliv = dllLightModeliv = GPA( "glLightModeliv" ); + qglLightf = dllLightf = GPA( "glLightf" ); + qglLightfv = dllLightfv = GPA( "glLightfv" ); + qglLighti = dllLighti = GPA( "glLighti" ); + qglLightiv = dllLightiv = GPA( "glLightiv" ); + qglLineStipple = dllLineStipple = GPA( "glLineStipple" ); + qglLineWidth = dllLineWidth = GPA( "glLineWidth" ); + qglListBase = dllListBase = GPA( "glListBase" ); + qglLoadIdentity = dllLoadIdentity = GPA( "glLoadIdentity" ); + qglLoadMatrixd = dllLoadMatrixd = GPA( "glLoadMatrixd" ); + qglLoadMatrixf = dllLoadMatrixf = GPA( "glLoadMatrixf" ); + qglLoadName = dllLoadName = GPA( "glLoadName" ); + qglLogicOp = dllLogicOp = GPA( "glLogicOp" ); + qglMap1d = dllMap1d = GPA( "glMap1d" ); + qglMap1f = dllMap1f = GPA( "glMap1f" ); + qglMap2d = dllMap2d = GPA( "glMap2d" ); + qglMap2f = dllMap2f = GPA( "glMap2f" ); + qglMapGrid1d = dllMapGrid1d = GPA( "glMapGrid1d" ); + qglMapGrid1f = dllMapGrid1f = GPA( "glMapGrid1f" ); + qglMapGrid2d = dllMapGrid2d = GPA( "glMapGrid2d" ); + qglMapGrid2f = dllMapGrid2f = GPA( "glMapGrid2f" ); + qglMaterialf = dllMaterialf = GPA( "glMaterialf" ); + qglMaterialfv = dllMaterialfv = GPA( "glMaterialfv" ); + qglMateriali = dllMateriali = GPA( "glMateriali" ); + qglMaterialiv = dllMaterialiv = GPA( "glMaterialiv" ); + qglMatrixMode = dllMatrixMode = GPA( "glMatrixMode" ); + qglMultMatrixd = dllMultMatrixd = GPA( "glMultMatrixd" ); + qglMultMatrixf = dllMultMatrixf = GPA( "glMultMatrixf" ); + qglNewList = dllNewList = GPA( "glNewList" ); + qglNormal3b = dllNormal3b = GPA( "glNormal3b" ); + qglNormal3bv = dllNormal3bv = GPA( "glNormal3bv" ); + qglNormal3d = dllNormal3d = GPA( "glNormal3d" ); + qglNormal3dv = dllNormal3dv = GPA( "glNormal3dv" ); + qglNormal3f = dllNormal3f = GPA( "glNormal3f" ); + qglNormal3fv = dllNormal3fv = GPA( "glNormal3fv" ); + qglNormal3i = dllNormal3i = GPA( "glNormal3i" ); + qglNormal3iv = dllNormal3iv = GPA( "glNormal3iv" ); + qglNormal3s = dllNormal3s = GPA( "glNormal3s" ); + qglNormal3sv = dllNormal3sv = GPA( "glNormal3sv" ); + qglNormalPointer = dllNormalPointer = GPA( "glNormalPointer" ); + qglOrtho = dllOrtho = GPA( "glOrtho" ); + qglPassThrough = dllPassThrough = GPA( "glPassThrough" ); + qglPixelMapfv = dllPixelMapfv = GPA( "glPixelMapfv" ); + qglPixelMapuiv = dllPixelMapuiv = GPA( "glPixelMapuiv" ); + qglPixelMapusv = dllPixelMapusv = GPA( "glPixelMapusv" ); + qglPixelStoref = dllPixelStoref = GPA( "glPixelStoref" ); + qglPixelStorei = dllPixelStorei = GPA( "glPixelStorei" ); + qglPixelTransferf = dllPixelTransferf = GPA( "glPixelTransferf" ); + qglPixelTransferi = dllPixelTransferi = GPA( "glPixelTransferi" ); + qglPixelZoom = dllPixelZoom = GPA( "glPixelZoom" ); + qglPointSize = dllPointSize = GPA( "glPointSize" ); + qglPolygonMode = dllPolygonMode = GPA( "glPolygonMode" ); + qglPolygonOffset = dllPolygonOffset = GPA( "glPolygonOffset" ); + qglPolygonStipple = dllPolygonStipple = GPA( "glPolygonStipple" ); + qglPopAttrib = dllPopAttrib = GPA( "glPopAttrib" ); + qglPopClientAttrib = dllPopClientAttrib = GPA( "glPopClientAttrib" ); + qglPopMatrix = dllPopMatrix = GPA( "glPopMatrix" ); + qglPopName = dllPopName = GPA( "glPopName" ); + qglPrioritizeTextures = dllPrioritizeTextures = GPA( "glPrioritizeTextures" ); + qglPushAttrib = dllPushAttrib = GPA( "glPushAttrib" ); + qglPushClientAttrib = dllPushClientAttrib = GPA( "glPushClientAttrib" ); + qglPushMatrix = dllPushMatrix = GPA( "glPushMatrix" ); + qglPushName = dllPushName = GPA( "glPushName" ); + qglRasterPos2d = dllRasterPos2d = GPA( "glRasterPos2d" ); + qglRasterPos2dv = dllRasterPos2dv = GPA( "glRasterPos2dv" ); + qglRasterPos2f = dllRasterPos2f = GPA( "glRasterPos2f" ); + qglRasterPos2fv = dllRasterPos2fv = GPA( "glRasterPos2fv" ); + qglRasterPos2i = dllRasterPos2i = GPA( "glRasterPos2i" ); + qglRasterPos2iv = dllRasterPos2iv = GPA( "glRasterPos2iv" ); + qglRasterPos2s = dllRasterPos2s = GPA( "glRasterPos2s" ); + qglRasterPos2sv = dllRasterPos2sv = GPA( "glRasterPos2sv" ); + qglRasterPos3d = dllRasterPos3d = GPA( "glRasterPos3d" ); + qglRasterPos3dv = dllRasterPos3dv = GPA( "glRasterPos3dv" ); + qglRasterPos3f = dllRasterPos3f = GPA( "glRasterPos3f" ); + qglRasterPos3fv = dllRasterPos3fv = GPA( "glRasterPos3fv" ); + qglRasterPos3i = dllRasterPos3i = GPA( "glRasterPos3i" ); + qglRasterPos3iv = dllRasterPos3iv = GPA( "glRasterPos3iv" ); + qglRasterPos3s = dllRasterPos3s = GPA( "glRasterPos3s" ); + qglRasterPos3sv = dllRasterPos3sv = GPA( "glRasterPos3sv" ); + qglRasterPos4d = dllRasterPos4d = GPA( "glRasterPos4d" ); + qglRasterPos4dv = dllRasterPos4dv = GPA( "glRasterPos4dv" ); + qglRasterPos4f = dllRasterPos4f = GPA( "glRasterPos4f" ); + qglRasterPos4fv = dllRasterPos4fv = GPA( "glRasterPos4fv" ); + qglRasterPos4i = dllRasterPos4i = GPA( "glRasterPos4i" ); + qglRasterPos4iv = dllRasterPos4iv = GPA( "glRasterPos4iv" ); + qglRasterPos4s = dllRasterPos4s = GPA( "glRasterPos4s" ); + qglRasterPos4sv = dllRasterPos4sv = GPA( "glRasterPos4sv" ); + qglReadBuffer = dllReadBuffer = GPA( "glReadBuffer" ); + qglReadPixels = dllReadPixels = GPA( "glReadPixels" ); + qglRectd = dllRectd = GPA( "glRectd" ); + qglRectdv = dllRectdv = GPA( "glRectdv" ); + qglRectf = dllRectf = GPA( "glRectf" ); + qglRectfv = dllRectfv = GPA( "glRectfv" ); + qglRecti = dllRecti = GPA( "glRecti" ); + qglRectiv = dllRectiv = GPA( "glRectiv" ); + qglRects = dllRects = GPA( "glRects" ); + qglRectsv = dllRectsv = GPA( "glRectsv" ); + qglRenderMode = dllRenderMode = GPA( "glRenderMode" ); + qglRotated = dllRotated = GPA( "glRotated" ); + qglRotatef = dllRotatef = GPA( "glRotatef" ); + qglScaled = dllScaled = GPA( "glScaled" ); + qglScalef = dllScalef = GPA( "glScalef" ); + qglScissor = dllScissor = GPA( "glScissor" ); + qglSelectBuffer = dllSelectBuffer = GPA( "glSelectBuffer" ); + qglShadeModel = dllShadeModel = GPA( "glShadeModel" ); + qglStencilFunc = dllStencilFunc = GPA( "glStencilFunc" ); + qglStencilMask = dllStencilMask = GPA( "glStencilMask" ); + qglStencilOp = dllStencilOp = GPA( "glStencilOp" ); + qglTexCoord1d = dllTexCoord1d = GPA( "glTexCoord1d" ); + qglTexCoord1dv = dllTexCoord1dv = GPA( "glTexCoord1dv" ); + qglTexCoord1f = dllTexCoord1f = GPA( "glTexCoord1f" ); + qglTexCoord1fv = dllTexCoord1fv = GPA( "glTexCoord1fv" ); + qglTexCoord1i = dllTexCoord1i = GPA( "glTexCoord1i" ); + qglTexCoord1iv = dllTexCoord1iv = GPA( "glTexCoord1iv" ); + qglTexCoord1s = dllTexCoord1s = GPA( "glTexCoord1s" ); + qglTexCoord1sv = dllTexCoord1sv = GPA( "glTexCoord1sv" ); + qglTexCoord2d = dllTexCoord2d = GPA( "glTexCoord2d" ); + qglTexCoord2dv = dllTexCoord2dv = GPA( "glTexCoord2dv" ); + qglTexCoord2f = dllTexCoord2f = GPA( "glTexCoord2f" ); + qglTexCoord2fv = dllTexCoord2fv = GPA( "glTexCoord2fv" ); + qglTexCoord2i = dllTexCoord2i = GPA( "glTexCoord2i" ); + qglTexCoord2iv = dllTexCoord2iv = GPA( "glTexCoord2iv" ); + qglTexCoord2s = dllTexCoord2s = GPA( "glTexCoord2s" ); + qglTexCoord2sv = dllTexCoord2sv = GPA( "glTexCoord2sv" ); + qglTexCoord3d = dllTexCoord3d = GPA( "glTexCoord3d" ); + qglTexCoord3dv = dllTexCoord3dv = GPA( "glTexCoord3dv" ); + qglTexCoord3f = dllTexCoord3f = GPA( "glTexCoord3f" ); + qglTexCoord3fv = dllTexCoord3fv = GPA( "glTexCoord3fv" ); + qglTexCoord3i = dllTexCoord3i = GPA( "glTexCoord3i" ); + qglTexCoord3iv = dllTexCoord3iv = GPA( "glTexCoord3iv" ); + qglTexCoord3s = dllTexCoord3s = GPA( "glTexCoord3s" ); + qglTexCoord3sv = dllTexCoord3sv = GPA( "glTexCoord3sv" ); + qglTexCoord4d = dllTexCoord4d = GPA( "glTexCoord4d" ); + qglTexCoord4dv = dllTexCoord4dv = GPA( "glTexCoord4dv" ); + qglTexCoord4f = dllTexCoord4f = GPA( "glTexCoord4f" ); + qglTexCoord4fv = dllTexCoord4fv = GPA( "glTexCoord4fv" ); + qglTexCoord4i = dllTexCoord4i = GPA( "glTexCoord4i" ); + qglTexCoord4iv = dllTexCoord4iv = GPA( "glTexCoord4iv" ); + qglTexCoord4s = dllTexCoord4s = GPA( "glTexCoord4s" ); + qglTexCoord4sv = dllTexCoord4sv = GPA( "glTexCoord4sv" ); + qglTexCoordPointer = dllTexCoordPointer = GPA( "glTexCoordPointer" ); + qglTexEnvf = dllTexEnvf = GPA( "glTexEnvf" ); + qglTexEnvfv = dllTexEnvfv = GPA( "glTexEnvfv" ); + qglTexEnvi = dllTexEnvi = GPA( "glTexEnvi" ); + qglTexEnviv = dllTexEnviv = GPA( "glTexEnviv" ); + qglTexGend = dllTexGend = GPA( "glTexGend" ); + qglTexGendv = dllTexGendv = GPA( "glTexGendv" ); + qglTexGenf = dllTexGenf = GPA( "glTexGenf" ); + qglTexGenfv = dllTexGenfv = GPA( "glTexGenfv" ); + qglTexGeni = dllTexGeni = GPA( "glTexGeni" ); + qglTexGeniv = dllTexGeniv = GPA( "glTexGeniv" ); + qglTexImage1D = dllTexImage1D = GPA( "glTexImage1D" ); + qglTexImage2D = dllTexImage2D = GPA( "glTexImage2D" ); + qglTexParameterf = dllTexParameterf = GPA( "glTexParameterf" ); + qglTexParameterfv = dllTexParameterfv = GPA( "glTexParameterfv" ); + qglTexParameteri = dllTexParameteri = GPA( "glTexParameteri" ); + qglTexParameteriv = dllTexParameteriv = GPA( "glTexParameteriv" ); + qglTexSubImage1D = dllTexSubImage1D = GPA( "glTexSubImage1D" ); + qglTexSubImage2D = dllTexSubImage2D = GPA( "glTexSubImage2D" ); + qglTranslated = dllTranslated = GPA( "glTranslated" ); + qglTranslatef = dllTranslatef = GPA( "glTranslatef" ); + qglVertex2d = dllVertex2d = GPA( "glVertex2d" ); + qglVertex2dv = dllVertex2dv = GPA( "glVertex2dv" ); + qglVertex2f = dllVertex2f = GPA( "glVertex2f" ); + qglVertex2fv = dllVertex2fv = GPA( "glVertex2fv" ); + qglVertex2i = dllVertex2i = GPA( "glVertex2i" ); + qglVertex2iv = dllVertex2iv = GPA( "glVertex2iv" ); + qglVertex2s = dllVertex2s = GPA( "glVertex2s" ); + qglVertex2sv = dllVertex2sv = GPA( "glVertex2sv" ); + qglVertex3d = dllVertex3d = GPA( "glVertex3d" ); + qglVertex3dv = dllVertex3dv = GPA( "glVertex3dv" ); + qglVertex3f = dllVertex3f = GPA( "glVertex3f" ); + qglVertex3fv = dllVertex3fv = GPA( "glVertex3fv" ); + qglVertex3i = dllVertex3i = GPA( "glVertex3i" ); + qglVertex3iv = dllVertex3iv = GPA( "glVertex3iv" ); + qglVertex3s = dllVertex3s = GPA( "glVertex3s" ); + qglVertex3sv = dllVertex3sv = GPA( "glVertex3sv" ); + qglVertex4d = dllVertex4d = GPA( "glVertex4d" ); + qglVertex4dv = dllVertex4dv = GPA( "glVertex4dv" ); + qglVertex4f = dllVertex4f = GPA( "glVertex4f" ); + qglVertex4fv = dllVertex4fv = GPA( "glVertex4fv" ); + qglVertex4i = dllVertex4i = GPA( "glVertex4i" ); + qglVertex4iv = dllVertex4iv = GPA( "glVertex4iv" ); + qglVertex4s = dllVertex4s = GPA( "glVertex4s" ); + qglVertex4sv = dllVertex4sv = GPA( "glVertex4sv" ); + qglVertexPointer = dllVertexPointer = GPA( "glVertexPointer" ); + qglViewport = dllViewport = GPA( "glViewport" ); + + qwglCopyContext = GPA( "wglCopyContext" ); + qwglCreateContext = GPA( "wglCreateContext" ); + qwglCreateLayerContext = GPA( "wglCreateLayerContext" ); + qwglDeleteContext = GPA( "wglDeleteContext" ); + qwglDescribeLayerPlane = GPA( "wglDescribeLayerPlane" ); + qwglGetCurrentContext = GPA( "wglGetCurrentContext" ); + qwglGetCurrentDC = GPA( "wglGetCurrentDC" ); + qwglGetLayerPaletteEntries = GPA( "wglGetLayerPaletteEntries" ); + qwglGetProcAddress = GPA( "wglGetProcAddress" ); + qwglMakeCurrent = GPA( "wglMakeCurrent" ); + qwglRealizeLayerPalette = GPA( "wglRealizeLayerPalette" ); + qwglSetLayerPaletteEntries = GPA( "wglSetLayerPaletteEntries" ); + qwglShareLists = GPA( "wglShareLists" ); + qwglSwapLayerBuffers = GPA( "wglSwapLayerBuffers" ); + qwglUseFontBitmaps = GPA( "wglUseFontBitmapsA" ); + qwglUseFontOutlines = GPA( "wglUseFontOutlinesA" ); + + qwglChoosePixelFormat = GPA( "wglChoosePixelFormat" ); + qwglDescribePixelFormat = GPA( "wglDescribePixelFormat" ); + qwglGetPixelFormat = GPA( "wglGetPixelFormat" ); + qwglSetPixelFormat = GPA( "wglSetPixelFormat" ); + qwglSwapBuffers = GPA( "wglSwapBuffers" ); + + qwglSwapIntervalEXT = 0; + qglPointParameterfEXT = 0; + qglPointParameterfvEXT = 0; + qglColorTableEXT = 0; + qglSelectTextureSGIS = 0; + qglMTexCoord2fSGIS = 0; + + return true; +} + +void GLimp_EnableLogging( qboolean enable ) +{ + if ( enable ) + { + if ( !glw_state.log_fp ) + { + struct tm *newtime; + time_t aclock; + char buffer[1024]; + + time( &aclock ); + newtime = localtime( &aclock ); + + asctime( newtime ); + + Com_sprintf( buffer, sizeof(buffer), "%s/gl.log", ri.FS_Gamedir() ); + glw_state.log_fp = fopen( buffer, "wt" ); + + fprintf( glw_state.log_fp, "%s\n", asctime( newtime ) ); + } + + qglAccum = logAccum; + qglAlphaFunc = logAlphaFunc; + qglAreTexturesResident = logAreTexturesResident; + qglArrayElement = logArrayElement; + qglBegin = logBegin; + qglBindTexture = logBindTexture; + qglBitmap = logBitmap; + qglBlendFunc = logBlendFunc; + qglCallList = logCallList; + qglCallLists = logCallLists; + qglClear = logClear; + qglClearAccum = logClearAccum; + qglClearColor = logClearColor; + qglClearDepth = logClearDepth; + qglClearIndex = logClearIndex; + qglClearStencil = logClearStencil; + qglClipPlane = logClipPlane; + qglColor3b = logColor3b; + qglColor3bv = logColor3bv; + qglColor3d = logColor3d; + qglColor3dv = logColor3dv; + qglColor3f = logColor3f; + qglColor3fv = logColor3fv; + qglColor3i = logColor3i; + qglColor3iv = logColor3iv; + qglColor3s = logColor3s; + qglColor3sv = logColor3sv; + qglColor3ub = logColor3ub; + qglColor3ubv = logColor3ubv; + qglColor3ui = logColor3ui; + qglColor3uiv = logColor3uiv; + qglColor3us = logColor3us; + qglColor3usv = logColor3usv; + qglColor4b = logColor4b; + qglColor4bv = logColor4bv; + qglColor4d = logColor4d; + qglColor4dv = logColor4dv; + qglColor4f = logColor4f; + qglColor4fv = logColor4fv; + qglColor4i = logColor4i; + qglColor4iv = logColor4iv; + qglColor4s = logColor4s; + qglColor4sv = logColor4sv; + qglColor4ub = logColor4ub; + qglColor4ubv = logColor4ubv; + qglColor4ui = logColor4ui; + qglColor4uiv = logColor4uiv; + qglColor4us = logColor4us; + qglColor4usv = logColor4usv; + qglColorMask = logColorMask; + qglColorMaterial = logColorMaterial; + qglColorPointer = logColorPointer; + qglCopyPixels = logCopyPixels; + qglCopyTexImage1D = logCopyTexImage1D; + qglCopyTexImage2D = logCopyTexImage2D; + qglCopyTexSubImage1D = logCopyTexSubImage1D; + qglCopyTexSubImage2D = logCopyTexSubImage2D; + qglCullFace = logCullFace; + qglDeleteLists = logDeleteLists ; + qglDeleteTextures = logDeleteTextures ; + qglDepthFunc = logDepthFunc ; + qglDepthMask = logDepthMask ; + qglDepthRange = logDepthRange ; + qglDisable = logDisable ; + qglDisableClientState = logDisableClientState ; + qglDrawArrays = logDrawArrays ; + qglDrawBuffer = logDrawBuffer ; + qglDrawElements = logDrawElements ; + qglDrawPixels = logDrawPixels ; + qglEdgeFlag = logEdgeFlag ; + qglEdgeFlagPointer = logEdgeFlagPointer ; + qglEdgeFlagv = logEdgeFlagv ; + qglEnable = logEnable ; + qglEnableClientState = logEnableClientState ; + qglEnd = logEnd ; + qglEndList = logEndList ; + qglEvalCoord1d = logEvalCoord1d ; + qglEvalCoord1dv = logEvalCoord1dv ; + qglEvalCoord1f = logEvalCoord1f ; + qglEvalCoord1fv = logEvalCoord1fv ; + qglEvalCoord2d = logEvalCoord2d ; + qglEvalCoord2dv = logEvalCoord2dv ; + qglEvalCoord2f = logEvalCoord2f ; + qglEvalCoord2fv = logEvalCoord2fv ; + qglEvalMesh1 = logEvalMesh1 ; + qglEvalMesh2 = logEvalMesh2 ; + qglEvalPoint1 = logEvalPoint1 ; + qglEvalPoint2 = logEvalPoint2 ; + qglFeedbackBuffer = logFeedbackBuffer ; + qglFinish = logFinish ; + qglFlush = logFlush ; + qglFogf = logFogf ; + qglFogfv = logFogfv ; + qglFogi = logFogi ; + qglFogiv = logFogiv ; + qglFrontFace = logFrontFace ; + qglFrustum = logFrustum ; + qglGenLists = logGenLists ; + qglGenTextures = logGenTextures ; + qglGetBooleanv = logGetBooleanv ; + qglGetClipPlane = logGetClipPlane ; + qglGetDoublev = logGetDoublev ; + qglGetError = logGetError ; + qglGetFloatv = logGetFloatv ; + qglGetIntegerv = logGetIntegerv ; + qglGetLightfv = logGetLightfv ; + qglGetLightiv = logGetLightiv ; + qglGetMapdv = logGetMapdv ; + qglGetMapfv = logGetMapfv ; + qglGetMapiv = logGetMapiv ; + qglGetMaterialfv = logGetMaterialfv ; + qglGetMaterialiv = logGetMaterialiv ; + qglGetPixelMapfv = logGetPixelMapfv ; + qglGetPixelMapuiv = logGetPixelMapuiv ; + qglGetPixelMapusv = logGetPixelMapusv ; + qglGetPointerv = logGetPointerv ; + qglGetPolygonStipple = logGetPolygonStipple ; + qglGetString = logGetString ; + qglGetTexEnvfv = logGetTexEnvfv ; + qglGetTexEnviv = logGetTexEnviv ; + qglGetTexGendv = logGetTexGendv ; + qglGetTexGenfv = logGetTexGenfv ; + qglGetTexGeniv = logGetTexGeniv ; + qglGetTexImage = logGetTexImage ; + qglGetTexLevelParameterfv = logGetTexLevelParameterfv ; + qglGetTexLevelParameteriv = logGetTexLevelParameteriv ; + qglGetTexParameterfv = logGetTexParameterfv ; + qglGetTexParameteriv = logGetTexParameteriv ; + qglHint = logHint ; + qglIndexMask = logIndexMask ; + qglIndexPointer = logIndexPointer ; + qglIndexd = logIndexd ; + qglIndexdv = logIndexdv ; + qglIndexf = logIndexf ; + qglIndexfv = logIndexfv ; + qglIndexi = logIndexi ; + qglIndexiv = logIndexiv ; + qglIndexs = logIndexs ; + qglIndexsv = logIndexsv ; + qglIndexub = logIndexub ; + qglIndexubv = logIndexubv ; + qglInitNames = logInitNames ; + qglInterleavedArrays = logInterleavedArrays ; + qglIsEnabled = logIsEnabled ; + qglIsList = logIsList ; + qglIsTexture = logIsTexture ; + qglLightModelf = logLightModelf ; + qglLightModelfv = logLightModelfv ; + qglLightModeli = logLightModeli ; + qglLightModeliv = logLightModeliv ; + qglLightf = logLightf ; + qglLightfv = logLightfv ; + qglLighti = logLighti ; + qglLightiv = logLightiv ; + qglLineStipple = logLineStipple ; + qglLineWidth = logLineWidth ; + qglListBase = logListBase ; + qglLoadIdentity = logLoadIdentity ; + qglLoadMatrixd = logLoadMatrixd ; + qglLoadMatrixf = logLoadMatrixf ; + qglLoadName = logLoadName ; + qglLogicOp = logLogicOp ; + qglMap1d = logMap1d ; + qglMap1f = logMap1f ; + qglMap2d = logMap2d ; + qglMap2f = logMap2f ; + qglMapGrid1d = logMapGrid1d ; + qglMapGrid1f = logMapGrid1f ; + qglMapGrid2d = logMapGrid2d ; + qglMapGrid2f = logMapGrid2f ; + qglMaterialf = logMaterialf ; + qglMaterialfv = logMaterialfv ; + qglMateriali = logMateriali ; + qglMaterialiv = logMaterialiv ; + qglMatrixMode = logMatrixMode ; + qglMultMatrixd = logMultMatrixd ; + qglMultMatrixf = logMultMatrixf ; + qglNewList = logNewList ; + qglNormal3b = logNormal3b ; + qglNormal3bv = logNormal3bv ; + qglNormal3d = logNormal3d ; + qglNormal3dv = logNormal3dv ; + qglNormal3f = logNormal3f ; + qglNormal3fv = logNormal3fv ; + qglNormal3i = logNormal3i ; + qglNormal3iv = logNormal3iv ; + qglNormal3s = logNormal3s ; + qglNormal3sv = logNormal3sv ; + qglNormalPointer = logNormalPointer ; + qglOrtho = logOrtho ; + qglPassThrough = logPassThrough ; + qglPixelMapfv = logPixelMapfv ; + qglPixelMapuiv = logPixelMapuiv ; + qglPixelMapusv = logPixelMapusv ; + qglPixelStoref = logPixelStoref ; + qglPixelStorei = logPixelStorei ; + qglPixelTransferf = logPixelTransferf ; + qglPixelTransferi = logPixelTransferi ; + qglPixelZoom = logPixelZoom ; + qglPointSize = logPointSize ; + qglPolygonMode = logPolygonMode ; + qglPolygonOffset = logPolygonOffset ; + qglPolygonStipple = logPolygonStipple ; + qglPopAttrib = logPopAttrib ; + qglPopClientAttrib = logPopClientAttrib ; + qglPopMatrix = logPopMatrix ; + qglPopName = logPopName ; + qglPrioritizeTextures = logPrioritizeTextures ; + qglPushAttrib = logPushAttrib ; + qglPushClientAttrib = logPushClientAttrib ; + qglPushMatrix = logPushMatrix ; + qglPushName = logPushName ; + qglRasterPos2d = logRasterPos2d ; + qglRasterPos2dv = logRasterPos2dv ; + qglRasterPos2f = logRasterPos2f ; + qglRasterPos2fv = logRasterPos2fv ; + qglRasterPos2i = logRasterPos2i ; + qglRasterPos2iv = logRasterPos2iv ; + qglRasterPos2s = logRasterPos2s ; + qglRasterPos2sv = logRasterPos2sv ; + qglRasterPos3d = logRasterPos3d ; + qglRasterPos3dv = logRasterPos3dv ; + qglRasterPos3f = logRasterPos3f ; + qglRasterPos3fv = logRasterPos3fv ; + qglRasterPos3i = logRasterPos3i ; + qglRasterPos3iv = logRasterPos3iv ; + qglRasterPos3s = logRasterPos3s ; + qglRasterPos3sv = logRasterPos3sv ; + qglRasterPos4d = logRasterPos4d ; + qglRasterPos4dv = logRasterPos4dv ; + qglRasterPos4f = logRasterPos4f ; + qglRasterPos4fv = logRasterPos4fv ; + qglRasterPos4i = logRasterPos4i ; + qglRasterPos4iv = logRasterPos4iv ; + qglRasterPos4s = logRasterPos4s ; + qglRasterPos4sv = logRasterPos4sv ; + qglReadBuffer = logReadBuffer ; + qglReadPixels = logReadPixels ; + qglRectd = logRectd ; + qglRectdv = logRectdv ; + qglRectf = logRectf ; + qglRectfv = logRectfv ; + qglRecti = logRecti ; + qglRectiv = logRectiv ; + qglRects = logRects ; + qglRectsv = logRectsv ; + qglRenderMode = logRenderMode ; + qglRotated = logRotated ; + qglRotatef = logRotatef ; + qglScaled = logScaled ; + qglScalef = logScalef ; + qglScissor = logScissor ; + qglSelectBuffer = logSelectBuffer ; + qglShadeModel = logShadeModel ; + qglStencilFunc = logStencilFunc ; + qglStencilMask = logStencilMask ; + qglStencilOp = logStencilOp ; + qglTexCoord1d = logTexCoord1d ; + qglTexCoord1dv = logTexCoord1dv ; + qglTexCoord1f = logTexCoord1f ; + qglTexCoord1fv = logTexCoord1fv ; + qglTexCoord1i = logTexCoord1i ; + qglTexCoord1iv = logTexCoord1iv ; + qglTexCoord1s = logTexCoord1s ; + qglTexCoord1sv = logTexCoord1sv ; + qglTexCoord2d = logTexCoord2d ; + qglTexCoord2dv = logTexCoord2dv ; + qglTexCoord2f = logTexCoord2f ; + qglTexCoord2fv = logTexCoord2fv ; + qglTexCoord2i = logTexCoord2i ; + qglTexCoord2iv = logTexCoord2iv ; + qglTexCoord2s = logTexCoord2s ; + qglTexCoord2sv = logTexCoord2sv ; + qglTexCoord3d = logTexCoord3d ; + qglTexCoord3dv = logTexCoord3dv ; + qglTexCoord3f = logTexCoord3f ; + qglTexCoord3fv = logTexCoord3fv ; + qglTexCoord3i = logTexCoord3i ; + qglTexCoord3iv = logTexCoord3iv ; + qglTexCoord3s = logTexCoord3s ; + qglTexCoord3sv = logTexCoord3sv ; + qglTexCoord4d = logTexCoord4d ; + qglTexCoord4dv = logTexCoord4dv ; + qglTexCoord4f = logTexCoord4f ; + qglTexCoord4fv = logTexCoord4fv ; + qglTexCoord4i = logTexCoord4i ; + qglTexCoord4iv = logTexCoord4iv ; + qglTexCoord4s = logTexCoord4s ; + qglTexCoord4sv = logTexCoord4sv ; + qglTexCoordPointer = logTexCoordPointer ; + qglTexEnvf = logTexEnvf ; + qglTexEnvfv = logTexEnvfv ; + qglTexEnvi = logTexEnvi ; + qglTexEnviv = logTexEnviv ; + qglTexGend = logTexGend ; + qglTexGendv = logTexGendv ; + qglTexGenf = logTexGenf ; + qglTexGenfv = logTexGenfv ; + qglTexGeni = logTexGeni ; + qglTexGeniv = logTexGeniv ; + qglTexImage1D = logTexImage1D ; + qglTexImage2D = logTexImage2D ; + qglTexParameterf = logTexParameterf ; + qglTexParameterfv = logTexParameterfv ; + qglTexParameteri = logTexParameteri ; + qglTexParameteriv = logTexParameteriv ; + qglTexSubImage1D = logTexSubImage1D ; + qglTexSubImage2D = logTexSubImage2D ; + qglTranslated = logTranslated ; + qglTranslatef = logTranslatef ; + qglVertex2d = logVertex2d ; + qglVertex2dv = logVertex2dv ; + qglVertex2f = logVertex2f ; + qglVertex2fv = logVertex2fv ; + qglVertex2i = logVertex2i ; + qglVertex2iv = logVertex2iv ; + qglVertex2s = logVertex2s ; + qglVertex2sv = logVertex2sv ; + qglVertex3d = logVertex3d ; + qglVertex3dv = logVertex3dv ; + qglVertex3f = logVertex3f ; + qglVertex3fv = logVertex3fv ; + qglVertex3i = logVertex3i ; + qglVertex3iv = logVertex3iv ; + qglVertex3s = logVertex3s ; + qglVertex3sv = logVertex3sv ; + qglVertex4d = logVertex4d ; + qglVertex4dv = logVertex4dv ; + qglVertex4f = logVertex4f ; + qglVertex4fv = logVertex4fv ; + qglVertex4i = logVertex4i ; + qglVertex4iv = logVertex4iv ; + qglVertex4s = logVertex4s ; + qglVertex4sv = logVertex4sv ; + qglVertexPointer = logVertexPointer ; + qglViewport = logViewport ; + } + else + { + qglAccum = dllAccum; + qglAlphaFunc = dllAlphaFunc; + qglAreTexturesResident = dllAreTexturesResident; + qglArrayElement = dllArrayElement; + qglBegin = dllBegin; + qglBindTexture = dllBindTexture; + qglBitmap = dllBitmap; + qglBlendFunc = dllBlendFunc; + qglCallList = dllCallList; + qglCallLists = dllCallLists; + qglClear = dllClear; + qglClearAccum = dllClearAccum; + qglClearColor = dllClearColor; + qglClearDepth = dllClearDepth; + qglClearIndex = dllClearIndex; + qglClearStencil = dllClearStencil; + qglClipPlane = dllClipPlane; + qglColor3b = dllColor3b; + qglColor3bv = dllColor3bv; + qglColor3d = dllColor3d; + qglColor3dv = dllColor3dv; + qglColor3f = dllColor3f; + qglColor3fv = dllColor3fv; + qglColor3i = dllColor3i; + qglColor3iv = dllColor3iv; + qglColor3s = dllColor3s; + qglColor3sv = dllColor3sv; + qglColor3ub = dllColor3ub; + qglColor3ubv = dllColor3ubv; + qglColor3ui = dllColor3ui; + qglColor3uiv = dllColor3uiv; + qglColor3us = dllColor3us; + qglColor3usv = dllColor3usv; + qglColor4b = dllColor4b; + qglColor4bv = dllColor4bv; + qglColor4d = dllColor4d; + qglColor4dv = dllColor4dv; + qglColor4f = dllColor4f; + qglColor4fv = dllColor4fv; + qglColor4i = dllColor4i; + qglColor4iv = dllColor4iv; + qglColor4s = dllColor4s; + qglColor4sv = dllColor4sv; + qglColor4ub = dllColor4ub; + qglColor4ubv = dllColor4ubv; + qglColor4ui = dllColor4ui; + qglColor4uiv = dllColor4uiv; + qglColor4us = dllColor4us; + qglColor4usv = dllColor4usv; + qglColorMask = dllColorMask; + qglColorMaterial = dllColorMaterial; + qglColorPointer = dllColorPointer; + qglCopyPixels = dllCopyPixels; + qglCopyTexImage1D = dllCopyTexImage1D; + qglCopyTexImage2D = dllCopyTexImage2D; + qglCopyTexSubImage1D = dllCopyTexSubImage1D; + qglCopyTexSubImage2D = dllCopyTexSubImage2D; + qglCullFace = dllCullFace; + qglDeleteLists = dllDeleteLists ; + qglDeleteTextures = dllDeleteTextures ; + qglDepthFunc = dllDepthFunc ; + qglDepthMask = dllDepthMask ; + qglDepthRange = dllDepthRange ; + qglDisable = dllDisable ; + qglDisableClientState = dllDisableClientState ; + qglDrawArrays = dllDrawArrays ; + qglDrawBuffer = dllDrawBuffer ; + qglDrawElements = dllDrawElements ; + qglDrawPixels = dllDrawPixels ; + qglEdgeFlag = dllEdgeFlag ; + qglEdgeFlagPointer = dllEdgeFlagPointer ; + qglEdgeFlagv = dllEdgeFlagv ; + qglEnable = dllEnable ; + qglEnableClientState = dllEnableClientState ; + qglEnd = dllEnd ; + qglEndList = dllEndList ; + qglEvalCoord1d = dllEvalCoord1d ; + qglEvalCoord1dv = dllEvalCoord1dv ; + qglEvalCoord1f = dllEvalCoord1f ; + qglEvalCoord1fv = dllEvalCoord1fv ; + qglEvalCoord2d = dllEvalCoord2d ; + qglEvalCoord2dv = dllEvalCoord2dv ; + qglEvalCoord2f = dllEvalCoord2f ; + qglEvalCoord2fv = dllEvalCoord2fv ; + qglEvalMesh1 = dllEvalMesh1 ; + qglEvalMesh2 = dllEvalMesh2 ; + qglEvalPoint1 = dllEvalPoint1 ; + qglEvalPoint2 = dllEvalPoint2 ; + qglFeedbackBuffer = dllFeedbackBuffer ; + qglFinish = dllFinish ; + qglFlush = dllFlush ; + qglFogf = dllFogf ; + qglFogfv = dllFogfv ; + qglFogi = dllFogi ; + qglFogiv = dllFogiv ; + qglFrontFace = dllFrontFace ; + qglFrustum = dllFrustum ; + qglGenLists = dllGenLists ; + qglGenTextures = dllGenTextures ; + qglGetBooleanv = dllGetBooleanv ; + qglGetClipPlane = dllGetClipPlane ; + qglGetDoublev = dllGetDoublev ; + qglGetError = dllGetError ; + qglGetFloatv = dllGetFloatv ; + qglGetIntegerv = dllGetIntegerv ; + qglGetLightfv = dllGetLightfv ; + qglGetLightiv = dllGetLightiv ; + qglGetMapdv = dllGetMapdv ; + qglGetMapfv = dllGetMapfv ; + qglGetMapiv = dllGetMapiv ; + qglGetMaterialfv = dllGetMaterialfv ; + qglGetMaterialiv = dllGetMaterialiv ; + qglGetPixelMapfv = dllGetPixelMapfv ; + qglGetPixelMapuiv = dllGetPixelMapuiv ; + qglGetPixelMapusv = dllGetPixelMapusv ; + qglGetPointerv = dllGetPointerv ; + qglGetPolygonStipple = dllGetPolygonStipple ; + qglGetString = dllGetString ; + qglGetTexEnvfv = dllGetTexEnvfv ; + qglGetTexEnviv = dllGetTexEnviv ; + qglGetTexGendv = dllGetTexGendv ; + qglGetTexGenfv = dllGetTexGenfv ; + qglGetTexGeniv = dllGetTexGeniv ; + qglGetTexImage = dllGetTexImage ; + qglGetTexLevelParameterfv = dllGetTexLevelParameterfv ; + qglGetTexLevelParameteriv = dllGetTexLevelParameteriv ; + qglGetTexParameterfv = dllGetTexParameterfv ; + qglGetTexParameteriv = dllGetTexParameteriv ; + qglHint = dllHint ; + qglIndexMask = dllIndexMask ; + qglIndexPointer = dllIndexPointer ; + qglIndexd = dllIndexd ; + qglIndexdv = dllIndexdv ; + qglIndexf = dllIndexf ; + qglIndexfv = dllIndexfv ; + qglIndexi = dllIndexi ; + qglIndexiv = dllIndexiv ; + qglIndexs = dllIndexs ; + qglIndexsv = dllIndexsv ; + qglIndexub = dllIndexub ; + qglIndexubv = dllIndexubv ; + qglInitNames = dllInitNames ; + qglInterleavedArrays = dllInterleavedArrays ; + qglIsEnabled = dllIsEnabled ; + qglIsList = dllIsList ; + qglIsTexture = dllIsTexture ; + qglLightModelf = dllLightModelf ; + qglLightModelfv = dllLightModelfv ; + qglLightModeli = dllLightModeli ; + qglLightModeliv = dllLightModeliv ; + qglLightf = dllLightf ; + qglLightfv = dllLightfv ; + qglLighti = dllLighti ; + qglLightiv = dllLightiv ; + qglLineStipple = dllLineStipple ; + qglLineWidth = dllLineWidth ; + qglListBase = dllListBase ; + qglLoadIdentity = dllLoadIdentity ; + qglLoadMatrixd = dllLoadMatrixd ; + qglLoadMatrixf = dllLoadMatrixf ; + qglLoadName = dllLoadName ; + qglLogicOp = dllLogicOp ; + qglMap1d = dllMap1d ; + qglMap1f = dllMap1f ; + qglMap2d = dllMap2d ; + qglMap2f = dllMap2f ; + qglMapGrid1d = dllMapGrid1d ; + qglMapGrid1f = dllMapGrid1f ; + qglMapGrid2d = dllMapGrid2d ; + qglMapGrid2f = dllMapGrid2f ; + qglMaterialf = dllMaterialf ; + qglMaterialfv = dllMaterialfv ; + qglMateriali = dllMateriali ; + qglMaterialiv = dllMaterialiv ; + qglMatrixMode = dllMatrixMode ; + qglMultMatrixd = dllMultMatrixd ; + qglMultMatrixf = dllMultMatrixf ; + qglNewList = dllNewList ; + qglNormal3b = dllNormal3b ; + qglNormal3bv = dllNormal3bv ; + qglNormal3d = dllNormal3d ; + qglNormal3dv = dllNormal3dv ; + qglNormal3f = dllNormal3f ; + qglNormal3fv = dllNormal3fv ; + qglNormal3i = dllNormal3i ; + qglNormal3iv = dllNormal3iv ; + qglNormal3s = dllNormal3s ; + qglNormal3sv = dllNormal3sv ; + qglNormalPointer = dllNormalPointer ; + qglOrtho = dllOrtho ; + qglPassThrough = dllPassThrough ; + qglPixelMapfv = dllPixelMapfv ; + qglPixelMapuiv = dllPixelMapuiv ; + qglPixelMapusv = dllPixelMapusv ; + qglPixelStoref = dllPixelStoref ; + qglPixelStorei = dllPixelStorei ; + qglPixelTransferf = dllPixelTransferf ; + qglPixelTransferi = dllPixelTransferi ; + qglPixelZoom = dllPixelZoom ; + qglPointSize = dllPointSize ; + qglPolygonMode = dllPolygonMode ; + qglPolygonOffset = dllPolygonOffset ; + qglPolygonStipple = dllPolygonStipple ; + qglPopAttrib = dllPopAttrib ; + qglPopClientAttrib = dllPopClientAttrib ; + qglPopMatrix = dllPopMatrix ; + qglPopName = dllPopName ; + qglPrioritizeTextures = dllPrioritizeTextures ; + qglPushAttrib = dllPushAttrib ; + qglPushClientAttrib = dllPushClientAttrib ; + qglPushMatrix = dllPushMatrix ; + qglPushName = dllPushName ; + qglRasterPos2d = dllRasterPos2d ; + qglRasterPos2dv = dllRasterPos2dv ; + qglRasterPos2f = dllRasterPos2f ; + qglRasterPos2fv = dllRasterPos2fv ; + qglRasterPos2i = dllRasterPos2i ; + qglRasterPos2iv = dllRasterPos2iv ; + qglRasterPos2s = dllRasterPos2s ; + qglRasterPos2sv = dllRasterPos2sv ; + qglRasterPos3d = dllRasterPos3d ; + qglRasterPos3dv = dllRasterPos3dv ; + qglRasterPos3f = dllRasterPos3f ; + qglRasterPos3fv = dllRasterPos3fv ; + qglRasterPos3i = dllRasterPos3i ; + qglRasterPos3iv = dllRasterPos3iv ; + qglRasterPos3s = dllRasterPos3s ; + qglRasterPos3sv = dllRasterPos3sv ; + qglRasterPos4d = dllRasterPos4d ; + qglRasterPos4dv = dllRasterPos4dv ; + qglRasterPos4f = dllRasterPos4f ; + qglRasterPos4fv = dllRasterPos4fv ; + qglRasterPos4i = dllRasterPos4i ; + qglRasterPos4iv = dllRasterPos4iv ; + qglRasterPos4s = dllRasterPos4s ; + qglRasterPos4sv = dllRasterPos4sv ; + qglReadBuffer = dllReadBuffer ; + qglReadPixels = dllReadPixels ; + qglRectd = dllRectd ; + qglRectdv = dllRectdv ; + qglRectf = dllRectf ; + qglRectfv = dllRectfv ; + qglRecti = dllRecti ; + qglRectiv = dllRectiv ; + qglRects = dllRects ; + qglRectsv = dllRectsv ; + qglRenderMode = dllRenderMode ; + qglRotated = dllRotated ; + qglRotatef = dllRotatef ; + qglScaled = dllScaled ; + qglScalef = dllScalef ; + qglScissor = dllScissor ; + qglSelectBuffer = dllSelectBuffer ; + qglShadeModel = dllShadeModel ; + qglStencilFunc = dllStencilFunc ; + qglStencilMask = dllStencilMask ; + qglStencilOp = dllStencilOp ; + qglTexCoord1d = dllTexCoord1d ; + qglTexCoord1dv = dllTexCoord1dv ; + qglTexCoord1f = dllTexCoord1f ; + qglTexCoord1fv = dllTexCoord1fv ; + qglTexCoord1i = dllTexCoord1i ; + qglTexCoord1iv = dllTexCoord1iv ; + qglTexCoord1s = dllTexCoord1s ; + qglTexCoord1sv = dllTexCoord1sv ; + qglTexCoord2d = dllTexCoord2d ; + qglTexCoord2dv = dllTexCoord2dv ; + qglTexCoord2f = dllTexCoord2f ; + qglTexCoord2fv = dllTexCoord2fv ; + qglTexCoord2i = dllTexCoord2i ; + qglTexCoord2iv = dllTexCoord2iv ; + qglTexCoord2s = dllTexCoord2s ; + qglTexCoord2sv = dllTexCoord2sv ; + qglTexCoord3d = dllTexCoord3d ; + qglTexCoord3dv = dllTexCoord3dv ; + qglTexCoord3f = dllTexCoord3f ; + qglTexCoord3fv = dllTexCoord3fv ; + qglTexCoord3i = dllTexCoord3i ; + qglTexCoord3iv = dllTexCoord3iv ; + qglTexCoord3s = dllTexCoord3s ; + qglTexCoord3sv = dllTexCoord3sv ; + qglTexCoord4d = dllTexCoord4d ; + qglTexCoord4dv = dllTexCoord4dv ; + qglTexCoord4f = dllTexCoord4f ; + qglTexCoord4fv = dllTexCoord4fv ; + qglTexCoord4i = dllTexCoord4i ; + qglTexCoord4iv = dllTexCoord4iv ; + qglTexCoord4s = dllTexCoord4s ; + qglTexCoord4sv = dllTexCoord4sv ; + qglTexCoordPointer = dllTexCoordPointer ; + qglTexEnvf = dllTexEnvf ; + qglTexEnvfv = dllTexEnvfv ; + qglTexEnvi = dllTexEnvi ; + qglTexEnviv = dllTexEnviv ; + qglTexGend = dllTexGend ; + qglTexGendv = dllTexGendv ; + qglTexGenf = dllTexGenf ; + qglTexGenfv = dllTexGenfv ; + qglTexGeni = dllTexGeni ; + qglTexGeniv = dllTexGeniv ; + qglTexImage1D = dllTexImage1D ; + qglTexImage2D = dllTexImage2D ; + qglTexParameterf = dllTexParameterf ; + qglTexParameterfv = dllTexParameterfv ; + qglTexParameteri = dllTexParameteri ; + qglTexParameteriv = dllTexParameteriv ; + qglTexSubImage1D = dllTexSubImage1D ; + qglTexSubImage2D = dllTexSubImage2D ; + qglTranslated = dllTranslated ; + qglTranslatef = dllTranslatef ; + qglVertex2d = dllVertex2d ; + qglVertex2dv = dllVertex2dv ; + qglVertex2f = dllVertex2f ; + qglVertex2fv = dllVertex2fv ; + qglVertex2i = dllVertex2i ; + qglVertex2iv = dllVertex2iv ; + qglVertex2s = dllVertex2s ; + qglVertex2sv = dllVertex2sv ; + qglVertex3d = dllVertex3d ; + qglVertex3dv = dllVertex3dv ; + qglVertex3f = dllVertex3f ; + qglVertex3fv = dllVertex3fv ; + qglVertex3i = dllVertex3i ; + qglVertex3iv = dllVertex3iv ; + qglVertex3s = dllVertex3s ; + qglVertex3sv = dllVertex3sv ; + qglVertex4d = dllVertex4d ; + qglVertex4dv = dllVertex4dv ; + qglVertex4f = dllVertex4f ; + qglVertex4fv = dllVertex4fv ; + qglVertex4i = dllVertex4i ; + qglVertex4iv = dllVertex4iv ; + qglVertex4s = dllVertex4s ; + qglVertex4sv = dllVertex4sv ; + qglVertexPointer = dllVertexPointer ; + qglViewport = dllViewport ; + } +} + + +void GLimp_LogNewFrame( void ) +{ + fprintf( glw_state.log_fp, "*** R_BeginFrame ***\n" ); +} + +#pragma warning (default : 4113 4133 4047 ) + + + diff --git a/win32/resource.h b/win32/resource.h new file mode 100644 index 000000000..a3e3858be --- /dev/null +++ b/win32/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by q2.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/win32/rw_ddraw.c b/win32/rw_ddraw.c new file mode 100644 index 000000000..82dee5a71 --- /dev/null +++ b/win32/rw_ddraw.c @@ -0,0 +1,556 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +/* +** RW_DDRAW.C +** +** This handles DirecTDraw management under Windows. +*/ +#ifndef _WIN32 +# error You should not be compiling this file on this platform +#endif + +#include + +#include "..\ref_soft\r_local.h" +#define INITGUID +#include "rw_win.h" + +static const char *DDrawError( int code ); + +/* +** DDRAW_Init +** +** Builds our DDRAW stuff +*/ +qboolean DDRAW_Init( unsigned char **ppbuffer, int *ppitch ) +{ + HRESULT ddrval; + DDSURFACEDESC ddsd; + DDSCAPS ddscaps; + PALETTEENTRY palentries[256]; + int i; + extern cvar_t *sw_allow_modex; + + HRESULT (WINAPI *QDirectDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR * lplpDDRAW, IUnknown FAR * pUnkOuter ); + +ri.Con_Printf( PRINT_ALL, "Initializing DirectDraw\n"); + + + for ( i = 0; i < 256; i++ ) + { + palentries[i].peRed = ( d_8to24table[i] >> 0 ) & 0xff; + palentries[i].peGreen = ( d_8to24table[i] >> 8 ) & 0xff; + palentries[i].peBlue = ( d_8to24table[i] >> 16 ) & 0xff; + } + + /* + ** load DLL and fetch pointer to entry point + */ + if ( !sww_state.hinstDDRAW ) + { + ri.Con_Printf( PRINT_ALL, "...loading DDRAW.DLL: "); + if ( ( sww_state.hinstDDRAW = LoadLibrary( "ddraw.dll" ) ) == NULL ) + { + ri.Con_Printf( PRINT_ALL, "failed\n" ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + } + + if ( ( QDirectDrawCreate = ( HRESULT (WINAPI *)( GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR * ) ) GetProcAddress( sww_state.hinstDDRAW, "DirectDrawCreate" ) ) == NULL ) + { + ri.Con_Printf( PRINT_ALL, "*** DirectDrawCreate == NULL ***\n" ); + goto fail; + } + + /* + ** create the direct draw object + */ + ri.Con_Printf( PRINT_ALL, "...creating DirectDraw object: "); + if ( ( ddrval = QDirectDrawCreate( NULL, &sww_state.lpDirectDraw, NULL ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + /* + ** see if linear modes exist first + */ + sww_state.modex = false; + + ri.Con_Printf( PRINT_ALL, "...setting exclusive mode: "); + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw, + sww_state.hWnd, + DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n",DDrawError (ddrval) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + /* + ** try changing the display mode normally + */ + ri.Con_Printf( PRINT_ALL, "...finding display mode\n" ); + ri.Con_Printf( PRINT_ALL, "...setting linear mode: " ); + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetDisplayMode( sww_state.lpDirectDraw, vid.width, vid.height, 8 ) ) == DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "ok\n" ); + } + /* + ** if no linear mode found, go for modex if we're trying 320x240 + */ + else if ( ( sw_mode->value == 0 ) && sw_allow_modex->value ) + { + ri.Con_Printf( PRINT_ALL, "failed\n" ); + ri.Con_Printf( PRINT_ALL, "...attempting ModeX 320x240: "); + + /* + ** reset to normal cooperative level + */ + sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw, + sww_state.hWnd, + DDSCL_NORMAL ); + + /* + ** set exclusive mode + */ + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw, + sww_state.hWnd, + DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES | DDSCL_ALLOWMODEX ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed SCL - %s\n",DDrawError (ddrval) ); + goto fail; + } + + /* + ** change our display mode + */ + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetDisplayMode( sww_state.lpDirectDraw, vid.width, vid.height, 8 ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed SDM - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + sww_state.modex = true; + } + else + { + ri.Con_Printf( PRINT_ALL, "failed\n" ); + goto fail; + } + + /* + ** create our front buffer + */ + memset( &ddsd, 0, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; + ddsd.dwBackBufferCount = 1; + + ri.Con_Printf( PRINT_ALL, "...creating front buffer: "); + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->CreateSurface( sww_state.lpDirectDraw, &ddsd, &sww_state.lpddsFrontBuffer, NULL ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + /* + ** see if we're a ModeX mode + */ + sww_state.lpddsFrontBuffer->lpVtbl->GetCaps( sww_state.lpddsFrontBuffer, &ddscaps ); + if ( ddscaps.dwCaps & DDSCAPS_MODEX ) + ri.Con_Printf( PRINT_ALL, "...using ModeX\n" ); + + /* + ** create our back buffer + */ + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + + ri.Con_Printf( PRINT_ALL, "...creating back buffer: " ); + if ( ( ddrval = sww_state.lpddsFrontBuffer->lpVtbl->GetAttachedSurface( sww_state.lpddsFrontBuffer, &ddsd.ddsCaps, &sww_state.lpddsBackBuffer ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + /* + ** create our rendering buffer + */ + memset( &ddsd, 0, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + ddsd.dwHeight = vid.height; + ddsd.dwWidth = vid.width; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + + ri.Con_Printf( PRINT_ALL, "...creating offscreen buffer: " ); + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->CreateSurface( sww_state.lpDirectDraw, &ddsd, &sww_state.lpddsOffScreenBuffer, NULL ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + /* + ** create our DIRECTDRAWPALETTE + */ + ri.Con_Printf( PRINT_ALL, "...creating palette: " ); + if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->CreatePalette( sww_state.lpDirectDraw, + DDPCAPS_8BIT | DDPCAPS_ALLOW256, + palentries, + &sww_state.lpddpPalette, + NULL ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + ri.Con_Printf( PRINT_ALL, "...setting palette: " ); + if ( ( ddrval = sww_state.lpddsFrontBuffer->lpVtbl->SetPalette( sww_state.lpddsFrontBuffer, + sww_state.lpddpPalette ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } + ri.Con_Printf( PRINT_ALL, "ok\n" ); + + DDRAW_SetPalette( ( const unsigned char * ) sw_state.currentpalette ); + + /* + ** lock the back buffer + */ + memset( &ddsd, 0, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + +ri.Con_Printf( PRINT_ALL, "...locking backbuffer: " ); + if ( ( ddrval = sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL ) ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) ); + goto fail; + } +ri.Con_Printf( PRINT_ALL, "ok\n" ); + + *ppbuffer = ddsd.lpSurface; + *ppitch = ddsd.lPitch; + + for ( i = 0; i < vid.height; i++ ) + { + memset( *ppbuffer + i * *ppitch, 0, *ppitch ); + } + + sww_state.palettized = true; + + return true; +fail: + ri.Con_Printf( PRINT_ALL, "*** DDraw init failure ***\n" ); + + DDRAW_Shutdown(); + return false; +} + +/* +** DDRAW_SetPalette +** +** Sets the color table in our DIB section, and also sets the system palette +** into an identity mode if we're running in an 8-bit palettized display mode. +** +** The palette is expected to be 1024 bytes, in the format: +** +** R = offset 0 +** G = offset 1 +** B = offset 2 +** A = offset 3 +*/ +void DDRAW_SetPalette( const unsigned char *pal ) +{ + PALETTEENTRY palentries[256]; + int i; + + if (!sww_state.lpddpPalette) + return; + + for ( i = 0; i < 256; i++, pal += 4 ) + { + palentries[i].peRed = pal[0]; + palentries[i].peGreen = pal[1]; + palentries[i].peBlue = pal[2]; + palentries[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE; + } + + if ( sww_state.lpddpPalette->lpVtbl->SetEntries( sww_state.lpddpPalette, + 0, + 0, + 256, + palentries ) != DD_OK ) + { + ri.Con_Printf( PRINT_ALL, "DDRAW_SetPalette() - SetEntries failed\n" ); + } +} + +/* +** DDRAW_Shutdown +*/ +void DDRAW_Shutdown( void ) +{ + if ( sww_state.lpddsOffScreenBuffer ) + { + ri.Con_Printf( PRINT_ALL, "...releasing offscreen buffer\n"); + sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer ); + sww_state.lpddsOffScreenBuffer->lpVtbl->Release( sww_state.lpddsOffScreenBuffer ); + sww_state.lpddsOffScreenBuffer = NULL; + } + + if ( sww_state.lpddsBackBuffer ) + { + ri.Con_Printf( PRINT_ALL, "...releasing back buffer\n"); + sww_state.lpddsBackBuffer->lpVtbl->Release( sww_state.lpddsBackBuffer ); + sww_state.lpddsBackBuffer = NULL; + } + + if ( sww_state.lpddsFrontBuffer ) + { + ri.Con_Printf( PRINT_ALL, "...releasing front buffer\n"); + sww_state.lpddsFrontBuffer->lpVtbl->Release( sww_state.lpddsFrontBuffer ); + sww_state.lpddsFrontBuffer = NULL; + } + + if (sww_state.lpddpPalette) + { + ri.Con_Printf( PRINT_ALL, "...releasing palette\n"); + sww_state.lpddpPalette->lpVtbl->Release ( sww_state.lpddpPalette ); + sww_state.lpddpPalette = NULL; + } + + if ( sww_state.lpDirectDraw ) + { + ri.Con_Printf( PRINT_ALL, "...restoring display mode\n"); + sww_state.lpDirectDraw->lpVtbl->RestoreDisplayMode( sww_state.lpDirectDraw ); + ri.Con_Printf( PRINT_ALL, "...restoring normal coop mode\n"); + sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw, sww_state.hWnd, DDSCL_NORMAL ); + ri.Con_Printf( PRINT_ALL, "...releasing lpDirectDraw\n"); + sww_state.lpDirectDraw->lpVtbl->Release( sww_state.lpDirectDraw ); + sww_state.lpDirectDraw = NULL; + } + + if ( sww_state.hinstDDRAW ) + { + ri.Con_Printf( PRINT_ALL, "...freeing library\n"); + FreeLibrary( sww_state.hinstDDRAW ); + sww_state.hinstDDRAW = NULL; + } +} + +static const char *DDrawError (int code) +{ + switch(code) { + case DD_OK: + return "DD_OK"; + case DDERR_ALREADYINITIALIZED: + return "DDERR_ALREADYINITIALIZED"; + case DDERR_BLTFASTCANTCLIP: + return "DDERR_BLTFASTCANTCLIP"; + case DDERR_CANNOTATTACHSURFACE: + return "DDER_CANNOTATTACHSURFACE"; + case DDERR_CANNOTDETACHSURFACE: + return "DDERR_CANNOTDETACHSURFACE"; + case DDERR_CANTCREATEDC: + return "DDERR_CANTCREATEDC"; + case DDERR_CANTDUPLICATE: + return "DDER_CANTDUPLICATE"; + case DDERR_CLIPPERISUSINGHWND: + return "DDER_CLIPPERUSINGHWND"; + case DDERR_COLORKEYNOTSET: + return "DDERR_COLORKEYNOTSET"; + case DDERR_CURRENTLYNOTAVAIL: + return "DDERR_CURRENTLYNOTAVAIL"; + case DDERR_DIRECTDRAWALREADYCREATED: + return "DDERR_DIRECTDRAWALREADYCREATED"; + case DDERR_EXCEPTION: + return "DDERR_EXCEPTION"; + case DDERR_EXCLUSIVEMODEALREADYSET: + return "DDERR_EXCLUSIVEMODEALREADYSET"; + case DDERR_GENERIC: + return "DDERR_GENERIC"; + case DDERR_HEIGHTALIGN: + return "DDERR_HEIGHTALIGN"; + case DDERR_HWNDALREADYSET: + return "DDERR_HWNDALREADYSET"; + case DDERR_HWNDSUBCLASSED: + return "DDERR_HWNDSUBCLASSED"; + case DDERR_IMPLICITLYCREATED: + return "DDERR_IMPLICITLYCREATED"; + case DDERR_INCOMPATIBLEPRIMARY: + return "DDERR_INCOMPATIBLEPRIMARY"; + case DDERR_INVALIDCAPS: + return "DDERR_INVALIDCAPS"; + case DDERR_INVALIDCLIPLIST: + return "DDERR_INVALIDCLIPLIST"; + case DDERR_INVALIDDIRECTDRAWGUID: + return "DDERR_INVALIDDIRECTDRAWGUID"; + case DDERR_INVALIDMODE: + return "DDERR_INVALIDMODE"; + case DDERR_INVALIDOBJECT: + return "DDERR_INVALIDOBJECT"; + case DDERR_INVALIDPARAMS: + return "DDERR_INVALIDPARAMS"; + case DDERR_INVALIDPIXELFORMAT: + return "DDERR_INVALIDPIXELFORMAT"; + case DDERR_INVALIDPOSITION: + return "DDERR_INVALIDPOSITION"; + case DDERR_INVALIDRECT: + return "DDERR_INVALIDRECT"; + case DDERR_LOCKEDSURFACES: + return "DDERR_LOCKEDSURFACES"; + case DDERR_NO3D: + return "DDERR_NO3D"; + case DDERR_NOALPHAHW: + return "DDERR_NOALPHAHW"; + case DDERR_NOBLTHW: + return "DDERR_NOBLTHW"; + case DDERR_NOCLIPLIST: + return "DDERR_NOCLIPLIST"; + case DDERR_NOCLIPPERATTACHED: + return "DDERR_NOCLIPPERATTACHED"; + case DDERR_NOCOLORCONVHW: + return "DDERR_NOCOLORCONVHW"; + case DDERR_NOCOLORKEY: + return "DDERR_NOCOLORKEY"; + case DDERR_NOCOLORKEYHW: + return "DDERR_NOCOLORKEYHW"; + case DDERR_NOCOOPERATIVELEVELSET: + return "DDERR_NOCOOPERATIVELEVELSET"; + case DDERR_NODC: + return "DDERR_NODC"; + case DDERR_NODDROPSHW: + return "DDERR_NODDROPSHW"; + case DDERR_NODIRECTDRAWHW: + return "DDERR_NODIRECTDRAWHW"; + case DDERR_NOEMULATION: + return "DDERR_NOEMULATION"; + case DDERR_NOEXCLUSIVEMODE: + return "DDERR_NOEXCLUSIVEMODE"; + case DDERR_NOFLIPHW: + return "DDERR_NOFLIPHW"; + case DDERR_NOGDI: + return "DDERR_NOGDI"; + case DDERR_NOHWND: + return "DDERR_NOHWND"; + case DDERR_NOMIRRORHW: + return "DDERR_NOMIRRORHW"; + case DDERR_NOOVERLAYDEST: + return "DDERR_NOOVERLAYDEST"; + case DDERR_NOOVERLAYHW: + return "DDERR_NOOVERLAYHW"; + case DDERR_NOPALETTEATTACHED: + return "DDERR_NOPALETTEATTACHED"; + case DDERR_NOPALETTEHW: + return "DDERR_NOPALETTEHW"; + case DDERR_NORASTEROPHW: + return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0"; + case DDERR_NOROTATIONHW: + return "Operation could not be carried out because there is no rotation hardware present or available.\0"; + case DDERR_NOSTRETCHHW: + return "Operation could not be carried out because there is no hardware support for stretching.\0"; + case DDERR_NOT4BITCOLOR: + return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0"; + case DDERR_NOT4BITCOLORINDEX: + return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0"; + case DDERR_NOT8BITCOLOR: + return "DDERR_NOT8BITCOLOR"; + case DDERR_NOTAOVERLAYSURFACE: + return "Returned when an overlay member is called for a non-overlay surface.\0"; + case DDERR_NOTEXTUREHW: + return "Operation could not be carried out because there is no texture mapping hardware present or available.\0"; + case DDERR_NOTFLIPPABLE: + return "DDERR_NOTFLIPPABLE"; + case DDERR_NOTFOUND: + return "DDERR_NOTFOUND"; + case DDERR_NOTLOCKED: + return "DDERR_NOTLOCKED"; + case DDERR_NOTPALETTIZED: + return "DDERR_NOTPALETTIZED"; + case DDERR_NOVSYNCHW: + return "DDERR_NOVSYNCHW"; + case DDERR_NOZBUFFERHW: + return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0"; + case DDERR_NOZOVERLAYHW: + return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0"; + case DDERR_OUTOFCAPS: + return "The hardware needed for the requested operation has already been allocated.\0"; + case DDERR_OUTOFMEMORY: + return "DDERR_OUTOFMEMORY"; + case DDERR_OUTOFVIDEOMEMORY: + return "DDERR_OUTOFVIDEOMEMORY"; + case DDERR_OVERLAYCANTCLIP: + return "The hardware does not support clipped overlays.\0"; + case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: + return "Can only have ony color key active at one time for overlays.\0"; + case DDERR_OVERLAYNOTVISIBLE: + return "Returned when GetOverlayPosition is called on a hidden overlay.\0"; + case DDERR_PALETTEBUSY: + return "DDERR_PALETTEBUSY"; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + return "DDERR_PRIMARYSURFACEALREADYEXISTS"; + case DDERR_REGIONTOOSMALL: + return "Region passed to Clipper::GetClipList is too small.\0"; + case DDERR_SURFACEALREADYATTACHED: + return "DDERR_SURFACEALREADYATTACHED"; + case DDERR_SURFACEALREADYDEPENDENT: + return "DDERR_SURFACEALREADYDEPENDENT"; + case DDERR_SURFACEBUSY: + return "DDERR_SURFACEBUSY"; + case DDERR_SURFACEISOBSCURED: + return "Access to surface refused because the surface is obscured.\0"; + case DDERR_SURFACELOST: + return "DDERR_SURFACELOST"; + case DDERR_SURFACENOTATTACHED: + return "DDERR_SURFACENOTATTACHED"; + case DDERR_TOOBIGHEIGHT: + return "Height requested by DirectDraw is too large.\0"; + case DDERR_TOOBIGSIZE: + return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0"; + case DDERR_TOOBIGWIDTH: + return "Width requested by DirectDraw is too large.\0"; + case DDERR_UNSUPPORTED: + return "DDERR_UNSUPPORTED"; + case DDERR_UNSUPPORTEDFORMAT: + return "FOURCC format requested is unsupported by DirectDraw.\0"; + case DDERR_UNSUPPORTEDMASK: + return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0"; + case DDERR_VERTICALBLANKINPROGRESS: + return "Vertical blank is in progress.\0"; + case DDERR_WASSTILLDRAWING: + return "DDERR_WASSTILLDRAWING"; + case DDERR_WRONGMODE: + return "This surface can not be restored because it was created in a different mode.\0"; + case DDERR_XALIGN: + return "Rectangle provided was not horizontally aligned on required boundary.\0"; + default: + return "UNKNOWN\0"; + } +} + diff --git a/win32/rw_dib.c b/win32/rw_dib.c new file mode 100644 index 000000000..ae5b1ba87 --- /dev/null +++ b/win32/rw_dib.c @@ -0,0 +1,375 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +/* +** RW_DIB.C +** +** This handles DIB section management under Windows. +** +*/ +#include "..\ref_soft\r_local.h" +#include "rw_win.h" + +#ifndef _WIN32 +# error You should not be trying to compile this file on this platform +#endif + +static qboolean s_systemcolors_saved; + +static HGDIOBJ previously_selected_GDI_obj; + +static int s_syspalindices[] = +{ + COLOR_ACTIVEBORDER, + COLOR_ACTIVECAPTION, + COLOR_APPWORKSPACE, + COLOR_BACKGROUND, + COLOR_BTNFACE, + COLOR_BTNSHADOW, + COLOR_BTNTEXT, + COLOR_CAPTIONTEXT, + COLOR_GRAYTEXT, + COLOR_HIGHLIGHT, + COLOR_HIGHLIGHTTEXT, + COLOR_INACTIVEBORDER, + + COLOR_INACTIVECAPTION, + COLOR_MENU, + COLOR_MENUTEXT, + COLOR_SCROLLBAR, + COLOR_WINDOW, + COLOR_WINDOWFRAME, + COLOR_WINDOWTEXT +}; + +#define NUM_SYS_COLORS ( sizeof( s_syspalindices ) / sizeof( int ) ) + +static int s_oldsyscolors[NUM_SYS_COLORS]; + +typedef struct dibinfo +{ + BITMAPINFOHEADER header; + RGBQUAD acolors[256]; +} dibinfo_t; + +typedef struct +{ + WORD palVersion; + WORD palNumEntries; + PALETTEENTRY palEntries[256]; +} identitypalette_t; + +static identitypalette_t s_ipal; + +static void DIB_SaveSystemColors( void ); +static void DIB_RestoreSystemColors( void ); + +/* +** DIB_Init +** +** Builds our DIB section +*/ +qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch ) +{ + dibinfo_t dibheader; + BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader; + int i; + + memset( &dibheader, 0, sizeof( dibheader ) ); + + /* + ** grab a DC + */ + if ( !sww_state.hDC ) + { + if ( ( sww_state.hDC = GetDC( sww_state.hWnd ) ) == NULL ) + return false; + } + + /* + ** figure out if we're running in an 8-bit display mode + */ + if ( GetDeviceCaps( sww_state.hDC, RASTERCAPS ) & RC_PALETTE ) + { + sww_state.palettized = true; + + // save system colors + if ( !s_systemcolors_saved ) + { + DIB_SaveSystemColors(); + s_systemcolors_saved = true; + } + } + else + { + sww_state.palettized = false; + } + + /* + ** fill in the BITMAPINFO struct + */ + pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmiDIB->bmiHeader.biWidth = vid.width; + pbmiDIB->bmiHeader.biHeight = vid.height; + pbmiDIB->bmiHeader.biPlanes = 1; + pbmiDIB->bmiHeader.biBitCount = 8; + pbmiDIB->bmiHeader.biCompression = BI_RGB; + pbmiDIB->bmiHeader.biSizeImage = 0; + pbmiDIB->bmiHeader.biXPelsPerMeter = 0; + pbmiDIB->bmiHeader.biYPelsPerMeter = 0; + pbmiDIB->bmiHeader.biClrUsed = 256; + pbmiDIB->bmiHeader.biClrImportant = 256; + + /* + ** fill in the palette + */ + for ( i = 0; i < 256; i++ ) + { + dibheader.acolors[i].rgbRed = ( d_8to24table[i] >> 0 ) & 0xff; + dibheader.acolors[i].rgbGreen = ( d_8to24table[i] >> 8 ) & 0xff; + dibheader.acolors[i].rgbBlue = ( d_8to24table[i] >> 16 ) & 0xff; + } + + /* + ** create the DIB section + */ + sww_state.hDIBSection = CreateDIBSection( sww_state.hDC, + pbmiDIB, + DIB_RGB_COLORS, + &sww_state.pDIBBase, + NULL, + 0 ); + + if ( sww_state.hDIBSection == NULL ) + { + ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateDIBSection failed\n" ); + goto fail; + } + + if ( pbmiDIB->bmiHeader.biHeight > 0 ) + { + // bottom up + *ppbuffer = sww_state.pDIBBase + ( vid.height - 1 ) * vid.width; + *ppitch = -vid.width; + } + else + { + // top down + *ppbuffer = sww_state.pDIBBase; + *ppitch = vid.width; + } + + /* + ** clear the DIB memory buffer + */ + memset( sww_state.pDIBBase, 0xff, vid.width * vid.height ); + + if ( ( sww_state.hdcDIBSection = CreateCompatibleDC( sww_state.hDC ) ) == NULL ) + { + ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateCompatibleDC failed\n" ); + goto fail; + } + if ( ( previously_selected_GDI_obj = SelectObject( sww_state.hdcDIBSection, sww_state.hDIBSection ) ) == NULL ) + { + ri.Con_Printf( PRINT_ALL, "DIB_Init() - SelectObject failed\n" ); + goto fail; + } + + return true; + +fail: + DIB_Shutdown(); + return false; + +} + +/* +** DIB_SetPalette +** +** Sets the color table in our DIB section, and also sets the system palette +** into an identity mode if we're running in an 8-bit palettized display mode. +** +** The palette is expected to be 1024 bytes, in the format: +** +** R = offset 0 +** G = offset 1 +** B = offset 2 +** A = offset 3 +*/ +void DIB_SetPalette( const unsigned char *_pal ) +{ + const unsigned char *pal = _pal; + LOGPALETTE *pLogPal = ( LOGPALETTE * ) &s_ipal; + RGBQUAD colors[256]; + int i; + int ret; + HDC hDC = sww_state.hDC; + + /* + ** set the DIB color table + */ + if ( sww_state.hdcDIBSection ) + { + for ( i = 0; i < 256; i++, pal += 4 ) + { + colors[i].rgbRed = pal[0]; + colors[i].rgbGreen = pal[1]; + colors[i].rgbBlue = pal[2]; + colors[i].rgbReserved = 0; + } + + colors[0].rgbRed = 0; + colors[0].rgbGreen = 0; + colors[0].rgbBlue = 0; + + colors[255].rgbRed = 0xff; + colors[255].rgbGreen = 0xff; + colors[255].rgbBlue = 0xff; + + if ( SetDIBColorTable( sww_state.hdcDIBSection, 0, 256, colors ) == 0 ) + { + ri.Con_Printf( PRINT_ALL, "DIB_SetPalette() - SetDIBColorTable failed\n" ); + } + } + + /* + ** for 8-bit color desktop modes we set up the palette for maximum + ** speed by going into an identity palette mode. + */ + if ( sww_state.palettized ) + { + int i; + HPALETTE hpalOld; + + if ( SetSystemPaletteUse( hDC, SYSPAL_NOSTATIC ) == SYSPAL_ERROR ) + { + ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SetSystemPaletteUse() failed\n" ); + } + + /* + ** destroy our old palette + */ + if ( sww_state.hPal ) + { + DeleteObject( sww_state.hPal ); + sww_state.hPal = 0; + } + + /* + ** take up all physical palette entries to flush out anything that's currently + ** in the palette + */ + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = 256; + + for ( i = 0, pal = _pal; i < 256; i++, pal += 4 ) + { + pLogPal->palPalEntry[i].peRed = pal[0]; + pLogPal->palPalEntry[i].peGreen = pal[1]; + pLogPal->palPalEntry[i].peBlue = pal[2]; + pLogPal->palPalEntry[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE; + } + pLogPal->palPalEntry[0].peRed = 0; + pLogPal->palPalEntry[0].peGreen = 0; + pLogPal->palPalEntry[0].peBlue = 0; + pLogPal->palPalEntry[0].peFlags = 0; + pLogPal->palPalEntry[255].peRed = 0xff; + pLogPal->palPalEntry[255].peGreen = 0xff; + pLogPal->palPalEntry[255].peBlue = 0xff; + pLogPal->palPalEntry[255].peFlags = 0; + + if ( ( sww_state.hPal = CreatePalette( pLogPal ) ) == NULL ) + { + ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError() ); + } + + if ( ( hpalOld = SelectPalette( hDC, sww_state.hPal, FALSE ) ) == NULL ) + { + ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SelectPalette failed(%x)\n",GetLastError() ); + } + + if ( sww_state.hpalOld == NULL ) + sww_state.hpalOld = hpalOld; + + if ( ( ret = RealizePalette( hDC ) ) != pLogPal->palNumEntries ) + { + ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - RealizePalette set %d entries\n", ret ); + } + } +} + +/* +** DIB_Shutdown +*/ +void DIB_Shutdown( void ) +{ + if ( sww_state.palettized && s_systemcolors_saved ) + DIB_RestoreSystemColors(); + + if ( sww_state.hPal ) + { + DeleteObject( sww_state.hPal ); + sww_state.hPal = 0; + } + + if ( sww_state.hpalOld ) + { + SelectPalette( sww_state.hDC, sww_state.hpalOld, FALSE ); + RealizePalette( sww_state.hDC ); + sww_state.hpalOld = NULL; + } + + if ( sww_state.hdcDIBSection ) + { + SelectObject( sww_state.hdcDIBSection, previously_selected_GDI_obj ); + DeleteDC( sww_state.hdcDIBSection ); + sww_state.hdcDIBSection = NULL; + } + + if ( sww_state.hDIBSection ) + { + DeleteObject( sww_state.hDIBSection ); + sww_state.hDIBSection = NULL; + sww_state.pDIBBase = NULL; + } + + if ( sww_state.hDC ) + { + ReleaseDC( sww_state.hWnd, sww_state.hDC ); + sww_state.hDC = 0; + } +} + + +/* +** DIB_Save/RestoreSystemColors +*/ +static void DIB_RestoreSystemColors( void ) +{ + SetSystemPaletteUse( sww_state.hDC, SYSPAL_STATIC ); + SetSysColors( NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors ); +} + +static void DIB_SaveSystemColors( void ) +{ + int i; + + for ( i = 0; i < NUM_SYS_COLORS; i++ ) + s_oldsyscolors[i] = GetSysColor( s_syspalindices[i] ); +} diff --git a/win32/rw_imp.c b/win32/rw_imp.c new file mode 100644 index 000000000..fa2d8e79c --- /dev/null +++ b/win32/rw_imp.c @@ -0,0 +1,471 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +/* +** RW_IMP.C +** +** This file contains ALL Win32 specific stuff having to do with the +** software refresh. When a port is being made the following functions +** must be implemented by the port: +** +** SWimp_EndFrame +** SWimp_Init +** SWimp_SetPalette +** SWimp_Shutdown +*/ +#include "..\ref_soft\r_local.h" +#include "rw_win.h" +#include "winquake.h" + +// Console variables that we need to access from this module + +swwstate_t sww_state; + +/* +** VID_CreateWindow +*/ +#define WINDOW_CLASS_NAME "Quake 2" + +void VID_CreateWindow( int width, int height, int stylebits ) +{ + WNDCLASS wc; + RECT r; + cvar_t *vid_xpos, *vid_ypos, *vid_fullscreen; + int x, y, w, h; + int exstyle; + + vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0); + vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0); + vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE ); + + if ( vid_fullscreen->value ) + exstyle = WS_EX_TOPMOST; + else + exstyle = 0; + + /* Register the frame class */ + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)sww_state.wndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = sww_state.hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = (void *)COLOR_GRAYTEXT; + wc.lpszMenuName = 0; + wc.lpszClassName = WINDOW_CLASS_NAME; + + if (!RegisterClass (&wc) ) + ri.Sys_Error (ERR_FATAL, "Couldn't register window class"); + + r.left = 0; + r.top = 0; + r.right = width; + r.bottom = height; + + AdjustWindowRect (&r, stylebits, FALSE); + + w = r.right - r.left; + h = r.bottom - r.top; + x = vid_xpos->value; + y = vid_ypos->value; + + sww_state.hWnd = CreateWindowEx ( + exstyle, + WINDOW_CLASS_NAME, + "Quake 2", + stylebits, + x, y, w, h, + NULL, + NULL, + sww_state.hInstance, + NULL); + + if (!sww_state.hWnd) + ri.Sys_Error (ERR_FATAL, "Couldn't create window"); + + ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); + UpdateWindow( sww_state.hWnd ); + SetForegroundWindow( sww_state.hWnd ); + SetFocus( sww_state.hWnd ); + + // let the sound and input subsystems know about the new window + ri.Vid_NewWindow (width, height); +} + +/* +** SWimp_Init +** +** This routine is responsible for initializing the implementation +** specific stuff in a software rendering subsystem. +*/ +int SWimp_Init( void *hInstance, void *wndProc ) +{ + sww_state.hInstance = ( HINSTANCE ) hInstance; + sww_state.wndproc = wndProc; + + return true; +} + +/* +** SWimp_InitGraphics +** +** This initializes the software refresh's implementation specific +** graphics subsystem. In the case of Windows it creates DIB or +** DDRAW surfaces. +** +** The necessary width and height parameters are grabbed from +** vid.width and vid.height. +*/ +static qboolean SWimp_InitGraphics( qboolean fullscreen ) +{ + // free resources in use + SWimp_Shutdown (); + + // create a new window + VID_CreateWindow (vid.width, vid.height, WINDOW_STYLE); + + // initialize the appropriate subsystem + if ( !fullscreen ) + { + if ( !DIB_Init( &vid.buffer, &vid.rowbytes ) ) + { + vid.buffer = 0; + vid.rowbytes = 0; + + return false; + } + } + else + { + if ( !DDRAW_Init( &vid.buffer, &vid.rowbytes ) ) + { + vid.buffer = 0; + vid.rowbytes = 0; + + return false; + } + } + + return true; +} + +/* +** SWimp_EndFrame +** +** This does an implementation specific copy from the backbuffer to the +** front buffer. In the Win32 case it uses BitBlt or BltFast depending +** on whether we're using DIB sections/GDI or DDRAW. +*/ +void SWimp_EndFrame (void) +{ + if ( !sw_state.fullscreen ) + { + if ( sww_state.palettized ) + { +// holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE); +// RealizePalette(hdcScreen); + } + + + BitBlt( sww_state.hDC, + 0, 0, + vid.width, + vid.height, + sww_state.hdcDIBSection, + 0, 0, + SRCCOPY ); + + if ( sww_state.palettized ) + { +// SelectPalette(hdcScreen, holdpal, FALSE); + } + } + else + { + RECT r; + HRESULT rval; + DDSURFACEDESC ddsd; + + r.left = 0; + r.top = 0; + r.right = vid.width; + r.bottom = vid.height; + + sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer ); + + if ( sww_state.modex ) + { + if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer, + 0, 0, + sww_state.lpddsOffScreenBuffer, + &r, + DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST ) + { + sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsBackBuffer ); + sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer, + 0, 0, + sww_state.lpddsOffScreenBuffer, + &r, + DDBLTFAST_WAIT ); + } + + if ( ( rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, + NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST ) + { + sww_state.lpddsFrontBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer ); + sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT ); + } + } + else + { + if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer, + 0, 0, + sww_state.lpddsOffScreenBuffer, + &r, + DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST ) + { + sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer ); + sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer, + 0, 0, + sww_state.lpddsOffScreenBuffer, + &r, + DDBLTFAST_WAIT ); + } + } + + memset( &ddsd, 0, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + + sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL ); + + vid.buffer = ddsd.lpSurface; + vid.rowbytes = ddsd.lPitch; + } +} + +/* +** SWimp_SetMode +*/ +rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) +{ + const char *win_fs[] = { "W", "FS" }; + rserr_t retval = rserr_ok; + + ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode ); + + if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) ) + { + ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); + return rserr_invalid_mode; + } + + ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] ); + + sww_state.initializing = true; + if ( fullscreen ) + { + if ( !SWimp_InitGraphics( 1 ) ) + { + if ( SWimp_InitGraphics( 0 ) ) + { + // mode is legal but not as fullscreen + fullscreen = 0; + retval = rserr_invalid_fullscreen; + } + else + { + // failed to set a valid mode in windowed mode + retval = rserr_unknown; + } + } + } + else + { + // failure to set a valid mode in windowed mode + if ( !SWimp_InitGraphics( fullscreen ) ) + { + sww_state.initializing = true; + return rserr_unknown; + } + } + + sw_state.fullscreen = fullscreen; +#if 0 + if ( retval != rserr_unknown ) + { + if ( retval == rserr_invalid_fullscreen || + ( retval == rserr_ok && !fullscreen ) ) + { + SetWindowLong( sww_state.hWnd, GWL_STYLE, WINDOW_STYLE ); + } + } +#endif + R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table ); + sww_state.initializing = true; + + return retval; +} + +/* +** SWimp_SetPalette +** +** System specific palette setting routine. A NULL palette means +** to use the existing palette. The palette is expected to be in +** a padded 4-byte xRGB format. +*/ +void SWimp_SetPalette( const unsigned char *palette ) +{ + // MGL - what the fuck was kendall doing here?! + // clear screen to black and change palette + // for (i=0 ; ivalue ) + ShowWindow( sww_state.hWnd, SW_MINIMIZE ); + } + } +} + +//=============================================================================== + + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + DWORD flOldProtect; + + if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect)) + ri.Sys_Error(ERR_FATAL, "Protection change failed\n"); +} + +/* +** Sys_SetFPCW +** +** For reference: +** +** 1 +** 5 0 +** xxxxRRPP.xxxxxxxx +** +** PP = 00 = 24-bit single precision +** PP = 01 = reserved +** PP = 10 = 53-bit double precision +** PP = 11 = 64-bit extended precision +** +** RR = 00 = round to nearest +** RR = 01 = round down (towards -inf, floor) +** RR = 10 = round up (towards +inf, ceil) +** RR = 11 = round to zero (truncate/towards 0) +** +*/ +#if !id386 +void Sys_SetFPCW (void) +{ +} +#else +unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw; +unsigned fpu_sp24_cw, fpu_sp24_ceil_cw; + +void Sys_SetFPCW( void ) +{ + __asm xor eax, eax + + __asm fnstcw word ptr fpu_cw + __asm mov ax, word ptr fpu_cw + + __asm and ah, 0f0h + __asm or ah, 003h ; round to nearest mode, extended precision + __asm mov fpu_full_cw, eax + + __asm and ah, 0f0h + __asm or ah, 00fh ; RTZ/truncate/chop mode, extended precision + __asm mov fpu_chop_cw, eax + + __asm and ah, 0f0h + __asm or ah, 00bh ; ceil mode, extended precision + __asm mov fpu_ceil_cw, eax + + __asm and ah, 0f0h ; round to nearest, 24-bit single precision + __asm mov fpu_sp24_cw, eax + + __asm and ah, 0f0h ; ceil mode, 24-bit single precision + __asm or ah, 008h ; + __asm mov fpu_sp24_ceil_cw, eax +} +#endif + diff --git a/win32/rw_win.h b/win32/rw_win.h new file mode 100644 index 000000000..ecf6488c3 --- /dev/null +++ b/win32/rw_win.h @@ -0,0 +1,68 @@ +/* +Copyright (C) 1997-2001 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 __RW_WIN_H__ +#define __RW_WIN_H__ + +#include +#include + +typedef struct +{ + HINSTANCE hInstance; + void *wndproc; + HDC hDC; // global DC we're using + HWND hWnd; // HWND of parent window + + HDC hdcDIBSection; // DC compatible with DIB section + HBITMAP hDIBSection; // DIB section + unsigned char *pDIBBase; // DIB base pointer, NOT used directly for rendering! + + HPALETTE hPal; // palette we're using + HPALETTE hpalOld; // original system palette + COLORREF oldsyscolors[20]; // original system colors + + HINSTANCE hinstDDRAW; // library instance for DDRAW.DLL + LPDIRECTDRAW lpDirectDraw; // pointer to DirectDraw object + + LPDIRECTDRAWSURFACE lpddsFrontBuffer; // video card display memory front buffer + LPDIRECTDRAWSURFACE lpddsBackBuffer; // system memory backbuffer + LPDIRECTDRAWSURFACE lpddsOffScreenBuffer; // system memory backbuffer + LPDIRECTDRAWPALETTE lpddpPalette; // DirectDraw palette + + qboolean palettized; // true if desktop is paletted + qboolean modex; + + qboolean initializing; +} swwstate_t; + +extern swwstate_t sww_state; + +/* +** DIB code +*/ +qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch ); +void DIB_Shutdown( void ); +void DIB_SetPalette( const unsigned char *palette ); + +qboolean DDRAW_Init( unsigned char **ppbuffer, int *ppitch ); +void DDRAW_Shutdown( void ); +void DDRAW_SetPalette( const unsigned char *palette ); + +#endif diff --git a/win32/snd_win.c b/win32/snd_win.c new file mode 100644 index 000000000..edd0bcb24 --- /dev/null +++ b/win32/snd_win.c @@ -0,0 +1,861 @@ +/* +Copyright (C) 1997-2001 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 + +#include "../client/client.h" +#include "../client/snd_loc.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; + +cvar_t *s_wavonly; + +static qboolean dsound_init; +static qboolean wav_init; +static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; +static qboolean primary_format_set; + +// starts at 0 for disabled +static int snd_buffer_count = 0; +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); + +void FreeSound( void ); + +static const char *DSoundError( int error ) +{ + switch ( error ) + { + case DSERR_BUFFERLOST: + return "DSERR_BUFFERLOST"; + case DSERR_INVALIDCALL: + return "DSERR_INVALIDCALLS"; + case DSERR_INVALIDPARAM: + return "DSERR_INVALIDPARAM"; + case DSERR_PRIOLEVELNEEDED: + return "DSERR_PRIOLEVELNEEDED"; + } + + return "unknown"; +} + +/* +** DS_CreateBuffers +*/ +static qboolean DS_CreateBuffers( void ) +{ + DSBUFFERDESC dsbuf; + DSBCAPS dsbcaps; + WAVEFORMATEX pformat, format; + DWORD dwWrite; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = dma.channels; + format.wBitsPerSample = dma.samplebits; + format.nSamplesPerSec = dma.speed; + format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; + format.cbSize = 0; + format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; + + Com_Printf( "Creating DS buffers\n" ); + + Com_DPrintf("...setting EXCLUSIVE coop level: " ); + if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_EXCLUSIVE ) ) + { + Com_Printf ("failed\n"); + FreeSound (); + return false; + } + Com_DPrintf("ok\n" ); + +// 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; + + Com_DPrintf( "...creating primary buffer: " ); + if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) + { + pformat = format; + + Com_DPrintf( "ok\n" ); + if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) + { + if (snd_firsttime) + Com_DPrintf ("...setting primary sound format: failed\n"); + } + else + { + if (snd_firsttime) + Com_DPrintf ("...setting primary sound format: ok\n"); + + primary_format_set = true; + } + } + else + Com_Printf( "failed\n" ); + + if ( !primary_format_set || !s_primary->value) + { + // 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); + + Com_DPrintf( "...creating secondary buffer: " ); + if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) + { + Com_Printf( "failed\n" ); + FreeSound (); + return false; + } + Com_DPrintf( "ok\n" ); + + dma.channels = format.nChannels; + dma.samplebits = format.wBitsPerSample; + dma.speed = format.nSamplesPerSec; + + if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) + { + Com_Printf ("*** GetCaps failed ***\n"); + FreeSound (); + return false; + } + + Com_Printf ("...using secondary sound buffer\n"); + } + else + { + Com_Printf( "...using primary buffer\n" ); + + Com_DPrintf( "...setting WRITEPRIMARY coop level: " ); + if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, cl_hwnd, DSSCL_WRITEPRIMARY)) + { + Com_Printf( "failed\n" ); + FreeSound (); + return false; + } + Com_DPrintf( "ok\n" ); + + if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) + { + Com_Printf ("*** GetCaps failed ***\n"); + return false; + } + + pDSBuf = pDSPBuf; + } + + // Make sure mixer is active + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + + if (snd_firsttime) + Com_Printf(" %d channel(s)\n" + " %d bits/sample\n" + " %d bytes/sec\n", + dma.channels, dma.samplebits, dma.speed); + + gSndBufSize = dsbcaps.dwBufferBytes; + + /* 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); + + dma.samples = gSndBufSize/(dma.samplebits/8); + dma.samplepos = 0; + dma.submission_chunk = 1; + dma.buffer = (unsigned char *) lpData; + sample16 = (dma.samplebits/8) - 1; + + return true; +} + +/* +** DS_DestroyBuffers +*/ +static void DS_DestroyBuffers( void ) +{ + Com_DPrintf( "Destroying DS buffers\n" ); + if ( pDS ) + { + Com_DPrintf( "...setting NORMAL coop level\n" ); + pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_NORMAL ); + } + + if ( pDSBuf ) + { + Com_DPrintf( "...stopping and releasing sound buffer\n" ); + 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 ) ) + { + Com_DPrintf( "...releasing primary buffer\n" ); + pDSPBuf->lpVtbl->Release( pDSPBuf ); + } + pDSBuf = NULL; + pDSPBuf = NULL; + + dma.buffer = NULL; +} + +/* +================== +FreeSound +================== +*/ +void FreeSound (void) +{ + int i; + + Com_DPrintf( "Shutting down sound system\n" ); + + if ( pDS ) + DS_DestroyBuffers(); + + if ( hWaveOut ) + { + Com_DPrintf( "...resetting waveOut\n" ); + waveOutReset (hWaveOut); + + if (lpWaveHdr) + { + Com_DPrintf( "...unpreparing headers\n" ); + for (i=0 ; i< WAV_BUFFERS ; i++) + waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); + } + + Com_DPrintf( "...closing waveOut\n" ); + waveOutClose (hWaveOut); + + if (hWaveHdr) + { + Com_DPrintf( "...freeing WAV header\n" ); + GlobalUnlock(hWaveHdr); + GlobalFree(hWaveHdr); + } + + if (hData) + { + Com_DPrintf( "...freeing WAV buffer\n" ); + GlobalUnlock(hData); + GlobalFree(hData); + } + + } + + if ( pDS ) + { + Com_DPrintf( "...releasing DS object\n" ); + pDS->lpVtbl->Release( pDS ); + } + + if ( hInstDS ) + { + Com_DPrintf( "...freeing DSOUND.DLL\n" ); + FreeLibrary( hInstDS ); + hInstDS = NULL; + } + + 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) +{ + DSCAPS dscaps; + HRESULT hresult; + + dma.channels = 2; + dma.samplebits = 16; + + if (s_khz->value == 44) + dma.speed = 44100; + if (s_khz->value == 22) + dma.speed = 22050; + else + dma.speed = 11025; + + Com_Printf( "Initializing DirectSound\n"); + + if ( !hInstDS ) + { + Com_DPrintf( "...loading dsound.dll: " ); + + hInstDS = LoadLibrary("dsound.dll"); + + if (hInstDS == NULL) + { + Com_Printf ("failed\n"); + return SIS_FAILURE; + } + + Com_DPrintf ("ok\n"); + pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); + + if (!pDirectSoundCreate) + { + Com_Printf ("*** couldn't get DS proc addr ***\n"); + return SIS_FAILURE; + } + } + + Com_DPrintf( "...creating DS object: " ); + while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK ) + { + if (hresult != DSERR_ALLOCATED) + { + Com_Printf( "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) + { + Com_Printf ("failed, hardware already in use\n" ); + return SIS_NOTAVAIL; + } + } + Com_DPrintf( "ok\n" ); + + dscaps.dwSize = sizeof(dscaps); + + if ( DS_OK != pDS->lpVtbl->GetCaps( pDS, &dscaps ) ) + { + Com_Printf ("*** couldn't get DS caps ***\n"); + } + + if ( dscaps.dwFlags & DSCAPS_EMULDRIVER ) + { + Com_DPrintf ("...no DSound driver found\n" ); + FreeSound(); + return SIS_FAILURE; + } + + if ( !DS_CreateBuffers() ) + return SIS_FAILURE; + + dsound_init = true; + + Com_DPrintf("...completed successfully\n" ); + + return SIS_SUCCESS; +} + + +/* +================== +SNDDM_InitWav + +Crappy windows multimedia base +================== +*/ +qboolean SNDDMA_InitWav (void) +{ + WAVEFORMATEX format; + int i; + HRESULT hr; + + Com_Printf( "Initializing wave sound\n" ); + + snd_sent = 0; + snd_completed = 0; + + dma.channels = 2; + dma.samplebits = 16; + + if (s_khz->value == 44) + dma.speed = 44100; + if (s_khz->value == 22) + dma.speed = 22050; + else + dma.speed = 11025; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = dma.channels; + format.wBitsPerSample = dma.samplebits; + format.nSamplesPerSec = dma.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. */ + Com_DPrintf ("...opening waveform device: "); + while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, + &format, + 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) + { + if (hr != MMSYSERR_ALLOCATED) + { + Com_Printf ("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 2 with no sound.", + "Sound not available", + MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) + { + Com_Printf ("hw in use\n" ); + return false; + } + } + Com_DPrintf( "ok\n" ); + + /* + * Allocate and lock memory for the waveform data. The memory + * for waveform data must be globally allocated with + * GMEM_MOVEABLE and GMEM_SHARE flags. + + */ + Com_DPrintf ("...allocating waveform buffer: "); + gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; + hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); + if (!hData) + { + Com_Printf( " failed\n" ); + FreeSound (); + return false; + } + Com_DPrintf( "ok\n" ); + + Com_DPrintf ("...locking waveform buffer: "); + lpData = GlobalLock(hData); + if (!lpData) + { + Com_Printf( " failed\n" ); + FreeSound (); + return false; + } + memset (lpData, 0, gSndBufSize); + Com_DPrintf( "ok\n" ); + + /* + * Allocate and lock memory for the header. This memory must + * also be globally allocated with GMEM_MOVEABLE and + * GMEM_SHARE flags. + */ + Com_DPrintf ("...allocating waveform header: "); + hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); + + if (hWaveHdr == NULL) + { + Com_Printf( "failed\n" ); + FreeSound (); + return false; + } + Com_DPrintf( "ok\n" ); + + Com_DPrintf ("...locking waveform header: "); + lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); + + if (lpWaveHdr == NULL) + { + Com_Printf( "failed\n" ); + FreeSound (); + return false; + } + memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); + Com_DPrintf( "ok\n" ); + + /* After allocation, set up and prepare headers. */ + Com_DPrintf ("...preparing headers: "); + for (i=0 ; ivalue) + { + if (snd_firsttime || snd_isdirect) + { + stat = SNDDMA_InitDirect (); + + if (stat == SIS_SUCCESS) + { + snd_isdirect = true; + + if (snd_firsttime) + Com_Printf ("dsound init succeeded\n" ); + } + else + { + snd_isdirect = false; + Com_Printf ("*** dsound init failed ***\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) + Com_Printf ("Wave sound init succeeded\n"); + } + else + { + Com_Printf ("Wave sound init failed\n"); + } + } + } + + snd_firsttime = false; + + snd_buffer_count = 1; + + if (!dsound_init && !wav_init) + { + if (snd_firsttime) + Com_Printf ("*** 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 &= (dma.samples-1); + + return s; +} + +/* +============== +SNDDMA_BeginPainting + +Makes sure dma.buffer is valid +=============== +*/ +DWORD locksize; +void SNDDMA_BeginPainting (void) +{ + int reps; + DWORD dwSize2; + DWORD *pbuf, *pbuf2; + HRESULT hresult; + DWORD dwStatus; + + if (!pDSBuf) + return; + + // if the buffer was lost or stopped, restore it and/or restart it + if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK) + Com_Printf ("Couldn't get sound buffer status\n"); + + if (dwStatus & DSBSTATUS_BUFFERLOST) + pDSBuf->lpVtbl->Restore (pDSBuf); + + if (!(dwStatus & DSBSTATUS_PLAYING)) + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + + // lock the dsound buffer + + reps = 0; + dma.buffer = NULL; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &locksize, + &pbuf2, &dwSize2, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Com_Printf( "S_TransferStereo16: Lock failed with error '%s'\n", DSoundError( hresult ) ); + S_Shutdown (); + return; + } + else + { + pDSBuf->lpVtbl->Restore( pDSBuf ); + } + + if (++reps > 2) + return; + } + dma.buffer = (unsigned char *)pbuf; +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +Also unlocks the dsound buffer +=============== +*/ +void SNDDMA_Submit(void) +{ + LPWAVEHDR h; + int wResult; + + if (!dma.buffer) + return; + + // unlock the dsound buffer + if (pDSBuf) + pDSBuf->lpVtbl->Unlock(pDSBuf, dma.buffer, locksize, NULL, 0); + + if (!wav_init) + return; + + // + // find which sound blocks have completed + // + while (1) + { + if ( snd_completed == snd_sent ) + { + Com_DPrintf ("Sound overrun\n"); + break; + } + + if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) + { + break; + } + + snd_completed++; // this buffer has been played + } + +//Com_Printf ("completed %i\n", snd_completed); + // + // submit a few new sound blocks + // + while (((snd_sent - snd_completed) >> sample16) < 8) + { + h = lpWaveHdr + ( snd_sent&WAV_MASK ); + if (paintedtime/256 <= snd_sent) + break; // Com_Printf ("submit overrun\n"); +//Com_Printf ("send %i\n", snd_sent); + 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) + { + Com_Printf ("Failed to write block to device\n"); + FreeSound (); + return; + } + } +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown(void) +{ + FreeSound (); +} + + +/* +=========== +S_Activate + +Called when the main window gains or loses focus. +The window have been destroyed and recreated +between a deactivate and an activate. +=========== +*/ +void S_Activate (qboolean active) +{ + if ( active ) + { + if ( pDS && cl_hwnd && snd_isdirect ) + { + DS_CreateBuffers(); + } + } + else + { + if ( pDS && cl_hwnd && snd_isdirect ) + { + DS_DestroyBuffers(); + } + } +} + diff --git a/win32/sys_win.c b/win32/sys_win.c new file mode 100644 index 000000000..f97c5dd93 --- /dev/null +++ b/win32/sys_win.c @@ -0,0 +1,663 @@ +/* +Copyright (C) 1997-2001 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.h + +#include "../qcommon/qcommon.h" +#include "winquake.h" +#include "resource.h" +#include +#include +#include +#include +#include +#include +#include +#include "../win32/conproc.h" + +#define MINIMUM_WIN_MEMORY 0x0a00000 +#define MAXIMUM_WIN_MEMORY 0x1000000 + +//#define DEMO + +qboolean s_win95; + +int starttime; +int ActiveApp; +qboolean Minimized; + +static HANDLE hinput, houtput; + +unsigned sys_msg_time; +unsigned sys_frame_time; + + +static HANDLE qwclsemaphore; + +#define MAX_NUM_ARGVS 128 +int argc; +char *argv[MAX_NUM_ARGVS]; + + +/* +=============================================================================== + +SYSTEM IO + +=============================================================================== +*/ + + +void Sys_Error (char *error, ...) +{ + va_list argptr; + char text[1024]; + + CL_Shutdown (); + Qcommon_Shutdown (); + + va_start (argptr, error); + vsprintf (text, error, argptr); + va_end (argptr); + + MessageBox(NULL, text, "Error", 0 /* MB_OK */ ); + + if (qwclsemaphore) + CloseHandle (qwclsemaphore); + +// shut down QHOST hooks if necessary + DeinitConProc (); + + exit (1); +} + +void Sys_Quit (void) +{ + timeEndPeriod( 1 ); + + CL_Shutdown(); + Qcommon_Shutdown (); + CloseHandle (qwclsemaphore); + if (dedicated && dedicated->value) + FreeConsole (); + +// shut down QHOST hooks if necessary + DeinitConProc (); + + exit (0); +} + + +void WinError (void) +{ + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string. + MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION ); + + // Free the buffer. + LocalFree( lpMsgBuf ); +} + +//================================================================ + + +/* +================ +Sys_ScanForCD + +================ +*/ +char *Sys_ScanForCD (void) +{ + static char cddir[MAX_OSPATH]; + static qboolean done; +#ifndef DEMO + char drive[4]; + FILE *f; + char test[MAX_QPATH]; + + if (done) // don't re-check + return cddir; + + // no abort/retry/fail errors + SetErrorMode (SEM_FAILCRITICALERRORS); + + drive[0] = 'c'; + drive[1] = ':'; + drive[2] = '\\'; + drive[3] = 0; + + done = true; + + // scan the drives + for (drive[0] = 'c' ; drive[0] <= 'z' ; drive[0]++) + { + // where activision put the stuff... + sprintf (cddir, "%sinstall\\data", drive); + sprintf (test, "%sinstall\\data\\quake2.exe", drive); + f = fopen(test, "r"); + if (f) + { + fclose (f); + if (GetDriveType (drive) == DRIVE_CDROM) + return cddir; + } + } +#endif + + cddir[0] = 0; + + return NULL; +} + +/* +================ +Sys_CopyProtect + +================ +*/ +void Sys_CopyProtect (void) +{ +#ifndef DEMO + char *cddir; + + cddir = Sys_ScanForCD(); + if (!cddir[0]) + Com_Error (ERR_FATAL, "You must have the Quake2 CD in the drive to play."); +#endif +} + + +//================================================================ + + +/* +================ +Sys_Init +================ +*/ +void Sys_Init (void) +{ + OSVERSIONINFO vinfo; + +#if 0 + // allocate a named semaphore on the client so the + // front end can tell if it is alive + + // mutex will fail if semephore already exists + qwclsemaphore = CreateMutex( + NULL, /* Security attributes */ + 0, /* owner */ + "qwcl"); /* Semaphore name */ + if (!qwclsemaphore) + Sys_Error ("QWCL is already running on this system"); + CloseHandle (qwclsemaphore); + + qwclsemaphore = CreateSemaphore( + NULL, /* Security attributes */ + 0, /* Initial count */ + 1, /* Maximum count */ + "qwcl"); /* Semaphore name */ +#endif + + timeBeginPeriod( 1 ); + + vinfo.dwOSVersionInfoSize = sizeof(vinfo); + + if (!GetVersionEx (&vinfo)) + Sys_Error ("Couldn't get OS info"); + + if (vinfo.dwMajorVersion < 4) + Sys_Error ("Quake2 requires windows version 4 or greater"); + if (vinfo.dwPlatformId == VER_PLATFORM_WIN32s) + Sys_Error ("Quake2 doesn't run on Win32s"); + else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) + s_win95 = true; + + if (dedicated->value) + { + if (!AllocConsole ()) + Sys_Error ("Couldn't create dedicated server console"); + hinput = GetStdHandle (STD_INPUT_HANDLE); + houtput = GetStdHandle (STD_OUTPUT_HANDLE); + + // let QHOST hook in + InitConProc (argc, argv); + } +} + + +static char console_text[256]; +static int console_textlen; + +/* +================ +Sys_ConsoleInput +================ +*/ +char *Sys_ConsoleInput (void) +{ + INPUT_RECORD recs[1024]; + int dummy; + int ch, numread, numevents; + + if (!dedicated || !dedicated->value) + 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 (console_textlen) + { + console_text[console_textlen] = 0; + console_textlen = 0; + return console_text; + } + break; + + case '\b': + if (console_textlen) + { + console_textlen--; + WriteFile(houtput, "\b \b", 3, &dummy, NULL); + } + break; + + default: + if (ch >= ' ') + { + if (console_textlen < sizeof(console_text)-2) + { + WriteFile(houtput, &ch, 1, &dummy, NULL); + console_text[console_textlen] = ch; + console_textlen++; + } + } + + break; + + } + } + } + } + + return NULL; +} + + +/* +================ +Sys_ConsoleOutput + +Print text to the dedicated console +================ +*/ +void Sys_ConsoleOutput (char *string) +{ + int dummy; + char text[256]; + + if (!dedicated || !dedicated->value) + return; + + if (console_textlen) + { + text[0] = '\r'; + memset(&text[1], ' ', console_textlen); + text[console_textlen+1] = '\r'; + text[console_textlen+2] = 0; + WriteFile(houtput, text, console_textlen+2, &dummy, NULL); + } + + WriteFile(houtput, string, strlen(string), &dummy, NULL); + + if (console_textlen) + WriteFile(houtput, console_text, console_textlen, &dummy, NULL); +} + + +/* +================ +Sys_SendKeyEvents + +Send Key_Event calls +================ +*/ +void Sys_SendKeyEvents (void) +{ + MSG msg; + + while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (!GetMessage (&msg, NULL, 0, 0)) + Sys_Quit (); + sys_msg_time = msg.time; + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + // grab frame time + sys_frame_time = timeGetTime(); // FIXME: should this be at start? +} + + + +/* +================ +Sys_GetClipboardData + +================ +*/ +char *Sys_GetClipboardData( void ) +{ + char *data = NULL; + char *cliptext; + + if ( OpenClipboard( NULL ) != 0 ) + { + HANDLE hClipboardData; + + if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 ) + { + if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 ) + { + data = malloc( GlobalSize( hClipboardData ) + 1 ); + strcpy( data, cliptext ); + GlobalUnlock( hClipboardData ); + } + } + CloseClipboard(); + } + return data; +} + +/* +============================================================================== + + WINDOWS CRAP + +============================================================================== +*/ + +/* +================= +Sys_AppActivate +================= +*/ +void Sys_AppActivate (void) +{ + ShowWindow ( cl_hwnd, SW_RESTORE); + SetForegroundWindow ( cl_hwnd ); +} + +/* +======================================================================== + +GAME DLL + +======================================================================== +*/ + +static HINSTANCE game_library; + +/* +================= +Sys_UnloadGame +================= +*/ +void Sys_UnloadGame (void) +{ + if (!FreeLibrary (game_library)) + Com_Error (ERR_FATAL, "FreeLibrary failed for game library"); + game_library = NULL; +} + +/* +================= +Sys_GetGameAPI + +Loads the game dll +================= +*/ +void *Sys_GetGameAPI (void *parms) +{ + void *(*GetGameAPI) (void *); + char name[MAX_OSPATH]; + char *path; + char cwd[MAX_OSPATH]; +#if defined _M_IX86 + const char *gamename = "gamex86.dll"; + +#ifdef NDEBUG + const char *debugdir = "release"; +#else + const char *debugdir = "debug"; +#endif + +#elif defined _M_ALPHA + const char *gamename = "gameaxp.dll"; + +#ifdef NDEBUG + const char *debugdir = "releaseaxp"; +#else + const char *debugdir = "debugaxp"; +#endif + +#endif + + if (game_library) + Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame"); + + // check the current debug directory first for development purposes + _getcwd (cwd, sizeof(cwd)); + Com_sprintf (name, sizeof(name), "%s/%s/%s", cwd, debugdir, gamename); + game_library = LoadLibrary ( name ); + if (game_library) + { + Com_DPrintf ("LoadLibrary (%s)\n", name); + } + else + { + // check the current directory for other development purposes + Com_sprintf (name, sizeof(name), "%s/%s", cwd, gamename); + game_library = LoadLibrary ( name ); + if (game_library) + { + Com_DPrintf ("LoadLibrary (%s)\n", name); + } + else + { + // now run through the search paths + path = NULL; + while (1) + { + path = FS_NextPath (path); + if (!path) + return NULL; // couldn't find one anywhere + Com_sprintf (name, sizeof(name), "%s/%s", path, gamename); + game_library = LoadLibrary (name); + if (game_library) + { + Com_DPrintf ("LoadLibrary (%s)\n",name); + break; + } + } + } + } + + GetGameAPI = (void *)GetProcAddress (game_library, "GetGameAPI"); + if (!GetGameAPI) + { + Sys_UnloadGame (); + return NULL; + } + + return GetGameAPI (parms); +} + +//======================================================================= + + +/* +================== +ParseCommandLine + +================== +*/ +void ParseCommandLine (LPSTR lpCmdLine) +{ + argc = 1; + argv[0] = "exe"; + + while (*lpCmdLine && (argc < MAX_NUM_ARGVS)) + { + while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + argv[argc] = lpCmdLine; + argc++; + + while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + *lpCmdLine = 0; + lpCmdLine++; + } + + } + } + +} + +/* +================== +WinMain + +================== +*/ +HINSTANCE global_hInstance; + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + int time, oldtime, newtime; + char *cddir; + + /* previous instances do not exist in Win32 */ + if (hPrevInstance) + return 0; + + global_hInstance = hInstance; + + ParseCommandLine (lpCmdLine); + + // if we find the CD, add a +set cddir xxx command line + cddir = Sys_ScanForCD (); + if (cddir && argc < MAX_NUM_ARGVS - 3) + { + int i; + + // don't override a cddir on the command line + for (i=0 ; ivalue) ) + { + Sleep (1); + } + + while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (!GetMessage (&msg, NULL, 0, 0)) + Com_Quit (); + sys_msg_time = msg.time; + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + do + { + newtime = Sys_Milliseconds (); + time = newtime - oldtime; + } while (time < 1); +// Con_Printf ("time:%5.2f - %5.2f = %5.2f\n", newtime, oldtime, time); + + // _controlfp( ~( _EM_ZERODIVIDE /*| _EM_INVALID*/ ), _MCW_EM ); + _controlfp( _PC_24, _MCW_PC ); + Qcommon_Frame (time); + + oldtime = newtime; + } + + // never gets here + return TRUE; +} diff --git a/win32/vid_dll.c b/win32/vid_dll.c new file mode 100644 index 000000000..404788521 --- /dev/null +++ b/win32/vid_dll.c @@ -0,0 +1,760 @@ +/* +Copyright (C) 1997-2001 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. + +*/ +// Main windowed and fullscreen graphics interface module. This module +// is used for both the software and OpenGL rendering versions of the +// Quake refresh engine. +#include +#include + +#include "..\client\client.h" +#include "winquake.h" +//#include "zmouse.h" + +// Structure containing functions exported from refresh DLL +refexport_t re; + +cvar_t *win_noalttab; + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS +#endif + +static UINT MSH_MOUSEWHEEL; + +// Console variables that we need to access from this module +cvar_t *vid_gamma; +cvar_t *vid_ref; // Name of Refresh DLL loaded +cvar_t *vid_xpos; // X coordinate of window position +cvar_t *vid_ypos; // Y coordinate of window position +cvar_t *vid_fullscreen; + +// Global variables used internally by this module +viddef_t viddef; // global video state; used by other modules +HINSTANCE reflib_library; // Handle to refresh DLL +qboolean reflib_active = 0; + +HWND cl_hwnd; // Main window handle for life of program + +#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) ) + +LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +static qboolean s_alttab_disabled; + +extern unsigned sys_msg_time; + +/* +** WIN32 helper functions +*/ +extern qboolean s_win95; + +static void WIN_DisableAltTab( void ) +{ + if ( s_alttab_disabled ) + return; + + if ( s_win95 ) + { + BOOL old; + + SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 ); + } + else + { + RegisterHotKey( 0, 0, MOD_ALT, VK_TAB ); + RegisterHotKey( 0, 1, MOD_ALT, VK_RETURN ); + } + s_alttab_disabled = true; +} + +static void WIN_EnableAltTab( void ) +{ + if ( s_alttab_disabled ) + { + if ( s_win95 ) + { + BOOL old; + + SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 ); + } + else + { + UnregisterHotKey( 0, 0 ); + UnregisterHotKey( 0, 1 ); + } + + s_alttab_disabled = false; + } +} + +/* +========================================================================== + +DLL GLUE + +========================================================================== +*/ + +#define MAXPRINTMSG 4096 +void VID_Printf (int print_level, char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + static qboolean inupdate; + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + + if (print_level == PRINT_ALL) + { + Com_Printf ("%s", msg); + } + else if ( print_level == PRINT_DEVELOPER ) + { + Com_DPrintf ("%s", msg); + } + else if ( print_level == PRINT_ALERT ) + { + MessageBox( 0, msg, "PRINT_ALERT", MB_ICONWARNING ); + OutputDebugString( msg ); + } +} + +void VID_Error (int err_level, char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + static qboolean inupdate; + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + + Com_Error (err_level,"%s", msg); +} + +//========================================================================== + +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, K_PAUSE, 0 , K_HOME, + K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,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 +}; + +/* +======= +MapKey + +Map from windows to quake keynums +======= +*/ +int MapKey (int key) +{ + int result; + int modified = ( key >> 16 ) & 255; + qboolean is_extended = false; + + if ( modified > 127) + return 0; + + if ( key & ( 1 << 24 ) ) + is_extended = true; + + result = scantokey[modified]; + + if ( !is_extended ) + { + switch ( result ) + { + case K_HOME: + return K_KP_HOME; + case K_UPARROW: + return K_KP_UPARROW; + case K_PGUP: + return K_KP_PGUP; + case K_LEFTARROW: + return K_KP_LEFTARROW; + case K_RIGHTARROW: + return K_KP_RIGHTARROW; + case K_END: + return K_KP_END; + case K_DOWNARROW: + return K_KP_DOWNARROW; + case K_PGDN: + return K_KP_PGDN; + case K_INS: + return K_KP_INS; + case K_DEL: + return K_KP_DEL; + default: + return result; + } + } + else + { + switch ( result ) + { + case 0x0D: + return K_KP_ENTER; + case 0x2F: + return K_KP_SLASH; + case 0xAF: + return K_KP_PLUS; + } + return result; + } +} + +void AppActivate(BOOL fActive, BOOL minimize) +{ + Minimized = minimize; + + Key_ClearStates(); + + // we don't want to act like we're active if we're minimized + if (fActive && !Minimized) + ActiveApp = true; + else + ActiveApp = false; + + // minimize/restore mouse-capture on demand + if (!ActiveApp) + { + IN_Activate (false); + CDAudio_Activate (false); + S_Activate (false); + + if ( win_noalttab->value ) + { + WIN_EnableAltTab(); + } + } + else + { + IN_Activate (true); + CDAudio_Activate (true); + S_Activate (true); + if ( win_noalttab->value ) + { + WIN_DisableAltTab(); + } + } +} + +/* +==================== +MainWndProc + +main window procedure +==================== +*/ +LONG WINAPI MainWndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 0; + + if ( uMsg == MSH_MOUSEWHEEL ) + { + if ( ( ( int ) wParam ) > 0 ) + { + Key_Event( K_MWHEELUP, true, sys_msg_time ); + Key_Event( K_MWHEELUP, false, sys_msg_time ); + } + else + { + Key_Event( K_MWHEELDOWN, true, sys_msg_time ); + Key_Event( K_MWHEELDOWN, false, sys_msg_time ); + } + return DefWindowProc (hWnd, uMsg, wParam, lParam); + } + + switch (uMsg) + { + case WM_MOUSEWHEEL: + /* + ** this chunk of code theoretically only works under NT4 and Win98 + ** since this message doesn't exist under Win95 + */ + if ( ( short ) HIWORD( wParam ) > 0 ) + { + Key_Event( K_MWHEELUP, true, sys_msg_time ); + Key_Event( K_MWHEELUP, false, sys_msg_time ); + } + else + { + Key_Event( K_MWHEELDOWN, true, sys_msg_time ); + Key_Event( K_MWHEELDOWN, false, sys_msg_time ); + } + break; + + case WM_HOTKEY: + return 0; + + case WM_CREATE: + cl_hwnd = hWnd; + + MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG"); + return DefWindowProc (hWnd, uMsg, wParam, lParam); + + case WM_PAINT: + SCR_DirtyScreen (); // force entire screen to update next frame + return DefWindowProc (hWnd, uMsg, wParam, lParam); + + case WM_DESTROY: + // let sound and input know about this? + cl_hwnd = NULL; + return DefWindowProc (hWnd, uMsg, wParam, lParam); + + case WM_ACTIVATE: + { + int fActive, fMinimized; + + // KJB: Watch this for problems in fullscreen modes with Alt-tabbing. + fActive = LOWORD(wParam); + fMinimized = (BOOL) HIWORD(wParam); + + AppActivate( fActive != WA_INACTIVE, fMinimized); + + if ( reflib_active ) + re.AppActivate( !( fActive == WA_INACTIVE ) ); + } + return DefWindowProc (hWnd, uMsg, wParam, lParam); + + case WM_MOVE: + { + int xPos, yPos; + RECT r; + int style; + + if (!vid_fullscreen->value) + { + xPos = (short) LOWORD(lParam); // horizontal position + yPos = (short) HIWORD(lParam); // vertical position + + r.left = 0; + r.top = 0; + r.right = 1; + r.bottom = 1; + + style = GetWindowLong( hWnd, GWL_STYLE ); + AdjustWindowRect( &r, style, FALSE ); + + Cvar_SetValue( "vid_xpos", xPos + r.left); + Cvar_SetValue( "vid_ypos", yPos + r.top); + vid_xpos->modified = false; + vid_ypos->modified = false; + if (ActiveApp) + IN_Activate (true); + } + } + return DefWindowProc (hWnd, uMsg, wParam, lParam); + +// this is complicated because Win32 seems to pack multiple mouse events into +// one update sometimes, so we always check all states and look for events + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEMOVE: + { + int temp; + + temp = 0; + + if (wParam & MK_LBUTTON) + temp |= 1; + + if (wParam & MK_RBUTTON) + temp |= 2; + + if (wParam & MK_MBUTTON) + temp |= 4; + + IN_MouseEvent (temp); + } + break; + + case WM_SYSCOMMAND: + if ( wParam == SC_SCREENSAVE ) + return 0; + return DefWindowProc (hWnd, uMsg, wParam, lParam); + case WM_SYSKEYDOWN: + if ( wParam == 13 ) + { + if ( vid_fullscreen ) + { + Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value ); + } + return 0; + } + // fall through + case WM_KEYDOWN: + Key_Event( MapKey( lParam ), true, sys_msg_time); + break; + + case WM_SYSKEYUP: + case WM_KEYUP: + Key_Event( MapKey( lParam ), false, sys_msg_time); + break; + + case MM_MCINOTIFY: + { + LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + } + break; + + default: // pass all unhandled messages to DefWindowProc + return DefWindowProc (hWnd, uMsg, wParam, lParam); + } + + /* return 0 if handled message, 1 if not */ + return DefWindowProc( hWnd, uMsg, wParam, lParam ); +} + +/* +============ +VID_Restart_f + +Console command to re-start the video mode and refresh DLL. We do this +simply by setting the modified flag for the vid_ref variable, which will +cause the entire video mode and refresh DLL to be reset on the next frame. +============ +*/ +void VID_Restart_f (void) +{ + vid_ref->modified = true; +} + +void VID_Front_f( void ) +{ + SetWindowLong( cl_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST ); + SetForegroundWindow( cl_hwnd ); +} + +/* +** VID_GetModeInfo +*/ +typedef struct vidmode_s +{ + const char *description; + int width, height; + int mode; +} vidmode_t; + +vidmode_t vid_modes[] = +{ + { "Mode 0: 320x240", 320, 240, 0 }, + { "Mode 1: 400x300", 400, 300, 1 }, + { "Mode 2: 512x384", 512, 384, 2 }, + { "Mode 3: 640x480", 640, 480, 3 }, + { "Mode 4: 800x600", 800, 600, 4 }, + { "Mode 5: 960x720", 960, 720, 5 }, + { "Mode 6: 1024x768", 1024, 768, 6 }, + { "Mode 7: 1152x864", 1152, 864, 7 }, + { "Mode 8: 1280x960", 1280, 960, 8 }, + { "Mode 9: 1600x1200", 1600, 1200, 9 } +}; + +qboolean VID_GetModeInfo( int *width, int *height, int mode ) +{ + if ( mode < 0 || mode >= VID_NUM_MODES ) + return false; + + *width = vid_modes[mode].width; + *height = vid_modes[mode].height; + + return true; +} + +/* +** VID_UpdateWindowPosAndSize +*/ +void VID_UpdateWindowPosAndSize( int x, int y ) +{ + RECT r; + int style; + int w, h; + + r.left = 0; + r.top = 0; + r.right = viddef.width; + r.bottom = viddef.height; + + style = GetWindowLong( cl_hwnd, GWL_STYLE ); + AdjustWindowRect( &r, style, FALSE ); + + w = r.right - r.left; + h = r.bottom - r.top; + + MoveWindow( cl_hwnd, vid_xpos->value, vid_ypos->value, w, h, TRUE ); +} + +/* +** VID_NewWindow +*/ +void VID_NewWindow ( int width, int height) +{ + viddef.width = width; + viddef.height = height; + + cl.force_refdef = true; // can't use a paused refdef +} + +void VID_FreeReflib (void) +{ + if ( !FreeLibrary( reflib_library ) ) + Com_Error( ERR_FATAL, "Reflib FreeLibrary failed" ); + memset (&re, 0, sizeof(re)); + reflib_library = NULL; + reflib_active = false; +} + +/* +============== +VID_LoadRefresh +============== +*/ +qboolean VID_LoadRefresh( char *name ) +{ + refimport_t ri; + GetRefAPI_t GetRefAPI; + + if ( reflib_active ) + { + re.Shutdown(); + VID_FreeReflib (); + } + + Com_Printf( "------- Loading %s -------\n", name ); + + if ( ( reflib_library = LoadLibrary( name ) ) == 0 ) + { + Com_Printf( "LoadLibrary(\"%s\") failed\n", name ); + + return false; + } + + ri.Cmd_AddCommand = Cmd_AddCommand; + ri.Cmd_RemoveCommand = Cmd_RemoveCommand; + ri.Cmd_Argc = Cmd_Argc; + ri.Cmd_Argv = Cmd_Argv; + ri.Cmd_ExecuteText = Cbuf_ExecuteText; + ri.Con_Printf = VID_Printf; + ri.Sys_Error = VID_Error; + ri.FS_LoadFile = FS_LoadFile; + ri.FS_FreeFile = FS_FreeFile; + ri.FS_Gamedir = FS_Gamedir; + ri.Cvar_Get = Cvar_Get; + ri.Cvar_Set = Cvar_Set; + ri.Cvar_SetValue = Cvar_SetValue; + ri.Vid_GetModeInfo = VID_GetModeInfo; + ri.Vid_MenuInit = VID_MenuInit; + ri.Vid_NewWindow = VID_NewWindow; + + if ( ( GetRefAPI = (void *) GetProcAddress( reflib_library, "GetRefAPI" ) ) == 0 ) + Com_Error( ERR_FATAL, "GetProcAddress failed on %s", name ); + + re = GetRefAPI( ri ); + + if (re.api_version != API_VERSION) + { + VID_FreeReflib (); + Com_Error (ERR_FATAL, "%s has incompatible api_version", name); + } + + if ( re.Init( global_hInstance, MainWndProc ) == -1 ) + { + re.Shutdown(); + VID_FreeReflib (); + return false; + } + + Com_Printf( "------------------------------------\n"); + reflib_active = true; + +//====== +//PGM + vidref_val = VIDREF_OTHER; + if(vid_ref) + { + if(!strcmp (vid_ref->string, "gl")) + vidref_val = VIDREF_GL; + else if(!strcmp(vid_ref->string, "soft")) + vidref_val = VIDREF_SOFT; + } +//PGM +//====== + + return true; +} + +/* +============ +VID_CheckChanges + +This function gets called once just before drawing each frame, and it's sole purpose in life +is to check to see if any of the video mode parameters have changed, and if they have to +update the rendering DLL and/or video mode to match. +============ +*/ +void VID_CheckChanges (void) +{ + char name[100]; + + if ( win_noalttab->modified ) + { + if ( win_noalttab->value ) + { + WIN_DisableAltTab(); + } + else + { + WIN_EnableAltTab(); + } + win_noalttab->modified = false; + } + + if ( vid_ref->modified ) + { + cl.force_refdef = true; // can't use a paused refdef + S_StopAllSounds(); + } + while (vid_ref->modified) + { + /* + ** refresh has changed + */ + vid_ref->modified = false; + vid_fullscreen->modified = true; + cl.refresh_prepped = false; + cls.disable_screen = true; + + Com_sprintf( name, sizeof(name), "ref_%s.dll", vid_ref->string ); + if ( !VID_LoadRefresh( name ) ) + { + if ( strcmp (vid_ref->string, "soft") == 0 ) + Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!"); + Cvar_Set( "vid_ref", "soft" ); + + /* + ** drop the console if we fail to load a refresh + */ + if ( cls.key_dest != key_console ) + { + Con_ToggleConsole_f(); + } + } + cls.disable_screen = false; + } + + /* + ** update our window position + */ + if ( vid_xpos->modified || vid_ypos->modified ) + { + if (!vid_fullscreen->value) + VID_UpdateWindowPosAndSize( vid_xpos->value, vid_ypos->value ); + + vid_xpos->modified = false; + vid_ypos->modified = false; + } +} + +/* +============ +VID_Init +============ +*/ +void VID_Init (void) +{ + /* Create the video variables so we know how to start the graphics drivers */ + vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE); + vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE); + vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE); + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE); + vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE ); + win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE ); + + /* Add some console commands that we want to handle */ + Cmd_AddCommand ("vid_restart", VID_Restart_f); + Cmd_AddCommand ("vid_front", VID_Front_f); + + /* + ** this is a gross hack but necessary to clamp the mode for 3Dfx + */ +#if 0 + { + cvar_t *gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 ); + cvar_t *gl_mode = Cvar_Get( "gl_mode", "3", 0 ); + + if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 ) + { + Cvar_SetValue( "gl_mode", 3 ); + viddef.width = 640; + viddef.height = 480; + } + } +#endif + + /* Disable the 3Dfx splash screen */ + putenv("FX_GLIDE_NO_SPLASH=0"); + + /* Start the graphics mode and load refresh DLL */ + VID_CheckChanges(); +} + +/* +============ +VID_Shutdown +============ +*/ +void VID_Shutdown (void) +{ + if ( reflib_active ) + { + re.Shutdown (); + VID_FreeReflib (); + } +} + + diff --git a/win32/vid_menu.c b/win32/vid_menu.c new file mode 100644 index 000000000..2592bcf32 --- /dev/null +++ b/win32/vid_menu.c @@ -0,0 +1,473 @@ +/* +Copyright (C) 1997-2001 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 "../client/client.h" +#include "../client/qmenu.h" + +#define REF_SOFT 0 +#define REF_OPENGL 1 +#define REF_3DFX 2 +#define REF_POWERVR 3 +#define REF_VERITE 4 + +extern cvar_t *vid_ref; +extern cvar_t *vid_fullscreen; +extern cvar_t *vid_gamma; +extern cvar_t *scr_viewsize; + +static cvar_t *gl_mode; +static cvar_t *gl_driver; +static cvar_t *gl_picmip; +static cvar_t *gl_ext_palettedtexture; +static cvar_t *gl_finish; + +static cvar_t *sw_mode; +static cvar_t *sw_stipplealpha; + +extern void M_ForceMenuOff( void ); + +/* +==================================================================== + +MENU INTERACTION + +==================================================================== +*/ +#define SOFTWARE_MENU 0 +#define OPENGL_MENU 1 + +static menuframework_s s_software_menu; +static menuframework_s s_opengl_menu; +static menuframework_s *s_current_menu; +static int s_current_menu_index; + +static menulist_s s_mode_list[2]; +static menulist_s s_ref_list[2]; +static menuslider_s s_tq_slider; +static menuslider_s s_screensize_slider[2]; +static menuslider_s s_brightness_slider[2]; +static menulist_s s_fs_box[2]; +static menulist_s s_stipple_box; +static menulist_s s_paletted_texture_box; +static menulist_s s_finish_box; +static menuaction_s s_cancel_action[2]; +static menuaction_s s_defaults_action[2]; + +static void DriverCallback( void *unused ) +{ + s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue; + + if ( s_ref_list[s_current_menu_index].curvalue == 0 ) + { + s_current_menu = &s_software_menu; + s_current_menu_index = 0; + } + else + { + s_current_menu = &s_opengl_menu; + s_current_menu_index = 1; + } + +} + +static void ScreenSizeCallback( void *s ) +{ + menuslider_s *slider = ( menuslider_s * ) s; + + Cvar_SetValue( "viewsize", slider->curvalue * 10 ); +} + +static void BrightnessCallback( void *s ) +{ + menuslider_s *slider = ( menuslider_s * ) s; + + if ( s_current_menu_index == SOFTWARE_MENU ) + s_brightness_slider[1].curvalue = s_brightness_slider[0].curvalue; + else + s_brightness_slider[0].curvalue = s_brightness_slider[1].curvalue; + + if ( stricmp( vid_ref->string, "soft" ) == 0 ) + { + float gamma = ( 0.8 - ( slider->curvalue/10.0 - 0.5 ) ) + 0.5; + + Cvar_SetValue( "vid_gamma", gamma ); + } +} + +static void ResetDefaults( void *unused ) +{ + VID_MenuInit(); +} + +static void ApplyChanges( void *unused ) +{ + float gamma; + + /* + ** make values consistent + */ + s_fs_box[!s_current_menu_index].curvalue = s_fs_box[s_current_menu_index].curvalue; + s_brightness_slider[!s_current_menu_index].curvalue = s_brightness_slider[s_current_menu_index].curvalue; + s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue; + + /* + ** invert sense so greater = brighter, and scale to a range of 0.5 to 1.3 + */ + gamma = ( 0.8 - ( s_brightness_slider[s_current_menu_index].curvalue/10.0 - 0.5 ) ) + 0.5; + + Cvar_SetValue( "vid_gamma", gamma ); + Cvar_SetValue( "sw_stipplealpha", s_stipple_box.curvalue ); + Cvar_SetValue( "gl_picmip", 3 - s_tq_slider.curvalue ); + Cvar_SetValue( "vid_fullscreen", s_fs_box[s_current_menu_index].curvalue ); + Cvar_SetValue( "gl_ext_palettedtexture", s_paletted_texture_box.curvalue ); + Cvar_SetValue( "gl_finish", s_finish_box.curvalue ); + Cvar_SetValue( "sw_mode", s_mode_list[SOFTWARE_MENU].curvalue ); + Cvar_SetValue( "gl_mode", s_mode_list[OPENGL_MENU].curvalue ); + + switch ( s_ref_list[s_current_menu_index].curvalue ) + { + case REF_SOFT: + Cvar_Set( "vid_ref", "soft" ); + break; + case REF_OPENGL: + Cvar_Set( "vid_ref", "gl" ); + Cvar_Set( "gl_driver", "opengl32" ); + break; + case REF_3DFX: + Cvar_Set( "vid_ref", "gl" ); + Cvar_Set( "gl_driver", "3dfxgl" ); + break; + case REF_POWERVR: + Cvar_Set( "vid_ref", "gl" ); + Cvar_Set( "gl_driver", "pvrgl" ); + break; + case REF_VERITE: + Cvar_Set( "vid_ref", "gl" ); + Cvar_Set( "gl_driver", "veritegl" ); + break; + } + + /* + ** update appropriate stuff if we're running OpenGL and gamma + ** has been modified + */ + if ( stricmp( vid_ref->string, "gl" ) == 0 ) + { + if ( vid_gamma->modified ) + { + vid_ref->modified = true; + if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 ) + { + char envbuffer[1024]; + float g; + + vid_ref->modified = true; + + g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F; + Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g ); + putenv( envbuffer ); + Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g ); + putenv( envbuffer ); + + vid_gamma->modified = false; + } + } + + if ( gl_driver->modified ) + vid_ref->modified = true; + } + + M_ForceMenuOff(); +} + +static void CancelChanges( void *unused ) +{ + extern void M_PopMenu( void ); + + M_PopMenu(); +} + +/* +** VID_MenuInit +*/ +void VID_MenuInit( void ) +{ + static const char *resolutions[] = + { + "[320 240 ]", + "[400 300 ]", + "[512 384 ]", + "[640 480 ]", + "[800 600 ]", + "[960 720 ]", + "[1024 768 ]", + "[1152 864 ]", + "[1280 960 ]", + "[1600 1200]", + 0 + }; + static const char *refs[] = + { + "[software ]", + "[default OpenGL]", + "[3Dfx OpenGL ]", + "[PowerVR OpenGL]", +// "[Rendition OpenGL]", + 0 + }; + static const char *yesno_names[] = + { + "no", + "yes", + 0 + }; + int i; + + if ( !gl_driver ) + gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 ); + if ( !gl_picmip ) + gl_picmip = Cvar_Get( "gl_picmip", "0", 0 ); + if ( !gl_mode ) + gl_mode = Cvar_Get( "gl_mode", "3", 0 ); + if ( !sw_mode ) + sw_mode = Cvar_Get( "sw_mode", "0", 0 ); + if ( !gl_ext_palettedtexture ) + gl_ext_palettedtexture = Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE ); + if ( !gl_finish ) + gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE ); + + if ( !sw_stipplealpha ) + sw_stipplealpha = Cvar_Get( "sw_stipplealpha", "0", CVAR_ARCHIVE ); + + s_mode_list[SOFTWARE_MENU].curvalue = sw_mode->value; + s_mode_list[OPENGL_MENU].curvalue = gl_mode->value; + + if ( !scr_viewsize ) + scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE); + + s_screensize_slider[SOFTWARE_MENU].curvalue = scr_viewsize->value/10; + s_screensize_slider[OPENGL_MENU].curvalue = scr_viewsize->value/10; + + if ( strcmp( vid_ref->string, "soft" ) == 0 ) + { + s_current_menu_index = SOFTWARE_MENU; + s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_SOFT; + } + else if ( strcmp( vid_ref->string, "gl" ) == 0 ) + { + s_current_menu_index = OPENGL_MENU; + if ( strcmp( gl_driver->string, "3dfxgl" ) == 0 ) + s_ref_list[s_current_menu_index].curvalue = REF_3DFX; + else if ( strcmp( gl_driver->string, "pvrgl" ) == 0 ) + s_ref_list[s_current_menu_index].curvalue = REF_POWERVR; + else if ( strcmp( gl_driver->string, "opengl32" ) == 0 ) + s_ref_list[s_current_menu_index].curvalue = REF_OPENGL; + else +// s_ref_list[s_current_menu_index].curvalue = REF_VERITE; + s_ref_list[s_current_menu_index].curvalue = REF_OPENGL; + } + + s_software_menu.x = viddef.width * 0.50; + s_software_menu.nitems = 0; + s_opengl_menu.x = viddef.width * 0.50; + s_opengl_menu.nitems = 0; + + for ( i = 0; i < 2; i++ ) + { + s_ref_list[i].generic.type = MTYPE_SPINCONTROL; + s_ref_list[i].generic.name = "driver"; + s_ref_list[i].generic.x = 0; + s_ref_list[i].generic.y = 0; + s_ref_list[i].generic.callback = DriverCallback; + s_ref_list[i].itemnames = refs; + + s_mode_list[i].generic.type = MTYPE_SPINCONTROL; + s_mode_list[i].generic.name = "video mode"; + s_mode_list[i].generic.x = 0; + s_mode_list[i].generic.y = 10; + s_mode_list[i].itemnames = resolutions; + + s_screensize_slider[i].generic.type = MTYPE_SLIDER; + s_screensize_slider[i].generic.x = 0; + s_screensize_slider[i].generic.y = 20; + s_screensize_slider[i].generic.name = "screen size"; + s_screensize_slider[i].minvalue = 3; + s_screensize_slider[i].maxvalue = 12; + s_screensize_slider[i].generic.callback = ScreenSizeCallback; + + s_brightness_slider[i].generic.type = MTYPE_SLIDER; + s_brightness_slider[i].generic.x = 0; + s_brightness_slider[i].generic.y = 30; + s_brightness_slider[i].generic.name = "brightness"; + s_brightness_slider[i].generic.callback = BrightnessCallback; + s_brightness_slider[i].minvalue = 5; + s_brightness_slider[i].maxvalue = 13; + s_brightness_slider[i].curvalue = ( 1.3 - vid_gamma->value + 0.5 ) * 10; + + s_fs_box[i].generic.type = MTYPE_SPINCONTROL; + s_fs_box[i].generic.x = 0; + s_fs_box[i].generic.y = 40; + s_fs_box[i].generic.name = "fullscreen"; + s_fs_box[i].itemnames = yesno_names; + s_fs_box[i].curvalue = vid_fullscreen->value; + + s_defaults_action[i].generic.type = MTYPE_ACTION; + s_defaults_action[i].generic.name = "reset to defaults"; + s_defaults_action[i].generic.x = 0; + s_defaults_action[i].generic.y = 90; + s_defaults_action[i].generic.callback = ResetDefaults; + + s_cancel_action[i].generic.type = MTYPE_ACTION; + s_cancel_action[i].generic.name = "cancel"; + s_cancel_action[i].generic.x = 0; + s_cancel_action[i].generic.y = 100; + s_cancel_action[i].generic.callback = CancelChanges; + } + + s_stipple_box.generic.type = MTYPE_SPINCONTROL; + s_stipple_box.generic.x = 0; + s_stipple_box.generic.y = 60; + s_stipple_box.generic.name = "stipple alpha"; + s_stipple_box.curvalue = sw_stipplealpha->value; + s_stipple_box.itemnames = yesno_names; + + s_tq_slider.generic.type = MTYPE_SLIDER; + s_tq_slider.generic.x = 0; + s_tq_slider.generic.y = 60; + s_tq_slider.generic.name = "texture quality"; + s_tq_slider.minvalue = 0; + s_tq_slider.maxvalue = 3; + s_tq_slider.curvalue = 3-gl_picmip->value; + + s_paletted_texture_box.generic.type = MTYPE_SPINCONTROL; + s_paletted_texture_box.generic.x = 0; + s_paletted_texture_box.generic.y = 70; + s_paletted_texture_box.generic.name = "8-bit textures"; + s_paletted_texture_box.itemnames = yesno_names; + s_paletted_texture_box.curvalue = gl_ext_palettedtexture->value; + + s_finish_box.generic.type = MTYPE_SPINCONTROL; + s_finish_box.generic.x = 0; + s_finish_box.generic.y = 80; + s_finish_box.generic.name = "sync every frame"; + s_finish_box.curvalue = gl_finish->value; + s_finish_box.itemnames = yesno_names; + + Menu_AddItem( &s_software_menu, ( void * ) &s_ref_list[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_mode_list[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_screensize_slider[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_brightness_slider[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_fs_box[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_stipple_box ); + + Menu_AddItem( &s_opengl_menu, ( void * ) &s_ref_list[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_mode_list[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_screensize_slider[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_brightness_slider[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_fs_box[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_tq_slider ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_paletted_texture_box ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_finish_box ); + + Menu_AddItem( &s_software_menu, ( void * ) &s_defaults_action[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_cancel_action[SOFTWARE_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_defaults_action[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_cancel_action[OPENGL_MENU] ); + + Menu_Center( &s_software_menu ); + Menu_Center( &s_opengl_menu ); + s_opengl_menu.x -= 8; + s_software_menu.x -= 8; +} + +/* +================ +VID_MenuDraw +================ +*/ +void VID_MenuDraw (void) +{ + int w, h; + + if ( s_current_menu_index == 0 ) + s_current_menu = &s_software_menu; + else + s_current_menu = &s_opengl_menu; + + /* + ** draw the banner + */ + re.DrawGetPicSize( &w, &h, "m_banner_video" ); + re.DrawPic( viddef.width / 2 - w / 2, viddef.height /2 - 110, "m_banner_video" ); + + /* + ** move cursor to a reasonable starting position + */ + Menu_AdjustCursor( s_current_menu, 1 ); + + /* + ** draw the menu + */ + Menu_Draw( s_current_menu ); +} + +/* +================ +VID_MenuKey +================ +*/ +const char *VID_MenuKey( int key ) +{ + menuframework_s *m = s_current_menu; + static const char *sound = "misc/menu1.wav"; + + switch ( key ) + { + case K_ESCAPE: + ApplyChanges( 0 ); + return NULL; + case K_KP_UPARROW: + case K_UPARROW: + m->cursor--; + Menu_AdjustCursor( m, -1 ); + break; + case K_KP_DOWNARROW: + case K_DOWNARROW: + m->cursor++; + Menu_AdjustCursor( m, 1 ); + break; + case K_KP_LEFTARROW: + case K_LEFTARROW: + Menu_SlideItem( m, -1 ); + break; + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + Menu_SlideItem( m, 1 ); + break; + case K_KP_ENTER: + case K_ENTER: + if ( !Menu_SelectItem( m ) ) + ApplyChanges( NULL ); + break; + } + + return sound; +} + + diff --git a/win32/winquake.aps b/win32/winquake.aps new file mode 100644 index 000000000..844c9199b Binary files /dev/null and b/win32/winquake.aps differ diff --git a/win32/winquake.h b/win32/winquake.h new file mode 100644 index 000000000..612a667fc --- /dev/null +++ b/win32/winquake.h @@ -0,0 +1,44 @@ +/* +Copyright (C) 1997-2001 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 + +#include + +#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE) + +extern HINSTANCE global_hInstance; + +extern LPDIRECTSOUND pDS; +extern LPDIRECTSOUNDBUFFER pDSBuf; + +extern DWORD gSndBufSize; + +extern HWND cl_hwnd; +extern qboolean ActiveApp, Minimized; + +void IN_Activate (qboolean active); +void IN_MouseEvent (int mstate); + +extern int window_center_x, window_center_y; +extern RECT window_rect; diff --git a/win32/winquake.rc b/win32/winquake.rc new file mode 100644 index 000000000..0d0a7fbdd --- /dev/null +++ b/win32/winquake.rc @@ -0,0 +1,98 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "q2.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 0, 0, 62, 21 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | + WS_VISIBLE +EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE +FONT 16, "Times New Roman", 0, 0, 0x1 +BEGIN + CTEXT "Starting QW...",IDC_STATIC,4,6,54,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_STRING1 "WinQuake" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED +