📄 windows.asm
字号:
.and_draw_outside_2:
.intersect_or_entry:
mov cl,[Win_Count+edx]
test cl,cl
jz .or_copy_win2
mov ch,[Win_Count+esi]
test ch,ch
jz .or_copy_win1
.or_win1_loop:
; start with leftmost window bands
mov al,[edx+Win_Bands]
mov bl,[esi+Win_Bands]
cmp al,bl
jbe .or_no_swap
rol cx,8
mov ebx,edx
mov edx,esi
mov esi,ebx
.or_no_swap:
mov ax,[edx+Win_Bands]
.or_win2_loop:
mov bx,[esi+Win_Bands]
; compare window 2 left edge against window 1 right edge
test ah,ah
jz .or_win1right_edge
cmp bl,ah ;win2left, win1right
ja .or_no_intersect
.or_win1right_edge:
dec ah
dec bh
cmp ah,bh
ja .or_max_right
mov ah,bh
.or_max_right:
inc ah
add esi,byte 2
dec ch
jnz .or_win2_loop
.or_no_intersect:
dec cl
jz .or_last_band
mov bx,[edx+Win_Bands+2]
add edx,byte 2
; compare next band left edge against accumulated band right edge
test ah,ah
jz .or_win1right_edge2
cmp bl,ah ;win2left, win1right
ja .or_no_intersect2
.or_win1right_edge2:
dec ah
dec bh
cmp ah,bh
ja .or_max_right2
mov ah,bh
.or_max_right2:
inc ah
test ch,ch
jnz .or_win2_loop
jmp .or_no_intersect
.or_no_intersect2:
mov [edi+ebp*2+Win_Bands],al
mov [edi+ebp*2+Win_Bands+1],ah
inc ebp
test ch,ch
jnz .or_win1_loop
mov ax,bx
jmp .or_no_intersect
.or_last_band:
mov [edi+ebp*2+Win_Bands],ax
inc ebp
.or_copy_win2:
mov cl,ch
mov edx,esi
.or_copy_win1:
test cl,cl
jz .or_done
.or_copy_another:
mov ax,[edx+Win_Bands]
add edx,byte 2
mov [edi+ebp*2+Win_Bands],ax
inc ebp
dec cl
jnz .or_copy_another
.or_done:
mov eax,ebp
mov [edi+Win_Count],al
ret
;if we're doing xor, we flip the inversion of one of the windows
.intersect_xor_check:
;fixup for xor/xnor
and ah,1
xor al,ah
.intersect_xor_setup:
add edi,esi
LOAD_WIN_TABLE 1
LOAD_WIN_TABLE 2,esi
; we want drawn areas, not window areas, so we need the inverted results...
test al,1
jnz .xor_draw_outside_1
add edx,byte Win_In - Win_Out
.xor_draw_outside_1:
test al,4
jz .xor_draw_outside_2
add esi,byte Win_In - Win_Out
.xor_draw_outside_2:
.intersect_xor_entry:
EXTERN_C xor_bands
mov cl,[Win_Count+edx]
mov ch,[Win_Count+esi]
%if Win_Bands
add edx,Win_Bands
add esi,Win_Bands
%endif
push edi
xor eax,eax
add edi,byte Win_Bands
mov al,ch
and ecx,byte 0x7F
push edi
push eax
push ecx
push esi
push edx
call C_LABEL(xor_bands)
mov edi,[esp+20]
add esp,byte 24
mov [edi+Win_Count],al
ret
EXPORT_EQU_C Intersect_Window_Area_AND,C_LABEL(Recalc_Window_Area_BG).intersect_and_entry
EXPORT_EQU_C Intersect_Window_Area_OR,C_LABEL(Recalc_Window_Area_BG).intersect_or_entry
EXPORT_EQU_C Intersect_Window_Area_XOR,C_LABEL(Recalc_Window_Area_BG).intersect_xor_entry
ALIGNC
EXPORT_C Recalc_Window_Effects
push eax
push ecx
push edx
push ebx
push ebp
push esi
push edi
test byte [Redo_Windowing],Redo_Win(1)
jz .win1_ok
Recalc_Single_Window C_LABEL(WH0), C_LABEL(WH1), 1
.win1_ok:
test byte [Redo_Windowing],Redo_Win(2)
jz .win2_ok
Recalc_Single_Window C_LABEL(WH2), C_LABEL(WH3), 2
.win2_ok:
mov al,[Redo_Windowing]
and al,[Layers_In_Use]
push eax
test al,Redo_Win_BG(1)
jz .bg1_ok
Recalc_Window_BG_Main 1
Recalc_Window_BG_Sub 1
.bg1_ok:
mov al,[esp]
test al,Redo_Win_BG(2)
jz .bg2_ok
Recalc_Window_BG_Main 2
Recalc_Window_BG_Sub 2
.bg2_ok:
mov al,[esp]
test al,Redo_Win_BG(3)
jz .bg3_ok
Recalc_Window_BG_Main 3
Recalc_Window_BG_Sub 3
.bg3_ok:
mov al,[esp]
test al,Redo_Win_BG(4)
jz .bg4_ok
Recalc_Window_BG_Main 4
Recalc_Window_BG_Sub 4
.bg4_ok:
mov al,[Layers_In_Use]
xor al,0xFF
and al,[Redo_Windowing]
and al,~(Redo_Win(1) | Redo_Win(2))
mov [Redo_Windowing],al
pop eax
pop edi
pop esi
pop ebp
pop ebx
pop edx
pop ecx
pop eax
ret
; max output bands is 1 more than max input bands; only in case where
;neither outermost band edges are at screen edge
EXPORT_C Invert_Window_Bands
;esi = base address for input bands; first byte is count
;edi = base address for output bands; first byte is count
;edx = count of bands output (count up)
;ecx = count of bands input (count down)
xor ecx,ecx
xor edx,edx ;current output
mov cl,[esi]
test ecx,ecx
jnz .no_bands
xor eax,eax
mov ah,[esi+1]
test ah,ah
jz .no_left_edge_band
mov [edi+1],eax ;00 xx
inc edx
.no_left_edge_band:
dec ecx
jz .last_band
.next_band:
mov ax,[esi+2]
mov [edi+edx*2+1],ax
add esi,2
inc edx
dec ecx
jnz .next_band
.last_band:
mov cl,[esi+2]
test cl,cl
jz .no_more_bands
mov [edi+edx*2+1],cx ;xx 00
inc edx
.no_more_bands:
mov [edi],dl
ret
.no_bands:
mov dword [edi],1 ;01 00 00 - 1 band, full area
ret
; windows:
%if 0
There are 5 basic window types for purposes of calculating
intersections:
1) full area (no invert: left = 0, right = 255; invert: left > right);
2) no area (no invert: left > right; invert: left = 0, right = 255);
3) flush to left side (no invert: left = 0, right < 255;
invert: left > 0, right = 255);
4) flush to right side (no invert: left > 0, right = 255;
invert: left = 0, right < 255);
5) flush to neither side (no invert: left > 0, right < 255);
6) two runs, flush to either side (invert: left > 0, right < 255).
Intersections can produce the following in addition:
7) two runs: one flush to left side, one flush to neither side;
8) two runs: one flush to right side, one flush to neither side;
9) two runs, flush to neither side;
10) three runs: two flush to either side, one in center.
Types 1 and 2 are the easiest to intersect.
1) result of OR is full area;
result of AND is other window;
result of XOR is other window inverted;
result of XNOR is other window.
2) result of OR is other window;
result of AND is no area;
result of XOR is other window;
result of XNOR is other window inverted.
TMW/TSW clipping is only done inside window areas defined by
WH0-WH1 (window 1) and WH2-WH3 (window 2), when enabled
(W12SEL/W34SEL/WOBJSEL odd bits).
Window areas can be inverted (W12SEL/W34SEL/WOBJSEL even bits).
When specified areas of windows 1/2 overlap, final window area is determined
by specified logic (WBGLOG/WOBJLOG).
Color arithmetic is done inside the area of the color window.
w2 w1
/\/\ /--+ enable
|||| |/-+ invert window area
76543210
\ /\ /
BG2 BG1 - ($2123) W12SEL
BG4 BG3 - ($2124) W34SEL
COL OBJ - ($2125) WOBJSEL
COL = Color window - related to CGWSEL ($2130)
WH0-WH1 Left and right position for window 1
WH2-WH3 Left and right position for window 2
if (left > right) no window range
/+-+ logic - 00 = or; 01 = and; 10 = xor; 11 = xnor
||
76543210
\/||||\/
BG4||||BG1 ($212A: WBGLOG)
\/\/OBJ ($212B: WOBJLOG)
BG3 BG2 ($212A: WBGLOG)
COL ($212B: WOBJLOG)
bits 4-7 are ignored in $212B: WOBJLOG
bits 5-7 are ignored in $212C-212F (TM, TS, TMW, TSW)
76543210
xxx||||\-+ BG1
|||\--+ BG2
||\---+ BG3
|\----+ BG4
\-----+ OBJ
($212C) TM specifies layers to be used as main screen
($212D) TS specifics layers to be used as sub screen, for screen arithmetic
($212E) TMW is mask to be inverted and applied with bitwise AND to TM
inside window areas
($212F) TSW is mask to be inverted and applied with bitwise AND to TS
inside window areas
$2130 - CGWSEL
76543210
||||xx|\-+ 1 = enable direct color mode (for BGMODEs 3,4,7)
|||| \--+ 0 = arithmetic with fixed color; 1 = arithmetic with screen
||\+-----+ sub screen normal display select \ 00 = on; 01 = on inside
\+-------+ main screen normal display select/ 10 = on outside; 11 = off
$2131 - CGADSUB
76543210
|||||||\-+ enable color arithmetic for BG1
||||||\--+ enable color arithmetic for BG2
|||||\---+ enable color arithmetic for BG3
||||\----+ enable color arithmetic for BG4
|||\-----+ enable color arithmetic for OBJ
||\------+ enable color arithmetic for back area
|\-------+ 1 = halve-result of arithmetic (except for back area)
\--------+ 0 = color addition; 1 = color subtraction
%endif
section .text
ALIGNC
section .data
ALIGND
section .bss
ALIGNB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -