Merge branch 'zscript' of https://github.com/rheit/zdoom into gz-zscript

This commit is contained in:
Christoph Oelckers 2016-12-06 12:33:52 +01:00
commit e41e404143
34 changed files with 521 additions and 1211 deletions

View file

@ -252,9 +252,10 @@ Note: All <bool> fields default to false unless mentioned otherwise.
// negative values are used as their absolute. Default = 1. // negative values are used as their absolute. Default = 1.
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal", renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil", // "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
// "translucent", "fuzzy", "optfuzzy", "soultrans". Default is an empty string for no change. // "addstencil", "shaded", "addshaded", "translucent", "fuzzy", "optfuzzy", "soultrans" and "shadow".
fillcolor = <integer>; // Fill color used by the "stencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000. // Default is an empty string for no change.
fillcolor = <integer>; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000.
alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0. alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0.
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0. score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal). pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).

View file

@ -650,7 +650,6 @@ public:
virtual void Touch(AActor *toucher); virtual void Touch(AActor *toucher);
void CallTouch(AActor *toucher); void CallTouch(AActor *toucher);
// Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed // Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
// Made a metadata property so no longer virtual // Made a metadata property so no longer virtual
void Howl (); void Howl ();
@ -1549,6 +1548,7 @@ struct FTranslatedLineTarget
{ {
AActor *linetarget; AActor *linetarget;
DAngle angleFromSource; DAngle angleFromSource;
DAngle attackAngleFromSource;
bool unlinked; // found by a trace that went through an unlinked portal. bool unlinked; // found by a trace that went through an unlinked portal.
}; };

View file

@ -598,894 +598,6 @@ dmsdone add esp,8
;*----------------------------------------------------------------------
;*
;* R_DrawColumnP
;*
;*----------------------------------------------------------------------
GLOBAL @R_DrawColumnP_ASM@0
GLOBAL _R_DrawColumnP_ASM
GLOBAL R_DrawColumnP_ASM
align 16
R_DrawColumnP_ASM:
_R_DrawColumnP_ASM:
@R_DrawColumnP_ASM@0:
; count = dc_yh - dc_yl;
mov ecx,[dc_count]
test ecx,ecx
jle near rdcpret ; count <= 0: nothing to do, so leave
push ebp ; save registers
push ebx
push edi
push esi
; dest = ylookup[dc_yl] + dc_x + dc_destorg;
mov edi,[dc_dest]
mov ebp,ecx
mov ebx,[dc_texturefrac] ; ebx = frac
rdcp1: sub edi,SPACEFILLER4
mov ecx,ebx
shr ecx,16
mov esi,[dc_source]
mov edx,[dc_iscale]
mov eax,[dc_colormap]
cmp BYTE [CPU+66],byte 5
jg rdcploop2
align 16
; The registers should now look like this:
;
; [31 .. 16][15 .. 8][7 .. 0]
; eax [colormap ]
; ebx [yi ][yf ]
; ecx [scratch ]
; edx [dyi ][dyf ]
; esi [source texture column ]
; edi [destination screen pointer ]
; ebp [counter ]
;
; Note the partial register stalls on anything better than a Pentium
; That's why there are two versions of this loop.
rdcploop:
mov cl,[esi+ecx] ; Fetch texel
xor ch,ch
add ebx,edx ; increment frac
rdcp2: add edi,SPACEFILLER4 ; increment destination pointer
mov cl,[eax+ecx] ; colormap texel
mov [edi],cl ; Store texel
mov ecx,ebx
shr ecx,16
dec ebp
jnz rdcploop ; loop
pop esi
pop edi
pop ebx
pop ebp
rdcpret:
ret
align 16
rdcploop2:
movzx ecx,byte [esi+ecx] ; Fetch texel
add ebx,edx ; increment frac
mov cl,[eax+ecx] ; colormap texel
rdcp3: add edi,SPACEFILLER4 ; increment destination pointer
mov [edi],cl ; Store texel
mov ecx,ebx
shr ecx,16
dec ebp
jnz rdcploop2 ; loop
pop esi
pop edi
pop ebx
pop ebp
ret
;*----------------------------------------------------------------------
;*
;* R_DrawFuzzColumnP
;*
;*----------------------------------------------------------------------
GLOBAL @R_DrawFuzzColumnP_ASM@0
GLOBAL _R_DrawFuzzColumnP_ASM
GLOBAL R_DrawFuzzColumnP_ASM
align 16
R_DrawFuzzColumnP_ASM:
_R_DrawFuzzColumnP_ASM:
@R_DrawFuzzColumnP_ASM@0:
; Adjust borders. Low...
mov eax,[dc_yl]
push ebx
push esi
push edi
push ebp
cmp eax,0
jg .ylok
mov eax,1
nop
; ...and high.
.ylok mov edx,[fuzzviewheight]
mov esi,[dc_yh]
cmp esi,edx
jle .yhok
mov esi,edx
nop
.yhok mov edx,[dc_x]
sub esi,eax ; esi = count
js near .dfcdone ; Zero length (or less)
mov edi,[ylookup+eax*4]
mov ebx,edx
add edi,[dc_destorg]
mov eax,[NormalLight]
mov ecx,[fuzzpos]
add edi,ebx
add eax,256*6
inc esi
mov ebp,[dc_pitch]
mov edx,FUZZTABLE
test ecx,ecx
je .fuzz0
;
; esi = count
; edi = dest
; ecx = fuzzpos
; eax = colormap 6
;
; first loop: end with fuzzpos or count 0, whichever happens first
sub edx,ecx ; edx = # of entries left in fuzzoffset
mov ebx,esi
cmp esi,edx
jle .enuf
mov esi,edx
.enuf sub ebx,esi
mov edx,[fuzzoffset+ecx*4]
push ebx
xor ebx,ebx
.loop1 inc ecx
mov bl,[edi+edx]
dec esi
mov bl,[eax+ebx]
mov [edi],bl
lea edi,[edi+ebp]
mov edx,[fuzzoffset+ecx*4]
jnz .loop1
; second loop: Chunk it into groups of FUZZTABLE-sized spans and do those
pop esi
cmp ecx,FUZZTABLE
jl .savefuzzpos
xor ecx,ecx
nop
.fuzz0 cmp esi,FUZZTABLE
jl .chunked
.oloop lea edx,[esi-FUZZTABLE]
mov esi,FUZZTABLE
push edx
mov edx,[fuzzoffset+ecx*4]
.iloop inc ecx
mov bl,[edi+edx]
dec esi
mov bl,[eax+ebx]
mov [edi],bl
lea edi,[edi+ebp]
mov edx,[fuzzoffset+ecx*4]
jnz .iloop
pop esi
xor ecx,ecx
cmp esi,FUZZTABLE
jge .oloop
; third loop: Do whatever is left
.chunked:
test esi,esi
jle .savefuzzpos
mov edx,[fuzzoffset+ecx*4]
nop
.loop3 inc ecx
mov bl,[edi+edx]
dec esi
mov bl,[eax+ebx]
mov [edi],bl
lea edi,[edi+ebp]
mov edx,[fuzzoffset+ecx*4]
jnz .loop3
.savefuzzpos:
mov [fuzzpos],ecx
.dfcdone:
pop ebp
pop edi
pop esi
pop ebx
ret
;*----------------------------------------------------------------------
;*
;* R_DrawColumnHorizP_ASM
;*
;*----------------------------------------------------------------------
GLOBAL @R_DrawColumnHorizP_ASM@0
GLOBAL _R_DrawColumnHorizP_ASM
GLOBAL R_DrawColumnHorizP_ASM
align 16
@R_DrawColumnHorizP_ASM@0:
_R_DrawColumnHorizP_ASM:
R_DrawColumnHorizP_ASM:
; count = dc_yh - dc_yl;
mov eax,[dc_yh]
mov ecx,[dc_yl]
sub eax,ecx
mov edx,[dc_x]
jl near .leave ; count < 0: nothing to do, so leave
push ebp ; save registers
push ebx
push edi
push esi
inc eax ; make 0 count mean 0 pixels
and edx,3
push eax
mov eax,[dc_temp]
mov esi,[dc_ctspan+edx*4]
add eax,edx
lea eax,[eax+ecx*4] ; eax = top of column in buffer
mov ebp,[dc_yh]
mov [esi],ecx
mov [esi+4],ebp
add esi,8
mov edi,[dc_source]
mov [dc_ctspan+edx*4],esi
mov esi,[dc_iscale]
mov ecx,[dc_texturefrac] ; ecx = frac
mov dl,[edi] ; load cache
mov ebx,[esp]
and ebx,0xfffffff8
jnz .mthan8
; Register usage in the following code is:
;
; eax: dest
; edi: source
; ecx: frac (16.16)
; esi: fracstep (16.16)
; ebx: add1
; ebp: add2
; dl: texel1
; dh: texel2
;[esp] count
; there are fewer than 8 pixels to draw
mov ebx,[esp]
.lthan8 shr ebx,1
jnc .even
; do one pixel before loop (little opportunity for pairing)
mov ebp,ecx ; copy frac to ebx
add ecx,esi ; increment frac
shr ebp,16 ; shift frac over to low end
add eax,4
mov dl,[edi+ebp]
mov [eax-4],dl
.even test ebx,ebx
jz near .done
.loop2 mov [esp],ebx ; save counter
mov ebx,ecx ; copy frac for texel1 to ebx
shr ebx,16 ; shift frac for texel1 to low end
add ecx,esi ; increment frac
mov ebp,ecx ; copy frac for texel2 to ebp
shr ebp,16 ; shift frac for texel2 to low end
add ecx,esi ; increment frac
mov dl,[edi+ebx] ; read texel1
mov ebx,[esp] ; fetch counter
mov dh,[edi+ebp] ; read texel2
mov [eax],dl ; write texel1
mov [eax+4],dh ; write texel2
add eax,8 ; increment dest
dec ebx ; decrement counter
jnz .loop2 ; loop until it hits 0
jmp .done
; there are more than 8 pixels to draw. position eax as close to a 32 byte
; boundary as possible, then do whatever is left.
.mthan8 test eax,4
jz .try2
mov ebp,ecx ; frac: in ebp
add ecx,esi ; step
shr ebp,16 ; frac: shift
add eax,4 ; increment dest
mov ebx,[esp] ; fetch counter
mov dl,[edi+ebp] ; tex: read
dec ebx ; decrement counter
mov [eax-4],dl ; tex: write
mov [esp],ebx ; store counter
.try2 test eax,8
jz .try4
mov ebx,ecx ; frac1: in ebx
add ecx,esi ; step
shr ebx,16 ; frac1: shift
mov ebp,ecx ; frac2: in ebp
shr ebp,16 ; frac2: shift
add ecx,esi ; step
mov dl,[edi+ebx] ; tex1: read
mov ebx,[esp] ; fetch counter
mov dh,[edi+ebp] ; tex2: read
mov [eax],dl ; tex1: write
mov [eax+4],dh ; tex2: write
sub ebx,2 ; decrement counter
add eax,8 ; increment dest
mov [esp],ebx ; store counter
.try4 test eax,16
jz .try8
mov ebx,ecx ; frac1: in ebx
add ecx,esi ; step
shr ebx,16 ; frac1: shift
mov ebp,ecx ; frac2: in ebp
shr ebp,16 ; frac2: shift
add ecx,esi ; step
mov dl,[edi+ebx] ; tex1: read
mov ebx,ecx ; frac3: in ebx
shr ebx,16 ; frac3: shift
mov dh,[edi+ebp] ; tex2: read
add ecx,esi ; step
mov [eax],dl ; tex1: write
mov [eax+4],dh ; tex2: write
mov ebp,ecx ; frac4: in ebp
shr ebp,16 ; frac4: shift
add ecx,esi ; step
mov dl,[edi+ebx] ; tex3: read
mov ebx,[esp] ; fetch counter
mov dh,[edi+ebp] ; tex4: read
sub ebx,4 ; decrement counter
mov [esp],ebx ; store counter
mov [eax+8],dl ; tex3: write
mov [eax+12],dh ; tex4: write
add eax,16 ; increment dest
.try8 mov ebx,[esp] ; make counter count groups of 8
sub esp,4
shr ebx,3
jmp .tail8
align 16
.loop8 mov [esp],ebx ; save counter
mov ebx,ecx ; frac1: in ebx
shr ebx,16 ; frac1: shift
add ecx,esi ; step
mov ebp,ecx ; frac2: in ebp
shr ebp,16 ; frac2: shift
add ecx,esi ; step
mov dl,[edi+ebx] ; tex1: read
mov ebx,ecx ; frac3: in ebx
mov dh,[edi+ebp] ; tex2: read
shr ebx,16 ; frac3: shift
add ecx,esi ; step
mov [eax],dl ; tex1: write
mov [eax+4],dh ; tex2: write
mov ebp,ecx ; frac4: in ebp
shr ebp,16 ; frac4: shift
add ecx,esi ; step
mov dl,[edi+ebx] ; tex3: read
mov ebx,ecx ; frac5: in ebx
mov dh,[edi+ebp] ; tex4: read
shr ebx,16 ; frac5: shift
mov [eax+8],dl ; tex3: write
mov [eax+12],dh ; tex4: write
add ecx,esi ; step
mov ebp,ecx ; frac6: in ebp
shr ebp,16 ; frac6: shift
mov dl,[edi+ebx] ; tex5: read
add ecx,esi ; step
mov ebx,ecx ; frac7: in ebx
mov [eax+16],dl ; tex5: write
shr ebx,16 ; frac7: shift
mov dh,[edi+ebp] ; tex6: read
add ecx,esi ; step
mov ebp,ecx ; frac8: in ebp
mov [eax+20],dh ; tex6: write
shr ebp,16 ; frac8: shift
add eax,32 ; increment dest pointer
mov dl,[edi+ebx] ; tex7: read
mov ebx,[esp] ; fetch counter
mov [eax-8],dl ; tex7: write
mov dh,[edi+ebp] ; tex8: read
add ecx,esi ; step
mov [eax-4],dh ; tex8: write
mov dl,[eax] ; load cache
dec ebx ; decrement counter
.tail8 jnz near .loop8 ; loop if more to do
pop ebp
mov ebx,[esp]
and ebx,7
jnz near .lthan8
.done pop eax
pop esi
pop edi
pop ebx
pop ebp
.leave ret
;*----------------------------------------------------------------------
;*
;* rt_copy1col_asm
;*
;* ecx = hx
;* edx = sx
;* [esp+4] = yl
;* [esp+8] = yh
;*
;*----------------------------------------------------------------------
GLOBAL @rt_copy1col_asm@16
GLOBAL _rt_copy1col_asm
GLOBAL rt_copy1col_asm
align 16
rt_copy1col_asm:
_rt_copy1col_asm:
pop eax
mov edx,[esp+4*3]
mov ecx,[esp+4*2]
push edx
push ecx
mov ecx,[esp+4*2]
mov edx,[esp+4*3]
push eax
@rt_copy1col_asm@16:
mov eax, [esp+4]
push ebx
mov ebx, [esp+12]
push esi
sub ebx, eax
push edi
js .done
lea esi,[eax*4]
inc ebx ; ebx = count
mov eax,edx
add ecx,esi
mov edi,[ylookup+esi]
add ecx,[dc_temp] ; ecx = source
mov esi,[dc_pitch] ; esi = pitch
add eax,edi ; eax = dest
add eax,[dc_destorg]
shr ebx,1
jnc .even
mov dl,[ecx]
add ecx,4
mov [eax],dl
add eax,esi
.even and ebx,ebx
jz .done
.loop mov dl,[ecx]
mov dh,[ecx+4]
mov [eax],dl
mov [eax+esi],dh
add ecx,8
lea eax,[eax+esi*2]
dec ebx
jnz .loop
.done pop edi
pop esi
pop ebx
ret 8
;*----------------------------------------------------------------------
;*
;* rt_copy4cols_asm
;*
;* ecx = sx
;* edx = yl
;* [esp+4] = yh
;*
;*----------------------------------------------------------------------
GLOBAL @rt_copy4cols_asm@12
GLOBAL _rt_copy4cols_asm
GLOBAL rt_copy4cols_asm
align 16
rt_copy4cols_asm:
_rt_copy4cols_asm:
pop eax
mov ecx,[esp+8]
mov edx,[esp+4]
push ecx
mov ecx,[esp+4]
push eax
@rt_copy4cols_asm@12:
push ebx
mov ebx,[esp+8]
push esi
sub ebx,edx
push edi
js .done
inc ebx ; ebx = count
mov eax,ecx
mov esi,[ylookup+edx*4]
mov ecx,[dc_temp]
add eax,esi ; eax = dest
add eax,[dc_destorg]
lea ecx,[ecx+edx*4] ; ecx = source
mov edx,[dc_pitch] ; edx = pitch
shr ebx,1
jnc .even
mov esi,[ecx]
add ecx,4
mov [eax],esi
add eax,edx
.even and ebx,ebx
jz .done
.loop mov esi,[ecx]
mov edi,[ecx+4]
mov [eax],esi
mov [eax+edx],edi
add ecx,8
lea eax,[eax+edx*2]
dec ebx
jnz .loop
.done pop edi
pop esi
pop ebx
ret 4
;*----------------------------------------------------------------------
;*
;* rt_map1col_asm
;*
;* ecx = hx
;* edx = sx
;* [esp+4] = yl
;* [esp+8] = yh
;*
;*----------------------------------------------------------------------
GLOBAL @rt_map1col_asm@16
GLOBAL _rt_map1col_asm
GLOBAL rt_map1col_asm
align 16
rt_map1col_asm:
_rt_map1col_asm:
pop eax
mov edx,[esp+4*3]
mov ecx,[esp+4*2]
push edx
push ecx
mov ecx,[esp+4*2]
mov edx,[esp+4*3]
push eax
@rt_map1col_asm@16:
mov eax,[esp+4]
push ebx
mov ebx,[esp+12]
push ebp
push esi
sub ebx, eax
push edi
js .done
lea edi,[eax*4]
mov esi,[dc_colormap] ; esi = colormap
inc ebx ; ebx = count
mov eax,edx
lea ebp,[ecx+edi] ; ebp = source
add ebp,[dc_temp]
mov ecx,[ylookup+edi]
mov edi,[dc_pitch] ; edi = pitch
add eax,ecx ; eax = dest
xor ecx,ecx
xor edx,edx
add eax,[dc_destorg]
shr ebx,1
jnc .even
mov dl,[ebp]
add ebp,4
mov dl,[esi+edx]
mov [eax],dl
add eax,edi
.even and ebx,ebx
jz .done
.loop mov dl,[ebp]
mov cl,[ebp+4]
add ebp,8
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax],dl
mov [eax+edi],cl
dec ebx
lea eax,[eax+edi*2]
jnz .loop
.done pop edi
pop esi
pop ebp
pop ebx
ret 8
;*----------------------------------------------------------------------
;*
;* rt_map4cols_asm
;*
;* rt_map4cols_asm1 is for PPro and above
;* rt_map4cols_asm2 is for Pentium and below
;*
;* ecx = sx
;* edx = yl
;* [esp+4] = yh
;*
;*----------------------------------------------------------------------
GLOBAL @rt_map4cols_asm1@12
GLOBAL _rt_map4cols_asm1
GLOBAL rt_map4cols_asm1
align 16
rt_map4cols_asm1:
_rt_map4cols_asm1:
pop eax
mov ecx,[esp+8]
mov edx,[esp+4]
push ecx
mov ecx,[esp+4]
push eax
@rt_map4cols_asm1@12:
push ebx
mov ebx,[esp+8]
push ebp
push esi
sub ebx,edx
push edi
js near .done
mov esi,[dc_colormap] ; esi = colormap
shl edx,2
mov eax,ecx
inc ebx ; ebx = count
mov edi,[ylookup+edx]
mov ebp,[dc_temp]
add ebp,edx ; ebp = source
add eax,edi ; eax = dest
mov edi,[dc_pitch] ; edi = pitch
add eax,[dc_destorg]
xor ecx,ecx
xor edx,edx
shr ebx,1
jnc .even
mov dl,[ebp]
mov cl,[ebp+1]
add ebp,4
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax],dl
mov [eax+1],cl
mov dl,[ebp-2]
mov cl,[ebp-1]
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax+2],dl
mov [eax+3],cl
add eax,edi
.even and ebx,ebx
jz .done
.loop:
mov dl,[ebp]
mov cl,[ebp+1]
add ebp,8
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax],dl
mov [eax+1],cl
mov dl,[ebp-6]
mov cl,[ebp-5]
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax+2],dl
mov [eax+3],cl
mov dl,[ebp-4]
mov cl,[ebp-3]
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax+edi],dl
mov [eax+edi+1],cl
mov dl,[ebp-2]
mov cl,[ebp-1]
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax+edi+2],dl
mov [eax+edi+3],cl
lea eax,[eax+edi*2]
dec ebx
jnz .loop
.done pop edi
pop esi
pop ebp
pop ebx
ret 4
GLOBAL @rt_map4cols_asm2@12
GLOBAL _rt_map4cols_asm2
GLOBAL rt_map4cols_asm2
align 16
rt_map4cols_asm2:
_rt_map4cols_asm2:
pop eax
mov ecx,[esp+8]
mov edx,[esp+4]
push ecx
mov ecx,[esp+4]
push eax
@rt_map4cols_asm2@12:
push ebx
mov ebx,[esp+8]
push ebp
push esi
sub ebx,edx
push edi
js near .done
mov esi,[dc_colormap] ; esi = colormap
shl edx,2
mov eax,ecx
inc ebx ; ebx = count
mov edi,[ylookup+edx]
mov ebp,[dc_temp]
add ebp,edx ; ebp = source
add eax,edi ; eax = dest
mov edi,[dc_pitch] ; edi = pitch
add eax,[dc_destorg]
xor ecx,ecx
xor edx,edx
shr ebx,1
jnc .even
mov dl,[ebp]
mov cl,[ebp+1]
add ebp,4
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax],dl
mov [eax+1],cl
mov dl,[ebp-2]
mov cl,[ebp-1]
mov dl,[esi+edx]
mov cl,[esi+ecx]
mov [eax+2],dl
mov [eax+3],cl
add eax,edi
.even and ebx,ebx
jz .done
.loop:
mov dl,[ebp+3]
mov ch,[esi+edx]
mov dl,[ebp+2]
mov cl,[esi+edx]
shl ecx,16
mov dl,[ebp+1]
mov ch,[esi+edx]
mov dl,[ebp]
mov cl,[esi+edx]
mov [eax],ecx
add eax,edi
mov dl,[ebp+7]
mov ch,[esi+edx]
mov dl,[ebp+6]
mov cl,[esi+edx]
shl ecx,16
mov dl,[ebp+5]
mov ch,[esi+edx]
mov dl,[ebp+4]
mov cl,[esi+edx]
mov [eax],ecx
add eax,edi
add ebp,8
dec ebx
jnz .loop
.done pop edi
pop esi
pop ebp
pop ebx
ret 4
align 16
GLOBAL rt_shaded4cols_asm GLOBAL rt_shaded4cols_asm
GLOBAL _rt_shaded4cols_asm GLOBAL _rt_shaded4cols_asm
@ -1875,9 +987,6 @@ ASM_PatchPitch:
_ASM_PatchPitch: _ASM_PatchPitch:
@ASM_PatchPitch@0: @ASM_PatchPitch@0:
mov eax,[dc_pitch] mov eax,[dc_pitch]
mov [rdcp1+2],eax
mov [rdcp2+2],eax
mov [rdcp3+2],eax
mov [s4p+1],eax mov [s4p+1],eax
mov [a4p+1],eax mov [a4p+1],eax
mov [ac4p+1],eax mov [ac4p+1],eax

View file

@ -1144,7 +1144,7 @@ CCMD(currentpos)
} }
else else
{ {
Printf("You are not in game!"); Printf("You are not in game!\n");
} }
} }

View file

@ -2653,7 +2653,6 @@ void D_DoomMain (void)
} }
D_DoomLoop (); // this only returns if a 'restart' CCMD is given. D_DoomLoop (); // this only returns if a 'restart' CCMD is given.
maxberestart:
// //
// Clean up after a restart // Clean up after a restart
// //

View file

@ -74,6 +74,7 @@ TArray<PClass *> PClass::AllClasses;
bool PClass::bShutdown; bool PClass::bShutdown;
PErrorType *TypeError; PErrorType *TypeError;
PErrorType *TypeAuto;
PVoidType *TypeVoid; PVoidType *TypeVoid;
PInt *TypeSInt8, *TypeUInt8; PInt *TypeSInt8, *TypeUInt8;
PInt *TypeSInt16, *TypeUInt16; PInt *TypeSInt16, *TypeUInt16;
@ -570,6 +571,7 @@ void PType::StaticInit()
// Create types and add them type the type table. // Create types and add them type the type table.
TypeTable.AddType(TypeError = new PErrorType); TypeTable.AddType(TypeError = new PErrorType);
TypeTable.AddType(TypeAuto = new PErrorType(2));
TypeTable.AddType(TypeVoid = new PVoidType); TypeTable.AddType(TypeVoid = new PVoidType);
TypeTable.AddType(TypeSInt8 = new PInt(1, false)); TypeTable.AddType(TypeSInt8 = new PInt(1, false));
TypeTable.AddType(TypeUInt8 = new PInt(1, true)); TypeTable.AddType(TypeUInt8 = new PInt(1, true));

View file

@ -370,7 +370,7 @@ class PErrorType : public PType
{ {
DECLARE_CLASS(PErrorType, PType); DECLARE_CLASS(PErrorType, PType);
public: public:
PErrorType() : PType(0, 1) {} PErrorType(int which = 1) : PType(0, which) {}
}; };
class PVoidType : public PType class PVoidType : public PType
@ -930,6 +930,7 @@ PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *>
// Built-in types ----------------------------------------------------------- // Built-in types -----------------------------------------------------------
extern PErrorType *TypeError; extern PErrorType *TypeError;
extern PErrorType *TypeAuto;
extern PVoidType *TypeVoid; extern PVoidType *TypeVoid;
extern PInt *TypeSInt8, *TypeUInt8; extern PInt *TypeSInt8, *TypeUInt8;
extern PInt *TypeSInt16, *TypeUInt16; extern PInt *TypeSInt16, *TypeUInt16;

View file

@ -721,6 +721,7 @@ xx(State)
xx(Fixed) xx(Fixed)
xx(Vector2) xx(Vector2)
xx(Vector3) xx(Vector3)
xx(let)
xx(Min) xx(Min)
xx(Max) xx(Max)

View file

@ -46,6 +46,7 @@
#include "r_utility.h" #include "r_utility.h"
#include "p_blockmap.h" #include "p_blockmap.h"
#include "p_3dmidtex.h" #include "p_3dmidtex.h"
#include "virtual.h"
#include "s_sound.h" #include "s_sound.h"
#include "decallib.h" #include "decallib.h"
@ -1134,6 +1135,12 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, CanCollideWith)
{
// No need to check the parameters, as they are not even used.
ACTION_RETURN_BOOL(true);
}
bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm) bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm)
{ {
AActor *thing = cres.thing; AActor *thing = cres.thing;
@ -1222,15 +1229,55 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
(thing->flags5 & MF5_DONTRIP) || (thing->flags5 & MF5_DONTRIP) ||
((tm.thing->flags6 & MF6_NOBOSSRIP) && (thing->flags2 & MF2_BOSS))) ((tm.thing->flags6 & MF6_NOBOSSRIP) && (thing->flags2 & MF2_BOSS)))
{ {
if (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP) // Some things prefer not to overlap each other, if possible (Q: Is this even needed anymore? It was just for dealing with some deficiencies in the code below in Heretic.)
{ // Some things prefer not to overlap each other, if possible if (!(tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP))
return unblocking; {
if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z()))
return true;
} }
if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z())) // If they are not allowed to overlap, the rest of this function still needs to be executed.
return true;
} }
} }
// Call the script callback. This must be done before any other checks that perform some actual action or may already return a 'block'.
// The checks here are to do this only for conditions that would later result in an action, calling this for everything would be too much of a drag if
// too many scripted overrides were being used, as PIT_CheckThing is even called for touching all the monster corpses lying around.
if (((thing->flags & MF_SOLID) || (thing->flags6 & (MF6_TOUCHY | MF6_BUMPSPECIAL))) &&
((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (tm.thing->flags2 & MF2_BLASTED) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS) || (tm.thing->BounceFlags & BOUNCE_MBF)))
{
static unsigned VIndex = ~0u;
if (VIndex == ~0u)
{
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCollideWith");
assert(VIndex != ~0u);
}
VMValue params[3] = { tm.thing, thing, false };
VMReturn ret;
int retval;
ret.IntAt(&retval);
auto clss = tm.thing->GetClass();
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
if (!retval) return true;
}
std::swap(params[0].a, params[1].a);
params[2].i = true;
// re-get for the other actor.
clss = thing->GetClass();
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
if (!retval) return true;
}
}
if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)) if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING))
{ {
// touchy object is alive, toucher is solid // touchy object is alive, toucher is solid
@ -3541,6 +3588,7 @@ struct aim_t
res.linetarget = th; res.linetarget = th;
res.pitch = pitch; res.pitch = pitch;
res.angleFromSource = (th->Pos() - startpos).Angle(); res.angleFromSource = (th->Pos() - startpos).Angle();
res.attackAngleFromSource = res.angleFromSource; // at this point we do not have an attack angle so it's the same as the actual angle between actors.
res.unlinked = unlinked; res.unlinked = unlinked;
res.frac = frac; res.frac = frac;
} }
@ -4459,7 +4507,9 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
if (victim != NULL) if (victim != NULL)
{ {
victim->linetarget = trace.Actor; victim->linetarget = trace.Actor;
victim->angleFromSource = trace.SrcAngleFromTarget; victim->attackAngleFromSource = trace.SrcAngleFromTarget;
// With arbitrary portals this cannot be calculated so using the actual attack angle is the only option.
victim->angleFromSource = trace.unlinked? victim->attackAngleFromSource : t1->AngleTo(trace.Actor);
victim->unlinked = trace.unlinked; victim->unlinked = trace.unlinked;
} }
} }

View file

@ -7418,7 +7418,7 @@ DEFINE_ACTION_FUNCTION(AActor, ClearCounters)
int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive) int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
{ {
if (Inventory != nullptr) if (Inventory != nullptr)
Inventory->ModifyDamage(damage, damagetype, damage, false); Inventory->ModifyDamage(damage, damagetype, damage, passive);
return damage; return damage;
} }

View file

@ -69,17 +69,10 @@ int scaledviewwidth;
// These get changed depending on the current // These get changed depending on the current
// screen depth and asm/no asm. // screen depth and asm/no asm.
void (*R_DrawColumnHoriz)(void); void (*R_DrawColumnHoriz)(void);
void (*R_DrawColumn)(void);
void (*R_DrawFuzzColumn)(void);
void (*R_DrawTranslatedColumn)(void); void (*R_DrawTranslatedColumn)(void);
void (*R_DrawShadedColumn)(void); void (*R_DrawShadedColumn)(void);
void (*R_DrawSpan)(void); void (*R_DrawSpan)(void);
void (*R_DrawSpanMasked)(void); void (*R_DrawSpanMasked)(void);
void (*R_DrawSpanTranslucent)(void);
void (*R_DrawSpanMaskedTranslucent)(void);
void (*R_DrawSpanAddClamp)(void);
void (*R_DrawSpanMaskedAddClamp)(void);
void (*rt_map4cols)(int,int,int);
// //
// R_DrawColumn // R_DrawColumn
@ -171,7 +164,6 @@ void R_InitShadeMaps()
/* */ /* */
/************************************/ /************************************/
#ifndef X86_ASM
// //
// A column is a vertical slice/span from a wall texture that, // A column is a vertical slice/span from a wall texture that,
// given the DOOM style restrictions on the view orientation, // given the DOOM style restrictions on the view orientation,
@ -179,7 +171,7 @@ void R_InitShadeMaps()
// Thus a special case loop for very fast rendering can // Thus a special case loop for very fast rendering can
// be used. It has also been used with Wolfenstein 3D. // be used. It has also been used with Wolfenstein 3D.
// //
void R_DrawColumnP_C (void) void R_DrawColumn (void)
{ {
int count; int count;
BYTE* dest; BYTE* dest;
@ -222,7 +214,7 @@ void R_DrawColumnP_C (void)
} while (--count); } while (--count);
} }
} }
#endif
// [RH] Just fills a column with a color // [RH] Just fills a column with a color
void R_FillColumnP (void) void R_FillColumnP (void)
@ -414,13 +406,12 @@ void R_InitFuzzTable (int fuzzoff)
} }
} }
#ifndef X86_ASM
// //
// Creates a fuzzy image by copying pixels from adjacent ones above and below. // Creates a fuzzy image by copying pixels from adjacent ones above and below.
// Used with an all black colormap, this could create the SHADOW effect, // Used with an all black colormap, this could create the SHADOW effect,
// i.e. spectres and invisible players. // i.e. spectres and invisible players.
// //
void R_DrawFuzzColumnP_C (void) void R_DrawFuzzColumn (void)
{ {
int count; int count;
BYTE *dest; BYTE *dest;
@ -490,7 +481,6 @@ void R_DrawFuzzColumnP_C (void)
fuzzpos = fuzz; fuzzpos = fuzz;
} }
} }
#endif
// //
// R_DrawTranlucentColumn // R_DrawTranlucentColumn
@ -1046,7 +1036,7 @@ void R_SetupSpanBits(FTexture *tex)
{ {
ds_xbits--; ds_xbits--;
} }
if ((1 << ds_ybits) > tex->GetHeight()) if ((1 << ds_ybits) > tex->GetHeight())
{ {
ds_ybits--; ds_ybits--;
} }
@ -1057,7 +1047,7 @@ void R_SetupSpanBits(FTexture *tex)
// //
// Draws the actual span. // Draws the actual span.
#ifndef X86_ASM //#ifndef X86_ASM
void R_DrawSpanP_C (void) void R_DrawSpanP_C (void)
{ {
dsfixed_t xfrac; dsfixed_t xfrac;
@ -1156,7 +1146,7 @@ void R_DrawSpanMaskedP_C (void)
// 64x64 is the most common case by far, so special case it. // 64x64 is the most common case by far, so special case it.
do do
{ {
BYTE texdata; int texdata;
spot = ((xfrac>>(32-6-6))&(63*64)) + (yfrac>>(32-6)); spot = ((xfrac>>(32-6-6))&(63*64)) + (yfrac>>(32-6));
texdata = source[spot]; texdata = source[spot];
@ -1176,7 +1166,7 @@ void R_DrawSpanMaskedP_C (void)
int xmask = ((1 << ds_xbits) - 1) << ds_ybits; int xmask = ((1 << ds_xbits) - 1) << ds_ybits;
do do
{ {
BYTE texdata; int texdata;
spot = ((xfrac >> xshift) & xmask) + (yfrac >> yshift); spot = ((xfrac >> xshift) & xmask) + (yfrac >> yshift);
texdata = source[spot]; texdata = source[spot];
@ -1190,9 +1180,9 @@ void R_DrawSpanMaskedP_C (void)
} while (--count); } while (--count);
} }
} }
#endif //#endif
void R_DrawSpanTranslucentP_C (void) void R_DrawSpanTranslucent (void)
{ {
dsfixed_t xfrac; dsfixed_t xfrac;
dsfixed_t yfrac; dsfixed_t yfrac;
@ -1252,7 +1242,7 @@ void R_DrawSpanTranslucentP_C (void)
} }
} }
void R_DrawSpanMaskedTranslucentP_C (void) void R_DrawSpanMaskedTranslucent (void)
{ {
dsfixed_t xfrac; dsfixed_t xfrac;
dsfixed_t yfrac; dsfixed_t yfrac;
@ -1326,7 +1316,7 @@ void R_DrawSpanMaskedTranslucentP_C (void)
} }
} }
void R_DrawSpanAddClampP_C (void) void R_DrawSpanAddClamp (void)
{ {
dsfixed_t xfrac; dsfixed_t xfrac;
dsfixed_t yfrac; dsfixed_t yfrac;
@ -1392,7 +1382,7 @@ void R_DrawSpanAddClampP_C (void)
} }
} }
void R_DrawSpanMaskedAddClampP_C (void) void R_DrawSpanMaskedAddClamp (void)
{ {
dsfixed_t xfrac; dsfixed_t xfrac;
dsfixed_t yfrac; dsfixed_t yfrac;
@ -1682,6 +1672,7 @@ DWORD vlinec1 ()
return frac; return frac;
} }
#ifndef _M_X64
void vlinec4 () void vlinec4 ()
{ {
BYTE *dest = dc_dest; BYTE *dest = dc_dest;
@ -1698,6 +1689,43 @@ void vlinec4 ()
dest += dc_pitch; dest += dc_pitch;
} while (--count); } while (--count);
} }
#else
// Optimized version for 64 bit. In 64 bit mode, accessing global variables is very expensive so even though
// this exceeds the register count, loading all those values into a local variable is faster than not loading all of them.
void vlinec4()
{
BYTE *dest = dc_dest;
int count = dc_count;
int bits = vlinebits;
DWORD place;
auto pal0 = palookupoffse[0];
auto pal1 = palookupoffse[1];
auto pal2 = palookupoffse[2];
auto pal3 = palookupoffse[3];
auto buf0 = bufplce[0];
auto buf1 = bufplce[1];
auto buf2 = bufplce[2];
auto buf3 = bufplce[3];
const auto vince0 = vince[0];
const auto vince1 = vince[1];
const auto vince2 = vince[2];
const auto vince3 = vince[3];
auto vplce0 = vplce[0];
auto vplce1 = vplce[1];
auto vplce2 = vplce[2];
auto vplce3 = vplce[3];
do
{
dest[0] = pal0[buf0[(place = vplce0) >> bits]]; vplce0 = place + vince0;
dest[1] = pal1[buf1[(place = vplce1) >> bits]]; vplce1 = place + vince1;
dest[2] = pal2[buf2[(place = vplce2) >> bits]]; vplce2 = place + vince2;
dest[3] = pal3[buf3[(place = vplce3) >> bits]]; vplce3 = place + vince3;
dest += dc_pitch;
} while (--count);
}
#endif
#endif #endif
void setupmvline (int fracbits) void setupmvline (int fracbits)
@ -2201,59 +2229,126 @@ void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom)
void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom) void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom)
{ {
for (int col = 0; col < 4; col++) uint8_t *dest = dc_dest;
int count = dc_count;
int pitch = dc_pitch;
const uint8_t *source0[4] = { bufplce[0], bufplce[1], bufplce[2], bufplce[3] };
int textureheight0 = bufheight[0];
const uint32_t *palette = (const uint32_t *)GPalette.BaseColors;
int32_t frac[4] = { (int32_t)vplce[0], (int32_t)vplce[1], (int32_t)vplce[2], (int32_t)vplce[3] };
int32_t fracstep[4] = { (int32_t)vince[0], (int32_t)vince[1], (int32_t)vince[2], (int32_t)vince[3] };
uint8_t output[4];
int start_fade = 2; // How fast it should fade out
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
uint32_t solid_top_fill = RGB32k.RGB[(solid_top_r >> 3)][(solid_top_g >> 3)][(solid_top_b >> 3)];
uint32_t solid_bottom_fill = RGB32k.RGB[(solid_bottom_r >> 3)][(solid_bottom_g >> 3)][(solid_bottom_b >> 3)];
solid_top_fill = (solid_top_fill << 24) | (solid_top_fill << 16) | (solid_top_fill << 8) | solid_top_fill;
solid_bottom_fill = (solid_bottom_fill << 24) | (solid_bottom_fill << 16) | (solid_bottom_fill << 8) | solid_bottom_fill;
// Find bands for top solid color, top fade, center textured, bottom fade, bottom solid color:
int fade_length = (1 << (24 - start_fade));
int start_fadetop_y = (-frac[0]) / fracstep[0];
int end_fadetop_y = (fade_length - frac[0]) / fracstep[0];
int start_fadebottom_y = ((2 << 24) - fade_length - frac[0]) / fracstep[0];
int end_fadebottom_y = ((2 << 24) - frac[0]) / fracstep[0];
for (int col = 1; col < 4; col++)
{ {
uint8_t *dest = dc_dest + col; start_fadetop_y = MIN(start_fadetop_y, (-frac[0]) / fracstep[0]);
int count = dc_count; end_fadetop_y = MAX(end_fadetop_y, (fade_length - frac[0]) / fracstep[0]);
int pitch = dc_pitch; start_fadebottom_y = MIN(start_fadebottom_y, ((2 << 24) - fade_length - frac[0]) / fracstep[0]);
const uint8_t *source0 = bufplce[col]; end_fadebottom_y = MAX(end_fadebottom_y, ((2 << 24) - frac[0]) / fracstep[0]);
int textureheight0 = bufheight[0]; }
start_fadetop_y = clamp(start_fadetop_y, 0, count);
end_fadetop_y = clamp(end_fadetop_y, 0, count);
start_fadebottom_y = clamp(start_fadebottom_y, 0, count);
end_fadebottom_y = clamp(end_fadebottom_y, 0, count);
int32_t frac = vplce[col]; // Top solid color:
int32_t fracstep = vince[col]; for (int index = 0; index < start_fadetop_y; index++)
{
*((uint32_t*)dest) = solid_top_fill;
dest += pitch;
for (int col = 0; col < 4; col++)
frac[col] += fracstep[col];
}
int start_fade = 2; // How fast it should fade out // Top fade:
for (int index = start_fadetop_y; index < end_fadetop_y; index++)
int solid_top_r = RPART(solid_top); {
int solid_top_g = GPART(solid_top); for (int col = 0; col < 4; col++)
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
for (int index = 0; index < count; index++)
{ {
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; uint32_t sample_index = (((((uint32_t)frac[col]) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index]; uint8_t fg = source0[col][sample_index];
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); uint32_t c = palette[fg];
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); int alpha_top = MAX(MIN(frac[col] >> (16 - start_fade), 256), 0);
int inv_alpha_top = 256 - alpha_top;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
output[col] = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
if (alpha_top == 256 && alpha_bottom == 256) frac[col] += fracstep[col];
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
}
frac += fracstep;
dest += pitch;
} }
*((uint32_t*)dest) = *((uint32_t*)output);
dest += pitch;
}
// Textured center:
for (int index = end_fadetop_y; index < start_fadebottom_y; index++)
{
for (int col = 0; col < 4; col++)
{
uint32_t sample_index = (((((uint32_t)frac[col]) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
output[col] = source0[col][sample_index];
frac[col] += fracstep[col];
}
*((uint32_t*)dest) = *((uint32_t*)output);
dest += pitch;
}
// Fade bottom:
for (int index = start_fadebottom_y; index < end_fadebottom_y; index++)
{
for (int col = 0; col < 4; col++)
{
uint32_t sample_index = (((((uint32_t)frac[col]) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[col][sample_index];
uint32_t c = palette[fg];
int alpha_bottom = MAX(MIN(((2 << 24) - frac[col]) >> (16 - start_fade), 256), 0);
int inv_alpha_bottom = 256 - alpha_bottom;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
output[col] = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
frac[col] += fracstep[col];
}
*((uint32_t*)dest) = *((uint32_t*)output);
dest += pitch;
}
// Bottom solid color:
for (int index = end_fadebottom_y; index < count; index++)
{
*((uint32_t*)dest) = solid_bottom_fill;
dest += pitch;
} }
} }
@ -2321,66 +2416,146 @@ void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom)
void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom) void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom)
{ {
for (int col = 0; col < 4; col++) uint8_t *dest = dc_dest;
int count = dc_count;
int pitch = dc_pitch;
const uint8_t *source0[4] = { bufplce[0], bufplce[1], bufplce[2], bufplce[3] };
const uint8_t *source1[4] = { bufplce2[0], bufplce2[1], bufplce2[2], bufplce2[3] };
int textureheight0 = bufheight[0];
uint32_t maxtextureheight1 = bufheight[1] - 1;
const uint32_t *palette = (const uint32_t *)GPalette.BaseColors;
int32_t frac[4] = { (int32_t)vplce[0], (int32_t)vplce[1], (int32_t)vplce[2], (int32_t)vplce[3] };
int32_t fracstep[4] = { (int32_t)vince[0], (int32_t)vince[1], (int32_t)vince[2], (int32_t)vince[3] };
uint8_t output[4];
int start_fade = 2; // How fast it should fade out
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
uint32_t solid_top_fill = RGB32k.RGB[(solid_top_r >> 3)][(solid_top_g >> 3)][(solid_top_b >> 3)];
uint32_t solid_bottom_fill = RGB32k.RGB[(solid_bottom_r >> 3)][(solid_bottom_g >> 3)][(solid_bottom_b >> 3)];
solid_top_fill = (solid_top_fill << 24) | (solid_top_fill << 16) | (solid_top_fill << 8) | solid_top_fill;
solid_bottom_fill = (solid_bottom_fill << 24) | (solid_bottom_fill << 16) | (solid_bottom_fill << 8) | solid_bottom_fill;
// Find bands for top solid color, top fade, center textured, bottom fade, bottom solid color:
int fade_length = (1 << (24 - start_fade));
int start_fadetop_y = (-frac[0]) / fracstep[0];
int end_fadetop_y = (fade_length - frac[0]) / fracstep[0];
int start_fadebottom_y = ((2 << 24) - fade_length - frac[0]) / fracstep[0];
int end_fadebottom_y = ((2 << 24) - frac[0]) / fracstep[0];
for (int col = 1; col < 4; col++)
{ {
uint8_t *dest = dc_dest + col; start_fadetop_y = MIN(start_fadetop_y, (-frac[0]) / fracstep[0]);
int count = dc_count; end_fadetop_y = MAX(end_fadetop_y, (fade_length - frac[0]) / fracstep[0]);
int pitch = dc_pitch; start_fadebottom_y = MIN(start_fadebottom_y, ((2 << 24) - fade_length - frac[0]) / fracstep[0]);
const uint8_t *source0 = bufplce[col]; end_fadebottom_y = MAX(end_fadebottom_y, ((2 << 24) - frac[0]) / fracstep[0]);
const uint8_t *source1 = bufplce2[col]; }
int textureheight0 = bufheight[0]; start_fadetop_y = clamp(start_fadetop_y, 0, count);
uint32_t maxtextureheight1 = bufheight[1] - 1; end_fadetop_y = clamp(end_fadetop_y, 0, count);
start_fadebottom_y = clamp(start_fadebottom_y, 0, count);
end_fadebottom_y = clamp(end_fadebottom_y, 0, count);
int32_t frac = vplce[col]; // Top solid color:
int32_t fracstep = vince[col]; for (int index = 0; index < start_fadetop_y; index++)
{
*((uint32_t*)dest) = solid_top_fill;
dest += pitch;
for (int col = 0; col < 4; col++)
frac[col] += fracstep[col];
}
int start_fade = 2; // How fast it should fade out // Top fade:
for (int index = start_fadetop_y; index < end_fadetop_y; index++)
int solid_top_r = RPART(solid_top); {
int solid_top_g = GPART(solid_top); for (int col = 0; col < 4; col++)
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
for (int index = 0; index < count; index++)
{ {
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; uint32_t sample_index = (((((uint32_t)frac[col]) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index]; uint8_t fg = source0[col][sample_index];
if (fg == 0) if (fg == 0)
{ {
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[sample_index2]; fg = source1[col][sample_index2];
} }
output[col] = fg;
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); uint32_t c = palette[fg];
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); int alpha_top = MAX(MIN(frac[col] >> (16 - start_fade), 256), 0);
int inv_alpha_top = 256 - alpha_top;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
output[col] = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
if (alpha_top == 256 && alpha_bottom == 256) frac[col] += fracstep[col];
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
}
frac += fracstep;
dest += pitch;
} }
*((uint32_t*)dest) = *((uint32_t*)output);
dest += pitch;
}
// Textured center:
for (int index = end_fadetop_y; index < start_fadebottom_y; index++)
{
for (int col = 0; col < 4; col++)
{
uint32_t sample_index = (((((uint32_t)frac[col]) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[col][sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[col][sample_index2];
}
output[col] = fg;
frac[col] += fracstep[col];
}
*((uint32_t*)dest) = *((uint32_t*)output);
dest += pitch;
}
// Fade bottom:
for (int index = start_fadebottom_y; index < end_fadebottom_y; index++)
{
for (int col = 0; col < 4; col++)
{
uint32_t sample_index = (((((uint32_t)frac[col]) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[col][sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[col][sample_index2];
}
output[col] = fg;
uint32_t c = palette[fg];
int alpha_bottom = MAX(MIN(((2 << 24) - frac[col]) >> (16 - start_fade), 256), 0);
int inv_alpha_bottom = 256 - alpha_bottom;
int c_red = RPART(c);
int c_green = GPART(c);
int c_blue = BPART(c);
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
output[col] = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
frac[col] += fracstep[col];
}
*((uint32_t*)dest) = *((uint32_t*)output);
dest += pitch;
}
// Bottom solid color:
for (int index = end_fadebottom_y; index < count; index++)
{
*((uint32_t*)dest) = solid_bottom_fill;
dest += pitch;
} }
} }
@ -2408,35 +2583,18 @@ const BYTE *R_GetColumn (FTexture *tex, int col)
void R_InitColumnDrawers () void R_InitColumnDrawers ()
{ {
#ifdef X86_ASM #ifdef X86_ASM
R_DrawColumn = R_DrawColumnP_ASM; R_DrawColumnHoriz = R_DrawColumnHorizP_C;
R_DrawColumnHoriz = R_DrawColumnHorizP_ASM;
R_DrawFuzzColumn = R_DrawFuzzColumnP_ASM;
R_DrawTranslatedColumn = R_DrawTranslatedColumnP_C; R_DrawTranslatedColumn = R_DrawTranslatedColumnP_C;
R_DrawShadedColumn = R_DrawShadedColumnP_C; R_DrawShadedColumn = R_DrawShadedColumnP_C;
R_DrawSpan = R_DrawSpanP_ASM; R_DrawSpan = R_DrawSpanP_ASM;
R_DrawSpanMasked = R_DrawSpanMaskedP_ASM; R_DrawSpanMasked = R_DrawSpanMaskedP_ASM;
if (CPU.Family <= 5)
{
rt_map4cols = rt_map4cols_asm2;
}
else
{
rt_map4cols = rt_map4cols_asm1;
}
#else #else
R_DrawColumnHoriz = R_DrawColumnHorizP_C; R_DrawColumnHoriz = R_DrawColumnHorizP_C;
R_DrawColumn = R_DrawColumnP_C;
R_DrawFuzzColumn = R_DrawFuzzColumnP_C;
R_DrawTranslatedColumn = R_DrawTranslatedColumnP_C; R_DrawTranslatedColumn = R_DrawTranslatedColumnP_C;
R_DrawShadedColumn = R_DrawShadedColumnP_C; R_DrawShadedColumn = R_DrawShadedColumnP_C;
R_DrawSpan = R_DrawSpanP_C; R_DrawSpan = R_DrawSpanP_C;
R_DrawSpanMasked = R_DrawSpanMaskedP_C; R_DrawSpanMasked = R_DrawSpanMaskedP_C;
rt_map4cols = rt_map4cols_c;
#endif #endif
R_DrawSpanTranslucent = R_DrawSpanTranslucentP_C;
R_DrawSpanMaskedTranslucent = R_DrawSpanMaskedTranslucentP_C;
R_DrawSpanAddClamp = R_DrawSpanAddClampP_C;
R_DrawSpanMaskedAddClamp = R_DrawSpanMaskedAddClampP_C;
} }
// [RH] Choose column drawers in a single place // [RH] Choose column drawers in a single place

View file

@ -65,7 +65,6 @@ extern "C" unsigned int horizspans[4];
// The span blitting interface. // The span blitting interface.
// Hook in assembler or system specific BLT here. // Hook in assembler or system specific BLT here.
extern void (*R_DrawColumn)(void);
extern DWORD (*dovline1) (); extern DWORD (*dovline1) ();
extern DWORD (*doprevline1) (); extern DWORD (*doprevline1) ();
@ -84,7 +83,7 @@ extern void setupmvline (int);
extern void setuptmvline (int); extern void setuptmvline (int);
// The Spectre/Invisibility effect. // The Spectre/Invisibility effect.
extern void (*R_DrawFuzzColumn)(void); extern void R_DrawFuzzColumn(void);
// [RH] Draw shaded column // [RH] Draw shaded column
extern void (*R_DrawShadedColumn)(void); extern void (*R_DrawShadedColumn)(void);
@ -103,16 +102,16 @@ void R_SetSpanSource(const BYTE *pixels);
extern void (*R_DrawSpanMasked)(void); extern void (*R_DrawSpanMasked)(void);
// Span drawing for translucent textures. // Span drawing for translucent textures.
extern void (*R_DrawSpanTranslucent)(void); void R_DrawSpanTranslucent(void);
// Span drawing for masked, translucent textures. // Span drawing for masked, translucent textures.
extern void (*R_DrawSpanMaskedTranslucent)(void); void R_DrawSpanMaskedTranslucent(void);
// Span drawing for translucent, additive textures. // Span drawing for translucent, additive textures.
extern void (*R_DrawSpanAddClamp)(void); void R_DrawSpanAddClamp(void);
// Span drawing for masked, translucent, additive textures. // Span drawing for masked, translucent, additive textures.
extern void (*R_DrawSpanMaskedAddClamp)(void); void R_DrawSpanMaskedAddClamp(void);
// [RH] Span blit into an interleaved intermediate buffer // [RH] Span blit into an interleaved intermediate buffer
extern void (*R_DrawColumnHoriz)(void); extern void (*R_DrawColumnHoriz)(void);
@ -121,16 +120,19 @@ extern void (*R_DrawColumnHoriz)(void);
void R_InitColumnDrawers (); void R_InitColumnDrawers ();
// [RH] Moves data from the temporary buffer to the screen. // [RH] Moves data from the temporary buffer to the screen.
void rt_copy1col(int hx, int sx, int yl, int yh);
void rt_copy4cols(int sx, int yl, int yh);
void rt_map4cols(int sx, int yl, int yh);
extern "C" extern "C"
{ {
void rt_copy1col_c (int hx, int sx, int yl, int yh);
void rt_copy4cols_c (int sx, int yl, int yh);
void rt_shaded1col (int hx, int sx, int yl, int yh); void rt_shaded1col (int hx, int sx, int yl, int yh);
void rt_shaded4cols_c (int sx, int yl, int yh); void rt_shaded4cols_c (int sx, int yl, int yh);
void rt_shaded4cols_asm (int sx, int yl, int yh); void rt_shaded4cols_asm (int sx, int yl, int yh);
void rt_map1col_c (int hx, int sx, int yl, int yh); void rt_map1col (int hx, int sx, int yl, int yh);
void rt_add1col (int hx, int sx, int yl, int yh); void rt_add1col (int hx, int sx, int yl, int yh);
void rt_addclamp1col (int hx, int sx, int yl, int yh); void rt_addclamp1col (int hx, int sx, int yl, int yh);
void rt_subclamp1col (int hx, int sx, int yl, int yh); void rt_subclamp1col (int hx, int sx, int yl, int yh);
@ -142,7 +144,6 @@ void rt_tlateaddclamp1col (int hx, int sx, int yl, int yh);
void rt_tlatesubclamp1col (int hx, int sx, int yl, int yh); void rt_tlatesubclamp1col (int hx, int sx, int yl, int yh);
void rt_tlaterevsubclamp1col (int hx, int sx, int yl, int yh); void rt_tlaterevsubclamp1col (int hx, int sx, int yl, int yh);
void rt_map4cols_c (int sx, int yl, int yh);
void rt_add4cols_c (int sx, int yl, int yh); void rt_add4cols_c (int sx, int yl, int yh);
void rt_addclamp4cols_c (int sx, int yl, int yh); void rt_addclamp4cols_c (int sx, int yl, int yh);
void rt_subclamp4cols (int sx, int yl, int yh); void rt_subclamp4cols (int sx, int yl, int yh);
@ -154,29 +155,16 @@ void rt_tlateaddclamp4cols (int sx, int yl, int yh);
void rt_tlatesubclamp4cols (int sx, int yl, int yh); void rt_tlatesubclamp4cols (int sx, int yl, int yh);
void rt_tlaterevsubclamp4cols (int sx, int yl, int yh); void rt_tlaterevsubclamp4cols (int sx, int yl, int yh);
void rt_copy1col_asm (int hx, int sx, int yl, int yh);
void rt_map1col_asm (int hx, int sx, int yl, int yh);
void rt_copy4cols_asm (int sx, int yl, int yh);
void rt_map4cols_asm1 (int sx, int yl, int yh);
void rt_map4cols_asm2 (int sx, int yl, int yh);
void rt_add4cols_asm (int sx, int yl, int yh); void rt_add4cols_asm (int sx, int yl, int yh);
void rt_addclamp4cols_asm (int sx, int yl, int yh); void rt_addclamp4cols_asm (int sx, int yl, int yh);
} }
extern void (*rt_map4cols)(int sx, int yl, int yh);
#ifdef X86_ASM #ifdef X86_ASM
#define rt_copy1col rt_copy1col_asm
#define rt_copy4cols rt_copy4cols_asm
#define rt_map1col rt_map1col_asm
#define rt_shaded4cols rt_shaded4cols_asm #define rt_shaded4cols rt_shaded4cols_asm
#define rt_add4cols rt_add4cols_asm #define rt_add4cols rt_add4cols_asm
#define rt_addclamp4cols rt_addclamp4cols_asm #define rt_addclamp4cols rt_addclamp4cols_asm
#else #else
#define rt_copy1col rt_copy1col_c
#define rt_copy4cols rt_copy4cols_c
#define rt_map1col rt_map1col_c
#define rt_shaded4cols rt_shaded4cols_c #define rt_shaded4cols rt_shaded4cols_c
#define rt_add4cols rt_add4cols_c #define rt_add4cols rt_add4cols_c
#define rt_addclamp4cols rt_addclamp4cols_c #define rt_addclamp4cols rt_addclamp4cols_c
@ -193,29 +181,25 @@ void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip);
#ifdef X86_ASM #ifdef X86_ASM
extern "C" void R_DrawColumnP_Unrolled (void);
extern "C" void R_DrawColumnHorizP_ASM (void);
extern "C" void R_DrawColumnP_ASM (void);
extern "C" void R_DrawFuzzColumnP_ASM (void);
void R_DrawTranslatedColumnP_C (void);
void R_DrawShadedColumnP_C (void); void R_DrawShadedColumnP_C (void);
extern "C" void R_DrawSpanP_ASM (void); extern "C" void R_DrawSpanP_ASM (void);
extern "C" void R_DrawSpanMaskedP_ASM (void); extern "C" void R_DrawSpanMaskedP_ASM (void);
void R_DrawColumnHorizP_C(void);
#else #else
void R_DrawColumnHorizP_C (void);
void R_DrawColumnP_C (void);
void R_DrawFuzzColumnP_C (void);
void R_DrawTranslatedColumnP_C (void);
void R_DrawShadedColumnP_C (void); void R_DrawShadedColumnP_C (void);
void R_DrawSpanP_C (void); void R_DrawSpanP_C (void);
void R_DrawSpanMaskedP_C (void); void R_DrawSpanMaskedP_C (void);
#endif #endif
void R_DrawSpanTranslucentP_C (void); void R_DrawColumn();
void R_DrawSpanMaskedTranslucentP_C (void); void R_DrawColumnHorizP_C(void);
void R_DrawTranslatedColumnP_C(void);
void R_DrawSpanTranslucent (void);
void R_DrawSpanMaskedTranslucent (void);
void R_DrawTlatedLucentColumnP_C (void); void R_DrawTlatedLucentColumnP_C (void);
#define R_DrawTlatedLucentColumn R_DrawTlatedLucentColumnP_C #define R_DrawTlatedLucentColumn R_DrawTlatedLucentColumnP_C

View file

@ -69,9 +69,8 @@ extern "C" void R_SetupAddCol();
extern "C" void R_SetupAddClampCol(); extern "C" void R_SetupAddClampCol();
#endif #endif
#ifndef X86_ASM
// Copies one span at hx to the screen at sx. // Copies one span at hx to the screen at sx.
void rt_copy1col_c (int hx, int sx, int yl, int yh) void rt_copy1col (int hx, int sx, int yl, int yh)
{ {
BYTE *source; BYTE *source;
BYTE *dest; BYTE *dest;
@ -112,7 +111,7 @@ void rt_copy1col_c (int hx, int sx, int yl, int yh)
} }
// Copies all four spans to the screen starting at sx. // Copies all four spans to the screen starting at sx.
void rt_copy4cols_c (int sx, int yl, int yh) void rt_copy4cols (int sx, int yl, int yh)
{ {
int *source; int *source;
int *dest; int *dest;
@ -145,7 +144,7 @@ void rt_copy4cols_c (int sx, int yl, int yh)
} }
// Maps one span at hx to the screen at sx. // Maps one span at hx to the screen at sx.
void rt_map1col_c (int hx, int sx, int yl, int yh) void rt_map1col (int hx, int sx, int yl, int yh)
{ {
BYTE *colormap; BYTE *colormap;
BYTE *source; BYTE *source;
@ -180,7 +179,7 @@ void rt_map1col_c (int hx, int sx, int yl, int yh)
} }
// Maps all four spans to the screen starting at sx. // Maps all four spans to the screen starting at sx.
void rt_map4cols_c (int sx, int yl, int yh) void rt_map4cols (int sx, int yl, int yh)
{ {
BYTE *colormap; BYTE *colormap;
BYTE *source; BYTE *source;
@ -222,7 +221,6 @@ void rt_map4cols_c (int sx, int yl, int yh)
dest += pitch*2; dest += pitch*2;
} while (--count); } while (--count);
} }
#endif
void rt_Translate1col(const BYTE *translation, int hx, int yl, int yh) void rt_Translate1col(const BYTE *translation, int hx, int yl, int yh)
{ {

View file

@ -183,6 +183,7 @@ std2:
'deprecated' { RET(TK_Deprecated); } 'deprecated' { RET(TK_Deprecated); }
'action' { RET(TK_Action); } 'action' { RET(TK_Action); }
'readonly' { RET(TK_ReadOnly); } 'readonly' { RET(TK_ReadOnly); }
'let' { RET(TK_Let); }
/* Actor state options */ /* Actor state options */
'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); } 'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); }

View file

@ -142,4 +142,5 @@ xx(TK_NoDelay, "'nodelay'")
xx(TK_Offset, "'offset'") xx(TK_Offset, "'offset'")
xx(TK_Slow, "'slow'") xx(TK_Slow, "'slow'")
xx(TK_Bright, "'bright'") xx(TK_Bright, "'bright'")
xx(TK_Let, "'let'")
#undef xx #undef xx

View file

@ -4324,58 +4324,32 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
// //
//========================================================================== //==========================================================================
PPrototype *FxTypeCheck::ReturnProto() ExpEmit FxTypeCheck::EmitCommon(VMFunctionBuilder *build)
{ {
EmitTail = true; ExpEmit castee = left->Emit(build);
return FxExpression::ReturnProto(); ExpEmit casttype = right->Emit(build);
castee.Free(build);
casttype.Free(build);
ExpEmit ares(build, REGT_POINTER);
build->Emit(casttype.Konst ? OP_DYNCAST_K : OP_DYNCAST_R, ares.RegNum, castee.RegNum, casttype.RegNum);
return ares;
} }
//==========================================================================
//
//
//
//==========================================================================
int BuiltinTypeCheck(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
{
assert(numparam == 2);
PARAM_POINTER_AT(0, obj, DObject);
PARAM_CLASS_AT(1, cls, DObject);
ACTION_RETURN_BOOL(obj && obj->IsKindOf(cls));
}
//==========================================================================
//
//
//
//==========================================================================
ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build)
{ {
EmitParameter(build, left, ScriptPosition); ExpEmit ares = EmitCommon(build);
EmitParameter(build, right, ScriptPosition); ares.Free(build);
ExpEmit bres(build, REGT_INT);
build->Emit(OP_CASTB, bres.RegNum, ares.RegNum, CASTB_A);
return bres;
}
void FxTypeCheck::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); {
ExpEmit ares = EmitCommon(build);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); ares.Free(build);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); build->Emit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT));
auto callfunc = ((PSymbolVMFunction *)sym)->Function; patchspots_no.Push(build->Emit(OP_JMP, 0));
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
if (EmitTail)
{
ExpEmit call;
call.Final = true;
return call;
}
ExpEmit out(build, REGT_INT);
build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum);
return out;
} }
//========================================================================== //==========================================================================
@ -4443,27 +4417,11 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx)
ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build)
{ {
ExpEmit in = expr->Emit(build); ExpEmit castee = expr->Emit(build);
ExpEmit out = in.Fixed ? ExpEmit(build, in.RegType) : in; castee.Free(build);
ExpEmit check(build, REGT_INT); ExpEmit ares(build, REGT_POINTER);
assert(out.RegType == REGT_POINTER); build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType, ATAG_OBJECT));
return ares;
if (in.Fixed) build->Emit(OP_MOVEA, out.RegNum, in.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER, in.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(CastType, ATAG_OBJECT));
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
build->Emit(OP_RESULT, 0, REGT_INT, check.RegNum);
build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(0));
auto patch = build->Emit(OP_JMP, 0);
build->Emit(OP_LKP, out.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT));
build->BackpatchToHere(patch);
return out;
} }
//========================================================================== //==========================================================================
@ -9586,8 +9544,7 @@ int BuiltinNameToClass(VMValue *param, TArray<VMValue> &defaultparam, int numpar
if (!cls->IsDescendantOf(desttype)) if (!cls->IsDescendantOf(desttype))
{ {
// Let the caller check this. The message can be enabled for diagnostic purposes. // Let the caller check this. Making this an error with a message is only taking away options from the user.
DPrintf(DMSG_SPAMMY, "class '%s' is not compatible with '%s'\n", clsname.GetChars(), desttype->TypeName.GetChars());
cls = nullptr; cls = nullptr;
} }
ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT); ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT);
@ -9964,17 +9921,43 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx)
delete this; delete this;
return nullptr; return nullptr;
} }
if (ValueType->RegType == REGT_NIL) if (ValueType->RegType == REGT_NIL && ValueType != TypeAuto)
{ {
auto sfunc = static_cast<VMScriptFunction *>(ctx.Function->Variants[0].Implementation); auto sfunc = static_cast<VMScriptFunction *>(ctx.Function->Variants[0].Implementation);
StackOffset = sfunc->AllocExtraStack(ValueType); StackOffset = sfunc->AllocExtraStack(ValueType);
// Todo: Process the compound initializer once implemented. // Todo: Process the compound initializer once implemented.
if (Init != nullptr)
{
ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars());
delete this;
return nullptr;
}
} }
else else if (ValueType !=TypeAuto)
{ {
if (Init) Init = new FxTypeCast(Init, ValueType, false); if (Init) Init = new FxTypeCast(Init, ValueType, false);
SAFE_RESOLVE_OPT(Init, ctx); SAFE_RESOLVE_OPT(Init, ctx);
} }
else
{
if (Init == nullptr)
{
ScriptPosition.Message(MSG_ERROR, "Automatic type deduction requires an initializer for variable %s", Name.GetChars());
delete this;
return nullptr;
}
SAFE_RESOLVE_OPT(Init, ctx);
if (Init->ValueType->RegType == REGT_NIL)
{
ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars());
delete this;
return nullptr;
}
ValueType = Init->ValueType;
// check for undersized ints and floats. These are not allowed as local variables.
if (IsInteger() && ValueType->Align < sizeof(int)) ValueType = TypeSInt32;
else if (IsFloat() && ValueType->Align < sizeof(double)) ValueType = TypeFloat64;
}
if (Name != NAME_None) if (Name != NAME_None)
{ {
for (auto l : ctx.Block->LocalVars) for (auto l : ctx.Block->LocalVars)

View file

@ -1078,9 +1078,10 @@ public:
FxTypeCheck(FxExpression*, FxExpression*); FxTypeCheck(FxExpression*, FxExpression*);
~FxTypeCheck(); ~FxTypeCheck();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
PPrototype *ReturnProto();
ExpEmit EmitCommon(VMFunctionBuilder *build);
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
}; };
//========================================================================== //==========================================================================

View file

@ -414,6 +414,18 @@ begin:
reg.f[a+1] = reg.f[B+1]; reg.f[a+1] = reg.f[B+1];
reg.f[a+2] = reg.f[B+2]; reg.f[a+2] = reg.f[B+2];
NEXTOP; NEXTOP;
OP(DYNCAST_R) :
ASSERTA(a); ASSERTA(B); ASSERTA(C);
b = B;
reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(DYNCAST_K) :
ASSERTA(a); ASSERTA(B); ASSERTKA(C);
b = B;
reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(CAST): OP(CAST):
if (C == CAST_I2F) if (C == CAST_I2F)
{ {

View file

@ -84,6 +84,8 @@ xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements)
xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements) xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements)
xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C
xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C
xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0), // aA = dyn_cast<aC>(aB);
xx(DYNCAST_K, dyncast, RPRPKP, NOP, 0, 0), // aA = dyn_cast<aKC>(aB);
// Control flow. // Control flow.
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++ xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++

View file

@ -704,6 +704,7 @@ type_name1(X) ::= NAME(T). { X.Int = ZCC_Name; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= SOUND(T). { X.Int = ZCC_Sound; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= SOUND(T). { X.Int = ZCC_Sound; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= STATE(T). { X.Int = ZCC_State; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= STATE(T). { X.Int = ZCC_State; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= COLOR(T). { X.Int = ZCC_Color; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= COLOR(T). { X.Int = ZCC_Color; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= LET(T). { X.Int = ZCC_Let; X.SourceLoc = T.SourceLoc; }
type_name(X) ::= type_name1(A). type_name(X) ::= type_name1(A).
{ {

View file

@ -1449,6 +1449,10 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
retval = TypeSound; retval = TypeSound;
break; break;
case ZCC_Let:
retval = TypeAuto;
break;
case ZCC_UserType: case ZCC_UserType:
// statelabel et.al. are not tokens - there really is no need to, it works just as well as an identifier. Maybe the same should be done for some other types, too? // statelabel et.al. are not tokens - there really is no need to, it works just as well as an identifier. Maybe the same should be done for some other types, too?
switch (btype->UserType->Id) switch (btype->UserType->Id)

View file

@ -201,6 +201,7 @@ static void InitTokenMap()
TOKENDEF2(TK_State, ZCC_STATE, NAME_State); TOKENDEF2(TK_State, ZCC_STATE, NAME_State);
TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color); TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color);
TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound); TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound);
TOKENDEF2(TK_Let, ZCC_LET, NAME_let);
TOKENDEF (TK_Identifier, ZCC_IDENTIFIER); TOKENDEF (TK_Identifier, ZCC_IDENTIFIER);
TOKENDEF (TK_StringConst, ZCC_STRCONST); TOKENDEF (TK_StringConst, ZCC_STRCONST);

View file

@ -131,6 +131,7 @@ enum EZCCBuiltinType
ZCC_Sound, ZCC_Sound,
ZCC_UserType, ZCC_UserType,
ZCC_Let,
ZCC_NUM_BUILT_IN_TYPES ZCC_NUM_BUILT_IN_TYPES
}; };

View file

@ -863,66 +863,34 @@ void FString::Insert (size_t index, const char *instr, size_t instrlen)
void FString::ReplaceChars (char oldchar, char newchar) void FString::ReplaceChars (char oldchar, char newchar)
{ {
size_t i, j; if (oldchar == '\0')
return;
LockBuffer(); ReplaceChars([&oldchar](char c){ return c == oldchar; }, newchar);
for (i = 0, j = Len(); i < j; ++i)
{
if (Chars[i] == oldchar)
{
Chars[i] = newchar;
}
}
UnlockBuffer();
} }
void FString::ReplaceChars (const char *oldcharset, char newchar) void FString::ReplaceChars (const char *oldcharset, char newchar)
{ {
size_t i, j; if (oldcharset == NULL || oldcharset[0] == '\0')
return;
LockBuffer(); ReplaceChars([&oldcharset](char c){ return strchr(oldcharset, c) != NULL; }, newchar);
for (i = 0, j = Len(); i < j; ++i)
{
if (strchr (oldcharset, Chars[i]) != NULL)
{
Chars[i] = newchar;
}
}
UnlockBuffer();
} }
void FString::StripChars (char killchar) void FString::StripChars (char killchar)
{ {
size_t read, write, mylen; if (killchar == '\0')
return;
LockBuffer(); StripChars([&killchar](char c){ return c == killchar; });
for (read = write = 0, mylen = Len(); read < mylen; ++read)
{
if (Chars[read] != killchar)
{
Chars[write++] = Chars[read];
}
}
Chars[write] = '\0';
ReallocBuffer (write);
UnlockBuffer();
} }
void FString::StripChars (const char *killchars) void FString::StripChars (const char *killcharset)
{ {
size_t read, write, mylen; if (killcharset == NULL || killcharset[0] == '\0')
return;
LockBuffer(); StripChars([&killcharset](char c){ return strchr(killcharset, c) != NULL; });
for (read = write = 0, mylen = Len(); read < mylen; ++read)
{
if (strchr (killchars, Chars[read]) == NULL)
{
Chars[write++] = Chars[read];
}
}
Chars[write] = '\0';
ReallocBuffer (write);
UnlockBuffer();
} }
void FString::MergeChars (char merger) void FString::MergeChars (char merger)

View file

@ -236,11 +236,45 @@ public:
void Insert (size_t index, const char *instr); void Insert (size_t index, const char *instr);
void Insert (size_t index, const char *instr, size_t instrlen); void Insert (size_t index, const char *instr, size_t instrlen);
template<typename Func>
void ReplaceChars (Func IsOldChar, char newchar)
{
size_t i, j;
LockBuffer();
for (i = 0, j = Len(); i < j; ++i)
{
if (IsOldChar(Chars[i]))
{
Chars[i] = newchar;
}
}
UnlockBuffer();
}
void ReplaceChars (char oldchar, char newchar); void ReplaceChars (char oldchar, char newchar);
void ReplaceChars (const char *oldcharset, char newchar); void ReplaceChars (const char *oldcharset, char newchar);
template<typename Func>
void StripChars (Func IsKillChar)
{
size_t read, write, mylen;
LockBuffer();
for (read = write = 0, mylen = Len(); read < mylen; ++read)
{
if (!IsKillChar(Chars[read]))
{
Chars[write++] = Chars[read];
}
}
Chars[write] = '\0';
ReallocBuffer (write);
UnlockBuffer();
}
void StripChars (char killchar); void StripChars (char killchar);
void StripChars (const char *killchars); void StripChars (const char *killcharset);
void MergeChars (char merger); void MergeChars (char merger);
void MergeChars (char merger, char newchar); void MergeChars (char merger, char newchar);

View file

@ -268,6 +268,7 @@ class Actor : Thinker native
virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0);
virtual native bool Slam(Actor victim); virtual native bool Slam(Actor victim);
virtual native void Touch(Actor toucher); virtual native void Touch(Actor toucher);
virtual native bool CanCollideWith(Actor other, bool passive); // This is an empty native function, it's native for the sole reason of performance as this is in a performance critical spot.
// Called when an actor is to be reflected by a disc of repulsion. // Called when an actor is to be reflected by a disc of repulsion.
// Returns true to continue normal blast processing. // Returns true to continue normal blast processing.

View file

@ -846,6 +846,7 @@ struct FTranslatedLineTarget
{ {
Actor linetarget; Actor linetarget;
double angleFromSource; double angleFromSource;
double attackAngleFromSource;
bool unlinked; // found by a trace that went through an unlinked portal. bool unlinked; // found by a trace that went through an unlinked portal.
native void TraceBleed(int damage, Actor missile); native void TraceBleed(int damage, Actor missile);

View file

@ -193,7 +193,7 @@ extend class Actor
if (sv_killbossmonst) if (sv_killbossmonst)
{ {
int count; // Repeat until we have no more boss-spawned monsters. int count; // Repeat until we have no more boss-spawned monsters.
ThinkerIterator it = ThinkerIterator.Create(); ThinkerIterator it = ThinkerIterator.Create("Actor");
do // (e.g. Pain Elementals can spawn more to kill upon death.) do // (e.g. Pain Elementals can spawn more to kill upon death.)
{ {
Actor mo; Actor mo;

View file

@ -148,14 +148,14 @@ extend class StateProvider
if (anglediff < 0.0) if (anglediff < 0.0)
{ {
if (anglediff < -4.5) if (anglediff < -4.5)
angle = ang + 90.0 / 21; angle = t.angleFromSource + 90.0 / 21;
else else
angle -= 4.5; angle -= 4.5;
} }
else else
{ {
if (anglediff > 4.5) if (anglediff > 4.5)
angle = ang - 90.0 / 21; angle = t.angleFromSource - 90.0 / 21;
else else
angle += 4.5; angle += 4.5;
} }

View file

@ -40,11 +40,7 @@ extend class Actor
void AdjustPlayerAngle(FTranslatedLineTarget t) void AdjustPlayerAngle(FTranslatedLineTarget t)
{ {
// normally this will adjust relative to the actual direction to the target, double difference = t.angleFromSource;
// but with arbitrary portals that cannot be calculated so using the actual
// attack angle is the only option.
double atkangle = t.unlinked ? t.angleFromSource : AngleTo(t.linetarget);
double difference = deltaangle(Angle, atkangle);
if (abs(difference) > MAX_ANGLE_ADJUST) if (abs(difference) > MAX_ANGLE_ADJUST)
{ {
if (difference > 0) if (difference > 0)

View file

@ -253,7 +253,7 @@ class FWeapAxe : FighterWeapon
{ {
if (t.linetarget.bIsMonster || t.linetarget.player) if (t.linetarget.bIsMonster || t.linetarget.player)
{ {
t.linetarget.Thrust(power, t.angleFromSource); t.linetarget.Thrust(power, t.attackAngleFromSource);
} }
AdjustPlayerAngle(t); AdjustPlayerAngle(t);

View file

@ -77,7 +77,7 @@ class FWeapFist : FighterWeapon
(t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster))) (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster)))
{ {
if (!t.linetarget.bDontThrust) if (!t.linetarget.bDontThrust)
t.linetarget.Thrust(power, t.angleFromSource); t.linetarget.Thrust(power, t.attackAngleFromSource);
} }
AdjustPlayerAngle(t); AdjustPlayerAngle(t);
return true; return true;

View file

@ -80,7 +80,7 @@ class FWeapHammer : FighterWeapon
AdjustPlayerAngle(t); AdjustPlayerAngle(t);
if (t.linetarget.bIsMonster || t.linetarget.player) if (t.linetarget.bIsMonster || t.linetarget.player)
{ {
t.linetarget.Thrust(10, t.angleFromSource); t.linetarget.Thrust(10, t.attackAngleFromSource);
} }
weaponspecial = false; // Don't throw a hammer weaponspecial = false; // Don't throw a hammer
return; return;

View file

@ -388,7 +388,7 @@ class Minotaur : Actor
// In case pain caused him to skip his fade in. // In case pain caused him to skip his fade in.
A_SetRenderStyle(1, STYLE_Normal); A_SetRenderStyle(1, STYLE_Normal);
MinotaurFriend mf = MinotaurFriend(self); let mf = MinotaurFriend(self);
if (mf) if (mf)
{ {
if (mf.StartTime >= 0 && (level.maptime - mf.StartTime) >= MAULATORTICS) if (mf.StartTime >= 0 && (level.maptime - mf.StartTime) >= MAULATORTICS)
@ -501,7 +501,7 @@ class Minotaur : Actor
void A_MinotaurChase() void A_MinotaurChase()
{ {
MinotaurFriend mf = MinotaurFriend(self); let mf = MinotaurFriend(self);
if (!mf) if (!mf)
{ {
A_Chase(); A_Chase();