[Decompilation] [th01] Restorable line drawing

Yes, when clipping the start and end points to the screen area, ZUN
uses an integer division to calculate the line slopes, rather than a
floating-point one. Doesn't seem like it actually causes any incorrect
lines to be drawn, though; that case is only hit in the Mima boss
fight, which draws a few lines with a bottom coordinate of 400 rather
than 399. It *might* also restore the wrong pixels at parts of the
YuugenMagan fight, causing weird flickering, but seriously, that's an
issue everywhere you look in this game.

Part of P0069, funded by [Anonymous] and Yanga.
This commit is contained in:
nmlgc 2020-01-12 19:13:26 +01:00
parent b5cef6eb69
commit b0c832bdee
9 changed files with 249 additions and 883 deletions

View File

@ -42,17 +42,17 @@ bin\th01\zunsoft.com: th01\zunsoft.c
$(CC) $(CFLAGS) -mt -lt -nbin\th01\ $** masters.lib
bin\th01\op.exe: bin\th01\op.obj th01\op_02.c th01\op_03.c th01\op_04.c th01\op_06.cpp th01\op_08.c th01\op_10.c th01\op_11.c th01\op_12.cpp
$(CC) $(CFLAGS) -ml -3 -nbin\th01\ -eOP.EXE @&&|
$(CC) $(CFLAGS) -ml -3 -DGAME=1 -nbin\th01\ -eOP.EXE @&&|
$**
|
bin\th01\reiiden.exe: bin\th01\reiiden.obj th01\main_02.c th01\main_03.c th01\main_04.c th01\main_06.cpp th01\main_12.c th01\main_13.c th01\main_14.c th01\main_16.c
$(CC) $(CFLAGS) -ml -3 -nbin\th01\ -eREIIDEN.EXE @&&|
$(CC) $(CFLAGS) -ml -3 -DGAME=1 -nbin\th01\ -eREIIDEN.EXE @&&|
$**
|
bin\th01\fuuin.exe: bin\th01\fuuin.obj th01\fuuin_05.c th01\fuuin_06.c th01\fuuin_08.cpp th01\fuuin_09.c th01\fuuin_11.c th01\fuuin_12.c th01\fuuin_13.c
$(CC) $(CFLAGS) -ml -3 -nbin\th01\ -eFUUIN.EXE @&&|
$(CC) $(CFLAGS) -ml -3 -DGAME=1 -nbin\th01\ -eFUUIN.EXE @&&|
$**
|

View File

@ -95,6 +95,10 @@ typedef struct {
planar16_t B, R, G, E;
} vram_planar_16_pixels_t;
typedef struct {
planar32_t B, R, G, E;
} vram_planar_32_pixels_t;
// Since array subscripts create slightly different assembly in places, we
// offer both variants.
extern planar8_t *VRAM_PLANE[PL_COUNT];

View File

@ -1,3 +1,5 @@
#include "defconv.h"
// Blits the rectangle from (⌊x/16⌋*16, y) to (⌈((x + w)/16)*16⌉, (y + h))
// from VRAM page 1 to the same position on VRAM page 0.
void pascal egc_copy_rect_1_to_0(int x, int y, int w, int h);
void DEFCONV egc_copy_rect_1_to_0(int x, int y, int w, int h);

View File

@ -5,6 +5,7 @@ extern "C" {
#include <mbctype.h>
#include <mbstring.h>
#include "ReC98.h"
#include "th01/hardware/egc.h"
#include "th01/hardware/vsync.h"
#include "th01/hardware/graph.h"
#include "th01/hardware/palette.hpp"
@ -88,6 +89,12 @@ extern "C" {
push cs; \
call near ptr grcg_off_func; \
}
#define GRAPH_ACCESSPAGE_FUNC(page, stack_clear_size) __asm { \
push page; \
push cs; \
call near ptr graph_accesspage_func; \
} \
_SP += stack_clear_size;
/// -----------------------------------------------
/// Pages
@ -105,6 +112,226 @@ extern Point graph_r_last_line_end;
extern bool graph_r_restore_from_1;
// Not used for purely horizontal lines.
extern planar16_t graph_r_pattern;
void graph_r_hline(int left, int right, int y, int col)
{
int full_bytes_to_put;
int order_tmp;
planar8_t left_pixels;
planar8_t right_pixels;
planar8_t *vram_row;
fix_order(left, right);
clip_x(left, right);
graph_r_last_line_end.x = right;
graph_r_last_line_end.y = y;
vram_row = (planar8_t *)(MK_FP(GRAM_400, (y * ROW_SIZE) + (left / 8)));
full_bytes_to_put = (right / 8) - (left / 8);
left_pixels = 0xFF >> (left & 7);
right_pixels = 0xFF << (7 - (right & 7));
if(!graph_r_restore_from_1) {
GRCG_SETCOLOR_RMW(col);
}
if(graph_r_restore_from_1) {
egc_copy_rect_1_to_0(left, y, RES_X - left, 1);
} else {
if(full_bytes_to_put == 0) {
vram_row[0] = (left_pixels & right_pixels);
} else {
vram_row[0] = left_pixels;
for(register int x = 1; x < full_bytes_to_put; x++) {
vram_row[x] = 0xFF;
}
vram_row[full_bytes_to_put] = right_pixels;
}
}
if(!graph_r_restore_from_1) {
GRCG_OFF();
}
}
void graph_r_vline(int x, int top, int bottom, int col)
{
int y;
int order_tmp;
planar16_t pattern;
int vram_row_offset;
fix_order(top, bottom);
clip_y(top, bottom);
graph_r_last_line_end.x = x;
graph_r_last_line_end.y = bottom;
if(graph_r_restore_from_1) {
egc_copy_rect_1_to_0(x, top, sizeof(pattern) * 8, bottom - top);
return;
}
vram_row_offset = VRAM_OFFSET(x, top);
pattern = graph_r_pattern >> (x & 7);
pattern |= graph_r_pattern << (16 - (x & 7));
GRCG_SETCOLOR_RMW(col);
for(y = top; y <= bottom; y++) {
VRAM_PUT(B, vram_row_offset, pattern, 16);
vram_row_offset += ROW_SIZE;
}
GRCG_OFF();
}
void graph_r_line_from_1(int left, int top, int right, int bottom)
{
graph_r_restore_from_1 = true;
graph_r_line(left, top, right, bottom, 7);
graph_r_restore_from_1 = false;
}
void graph_r_line_patterned(
int left, int top, int right, int bottom, int col, planar16_t pattern
)
{
graph_r_pattern = pattern;
graph_r_line(left, top, right, bottom, col);
graph_r_pattern = 0x80;
}
void graph_r_line(int left, int top, int right, int bottom, int col)
{
register int vram_offset;
int i;
int x_cur, y_cur;
int w, h;
int error;
int y_direction;
int order_tmp;
int x_vram, y_vram;
planar16_t pixels;
vram_planar_32_pixels_t page1;
#define slope_x ((bottom - top) / (right - left))
#define slope_y ((right - left) / (bottom - top))
#define lerp(m, x) static_cast<int>(m * static_cast<float>(x))
#define clip_lerp_min(low, high, lerp_point, slope, minimum) \
if(low < minimum) { \
if(high < minimum) { \
return; \
} \
lerp_point += lerp(slope, (minimum - low)); \
low = minimum; \
}
#define clip_lerp_max(low, high, lerp_point, slope, maximum) \
if(high > maximum) { \
if(low > maximum) { \
return; \
} \
lerp_point -= lerp(slope, (high - maximum)); \
high = maximum; \
}
#define restore_at(bit_count) \
GRAPH_ACCESSPAGE_FUNC(1, 0); VRAM_SNAP_4(page1, vram_offset, 32); \
GRAPH_ACCESSPAGE_FUNC(0, 4); VRAM_PUT_4(vram_offset, page1, 32);
#define plot_loop(\
step_var, step_len, step_increment, \
plotted_var, plotted_len, plotted_increment \
) \
error = (step_len >> 1); \
for(i = 0; i <= step_len; i++) { \
/* Advanced past the VRAM cursor? */ \
if((x_cur >> 3) != x_vram || (y_vram != y_cur)) { \
vram_offset = (y_vram * ROW_SIZE) + x_vram; \
if(!graph_r_restore_from_1) { \
VRAM_PUT(B, vram_offset, pixels, 16); \
pixels = 0; \
} else { \
vram_offset--; \
restore_at(vram_offset); \
} \
y_vram = y_cur; \
x_vram = (x_cur >> 3); \
} \
pixels |= (graph_r_pattern >> (x_cur & 7)); \
pixels |= (graph_r_pattern << (16 - (x_cur & 7))); \
error -= plotted_len; \
step_var += step_increment; \
if(error < 0) { \
error += step_len; \
plotted_var += plotted_increment; \
} \
} \
if(graph_r_restore_from_1) { \
goto restore_last; \
} \
goto end;
if(!graph_r_restore_from_1 && (left == right)) {
graph_r_vline(left, top, bottom, col);
return;
}
if(!graph_r_restore_from_1 && (top == bottom)) {
graph_r_hline(left, right, top, col);
return;
}
if(left > right) {
order_tmp = left;
left = right;
right = order_tmp;
order_tmp = top;
top = bottom;
bottom = order_tmp;
}
clip_lerp_min(left, right, top, slope_x, 0);
clip_lerp_max(left, right, bottom, slope_x, (RES_X - 1));
clip_lerp_min(top, bottom, left, slope_y, 0);
clip_lerp_max(top, bottom, right, slope_y, (RES_Y - 1));
if(bottom < 0) {
right += lerp(slope_y, 0 - bottom);
bottom = 0;
}
if(top > (RES_Y - 1)) {
left -= lerp(slope_y, top - (RES_Y - 1));
top = (RES_Y - 1);
}
graph_r_last_line_end.x = right;
graph_r_last_line_end.y = bottom;
x_cur = left;
y_cur = top;
y_direction = (top < bottom) ? 1 : -1;
w = right - left;
h = (bottom - top) * y_direction;
pixels = 0;
x_vram = (x_cur >> 3);
y_vram = y_cur;
if(!graph_r_restore_from_1) {
GRCG_SETCOLOR_RMW(col);
}
if(w > h) {
plot_loop(x_cur, w, 1, y_cur, h, y_direction);
} else {
plot_loop(y_cur, h, y_direction, x_cur, w, 1);
}
restore_last:
vram_offset = VRAM_OFFSET(x_cur, y_cur) - 1;
restore_at(vram_offset);
end:
if(!graph_r_restore_from_1) {
GRCG_OFF();
}
#undef plot_loop
#undef restore_at
#undef clip_lerp_min
#undef clip_lerp_max
#undef slope
}
/// -----------------------
void z_grcg_boxfill(int left, int top, int right, int bottom, int col)
@ -145,41 +372,10 @@ void z_grcg_boxfill(int left, int top, int right, int bottom, int col)
void graph_r_box(int left, int top, int right, int bottom, int col)
{
/* TODO: Replace with the decompiled calls
* graph_r_hline(left, right, top, col);
* graph_r_vline(left, top, bottom, col);
* graph_r_vline(right, top, bottom, col);
* graph_r_hline(left, right, bottom, col);
* once those functions are part of this translation unit */
__asm {
mov di, left
mov si, col
push si
push top
push right
push di
push cs
call near ptr graph_r_hline
push si
push bottom
push top
push di
push cs
call near ptr graph_r_vline
push si
push bottom
push top
push right
push cs
call near ptr graph_r_vline
push si
push bottom
push right
push di
push cs
call near ptr graph_r_hline
add sp, 0x20
}
graph_r_hline(left, right, top, col);
graph_r_vline(left, top, bottom, col);
graph_r_vline(right, top, bottom, col);
graph_r_hline(left, right, bottom, col);
}
int text_extent_fx(int fx, const unsigned char *str)
@ -230,33 +426,13 @@ void graph_putsa_fx(int left, int top, int fx, const unsigned char *str)
w = text_extent_fx(fx, str);
if(underline) {
z_grcg_boxfill(left, top, (left + w - 1), (top + GLYPH_H + 1), 0);
/* TODO: Replace with the decompiled call
* graph_r_hline(left, (left + w - 1), (top + GLYPH_H + 1), 7);
* once that function is part of this translation unit */
goto graph_hline_call;
graph_r_hline(left, (left + w - 1), (top + GLYPH_H + 1), 7);
} else {
z_grcg_boxfill(left, top, (left + w - 1), (top + GLYPH_H - 1), 0);
}
} else if(underline) {
w = text_extent_fx(fx, str);
/* TODO: Replace with the decompiled call
* graph_r_hline(left, (left + w - 1), (top + GLYPH_H + 1), 7);
* once that function is part of this translation unit */
graph_hline_call:
__asm {
push 7
mov ax, top
add ax, GLYPH_H + 1
push ax
db 0x8B, 0xC6
add ax, w
dec ax
push ax
db 0x56
push cs
call near ptr graph_r_hline
add sp, 8
}
graph_r_hline(left, (left + w - 1), (top + GLYPH_H + 1), 7);
}
GRCG_SETCOLOR_RMW(fx);

View File

@ -1,816 +0,0 @@
public _graph_r_hline
_graph_r_hline proc far
@@vram_row = dword ptr -0Ah
@@right_pixels = byte ptr -6
@@left_pixels = byte ptr -5
@@order_tmp = word ptr -4
@@full_bytes_to_put = word ptr -2
@@left = word ptr 6
@@right = word ptr 8
@@y = word ptr 0Ah
@@col = word ptr 0Ch
enter 0Ah, 0
push si
push di
mov di, [bp+@@y]
mov ax, [bp+@@left]
cmp ax, [bp+@@right]
jle short @@clip_left?
mov [bp+@@order_tmp], ax
mov ax, [bp+@@right]
mov [bp+@@left], ax
mov ax, [bp+@@order_tmp]
mov [bp+@@right], ax
@@clip_left?:
cmp [bp+@@left], 0
jge short @@clip_right?
cmp [bp+@@right], 0
jl @@ret
mov [bp+@@left], 0
@@clip_right?:
cmp [bp+@@right], (RES_X - 1)
jle short @@setup_vram_pointer_and_edges
cmp [bp+@@left], (RES_X - 1)
jg @@ret
mov [bp+@@right], (RES_X - 1)
@@setup_vram_pointer_and_edges:
mov ax, [bp+@@right]
mov _graph_r_last_line_end.x, ax
mov _graph_r_last_line_end.y, di
mov ax, di
imul ax, ROW_SIZE
push ax
mov ax, [bp+@@left]
mov bx, 8
cwd
idiv bx
pop dx
add dx, ax
mov word ptr [bp+@@vram_row+2], 0A800h
mov word ptr [bp+@@vram_row], dx
mov ax, [bp+@@right]
cwd
idiv bx
push ax
mov ax, [bp+@@left]
cwd
idiv bx
pop dx
sub dx, ax
mov [bp+@@full_bytes_to_put], dx
mov cl, byte ptr [bp+@@left]
and cl, 7
mov ax, 0FFh
sar ax, cl
mov [bp+@@left_pixels], al
mov al, byte ptr [bp+@@right]
and al, 7
mov cl, 7
sub cl, al
mov al, 0FFh
shl al, cl
mov [bp+@@right_pixels], al
cmp _graph_r_restore_from_1, 0
jnz short @@restore?
push [bp+@@col]
call _grcg_setcolor_rmw
pop cx
@@restore?:
cmp _graph_r_restore_from_1, 0
jz short @@put
push 1
mov ax, RES_X
sub ax, [bp+@@left]
push ax
push di
push [bp+@@left]
call _egc_copy_rect_1_to_0
add sp, 8
jmp short @@grcg_off?
; ---------------------------------------------------------------------------
@@put:
cmp [bp+@@full_bytes_to_put], 0
jnz short @@at_least_one_full_byte
mov al, [bp+@@left_pixels]
and al, [bp+@@right_pixels]
les bx, [bp+@@vram_row]
assume es:nothing
jmp short @@put_edge
; ---------------------------------------------------------------------------
@@at_least_one_full_byte:
les bx, [bp+@@vram_row]
mov al, [bp+@@left_pixels]
mov es:[bx], al
mov si, 1
jmp short @@xloop_more?
; ---------------------------------------------------------------------------
@@xloop:
les bx, [bp+@@vram_row]
add bx, si
mov byte ptr es:[bx], 0FFh
inc si
@@xloop_more?:
cmp si, [bp+@@full_bytes_to_put]
jl short @@xloop
les bx, [bp+@@vram_row]
add bx, [bp+@@full_bytes_to_put]
mov al, [bp+@@right_pixels]
@@put_edge:
mov es:[bx], al
@@grcg_off?:
cmp _graph_r_restore_from_1, 0
jnz short @@ret
call _grcg_off_func
@@ret:
pop di
pop si
leave
retf
_graph_r_hline endp
public _graph_r_vline
_graph_r_vline proc far
@@vram_row_offset = word ptr -8
@@pattern = word ptr -6
@@order_tmp = word ptr -4
@@y = word ptr -2
@@x = word ptr 6
@@top = word ptr 8
@@bottom = word ptr 0Ah
@@col = word ptr 0Ch
enter 8, 0
push si
push di
mov si, [bp+@@top]
mov di, [bp+@@bottom]
cmp si, di
jle short @@clip_top?
mov [bp+@@order_tmp], si
mov si, di
mov di, [bp+@@order_tmp]
@@clip_top?:
or si, si
jge short @@clip_bottom?
or di, di
jl @@ret
xor si, si
@@clip_bottom?:
cmp di, (RES_Y - 1)
jle short @@restore?
cmp si, (RES_Y - 1)
jg @@ret
mov di, (RES_Y - 1)
@@restore?:
mov ax, [bp+@@x]
mov _graph_r_last_line_end.x, ax
mov _graph_r_last_line_end.y, di
cmp _graph_r_restore_from_1, 0
jz short @@setup_vram_offset_and_pattern
mov ax, di
sub ax, si
push ax
push 16
push si
push [bp+@@x]
call _egc_copy_rect_1_to_0
add sp, 8
jmp short @@ret
; ---------------------------------------------------------------------------
@@setup_vram_offset_and_pattern:
mov ax, [bp+@@x]
sar ax, 3
mov dx, si
shl dx, 6
add ax, dx
mov dx, si
shl dx, 4
add ax, dx
mov [bp+@@vram_row_offset], ax
mov cl, byte ptr [bp+@@x]
and cl, 7
mov ax, _graph_r_pattern
shr ax, cl
mov [bp+@@pattern], ax
mov al, byte ptr [bp+@@x]
and al, 7
mov cl, 16
sub cl, al
mov ax, _graph_r_pattern
shl ax, cl
or [bp+@@pattern], ax
push [bp+@@col]
call _grcg_setcolor_rmw
pop cx
mov [bp+@@y], si
jmp short @@yloop_more?
; ---------------------------------------------------------------------------
@@yloop:
les bx, _VRAM_PLANE_B
add bx, [bp+@@vram_row_offset]
mov ax, [bp+@@pattern]
mov es:[bx], ax
add [bp+@@vram_row_offset], ROW_SIZE
inc [bp+@@y]
@@yloop_more?:
cmp [bp+@@y], di
jle short @@yloop
call _grcg_off_func
@@ret:
pop di
pop si
leave
retf
_graph_r_vline endp
public _graph_r_line_from_1
_graph_r_line_from_1 proc far
@@left = word ptr 6
@@top = word ptr 8
@@right = word ptr 0Ah
@@bottom = word ptr 0Ch
push bp
mov bp, sp
mov _graph_r_restore_from_1, 1
push 7
push [bp+@@bottom]
push [bp+@@right]
push [bp+@@top]
push [bp+@@left]
nopcall _graph_r_line
add sp, 0Ah
mov _graph_r_restore_from_1, 0
pop bp
retf
_graph_r_line_from_1 endp
public _graph_r_line_patterned
_graph_r_line_patterned proc far
@@left = word ptr 6
@@top = word ptr 8
@@right = word ptr 0Ah
@@bottom = word ptr 0Ch
@@col = word ptr 0Eh
@@pattern = word ptr 10h
push bp
mov bp, sp
mov ax, [bp+@@pattern]
mov _graph_r_pattern, ax
push [bp+@@col]
push [bp+@@bottom]
push [bp+@@right]
push [bp+@@top]
push [bp+@@left]
nopcall _graph_r_line
add sp, 0Ah
mov _graph_r_pattern, 80h
pop bp
retf
_graph_r_line_patterned endp
public _graph_r_line
_graph_r_line proc far
@@page1_B = dword ptr -28h
@@page1_R = dword ptr -24h
@@page1_G = dword ptr -20h
@@page1_E = dword ptr -1Ch
@@x87_tmp = word ptr -18h
@@pixels = word ptr -16h
@@y_vram = word ptr -14h
@@x_vram = word ptr -12h
@@tmp = word ptr -10h
@@y_direction = word ptr -0Eh
@@error = word ptr -0Ch
@@h = word ptr -0Ah
@@w = word ptr -8
@@y_cur = word ptr -6
@@x_cur = word ptr -4
@@i = word ptr -2
@@left = word ptr 6
@@top = word ptr 8
@@right = word ptr 0Ah
@@bottom = word ptr 0Ch
@@col = word ptr 0Eh
enter 28h, 0
push si
push di
mov di, [bp+@@top]
cmp _graph_r_restore_from_1, 0
jnz short @@horizontal_only?
mov ax, [bp+@@left]
cmp ax, [bp+@@right]
jnz short @@horizontal_only?
call _graph_r_vline stdcall, ax, di, [bp+@@bottom], [bp+@@col]
jmp short @@add_sp_and_ret
; ---------------------------------------------------------------------------
@@horizontal_only?:
cmp _graph_r_restore_from_1, 0
jnz short @@not_aligned
cmp di, [bp+@@bottom]
jnz short @@not_aligned
call _graph_r_hline stdcall, [bp+@@left], [bp+@@right], di, [bp+@@col]
@@add_sp_and_ret:
add sp, 8
jmp @@ret
; ---------------------------------------------------------------------------
@@not_aligned:
mov ax, [bp+@@left]
cmp ax, [bp+@@right]
jle short @@clip_left?
mov [bp+@@tmp], ax
mov ax, [bp+@@right]
mov [bp+@@left], ax
mov ax, [bp+@@tmp]
mov [bp+@@right], ax
mov [bp+@@tmp], di
mov di, [bp+@@bottom]
mov ax, [bp+@@tmp]
mov [bp+@@bottom], ax
@@clip_left?:
cmp [bp+@@left], 0
jge short @@clip_right?
cmp [bp+@@right], 0
jl @@ret
mov ax, [bp+@@bottom]
sub ax, di
mov bx, [bp+@@right]
sub bx, [bp+@@left]
cwd
idiv bx
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
xor ax, ax
sub ax, [bp+@@left]
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
fmulp st(1), st
call ftol@
add di, ax
mov [bp+@@left], 0
@@clip_right?:
cmp [bp+@@right], (RES_X - 1)
jle short @@clip_top?
cmp [bp+@@left], (RES_X - 1)
jg @@ret
mov ax, [bp+@@bottom]
sub ax, di
mov bx, [bp+@@right]
sub bx, [bp+@@left]
cwd
idiv bx
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
mov ax, [bp+@@right]
add ax, -(RES_X - 1)
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
fmulp st(1), st
call ftol@
sub [bp+@@bottom], ax
mov [bp+@@right], (RES_X - 1)
@@clip_top?:
or di, di
jge short @@clip_bottom?
cmp [bp+@@bottom], 0
jl @@ret
mov ax, [bp+@@right]
sub ax, [bp+@@left]
mov bx, [bp+@@bottom]
sub bx, di
cwd
idiv bx
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
xor ax, ax
sub ax, di
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
fmulp st(1), st
call ftol@
add [bp+@@left], ax
xor di, di
@@clip_bottom?:
cmp [bp+@@bottom], (RES_Y - 1)
jle short @@clip_bottom_at_top?
cmp di, (RES_Y - 1)
jg @@ret
mov ax, [bp+@@right]
sub ax, [bp+@@left]
mov bx, [bp+@@bottom]
sub bx, di
cwd
idiv bx
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
mov ax, [bp+@@bottom]
add ax, -(RES_Y - 1)
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
fmulp st(1), st
call ftol@
sub [bp+@@right], ax
mov [bp+@@bottom], (RES_Y - 1)
@@clip_bottom_at_top?:
cmp [bp+@@bottom], 0
jge short @@clip_top_at_bottom?
mov ax, [bp+@@right]
sub ax, [bp+@@left]
mov bx, [bp+@@bottom]
sub bx, di
cwd
idiv bx
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
xor ax, ax
sub ax, [bp+@@bottom]
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
fmulp st(1), st
call ftol@
add [bp+@@right], ax
mov [bp+@@bottom], 0
@@clip_top_at_bottom?:
cmp di, (RES_Y - 1)
jle short @@setup_coords
mov ax, [bp+@@right]
sub ax, [bp+@@left]
mov bx, [bp+@@bottom]
sub bx, di
cwd
idiv bx
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
lea ax, [di-(RES_Y - 1)]
mov [bp+@@x87_tmp], ax
fild [bp+@@x87_tmp]
fmulp st(1), st
call ftol@
sub [bp+@@left], ax
mov di, (RES_Y - 1)
@@setup_coords:
mov ax, [bp+@@right]
mov _graph_r_last_line_end.x, ax
mov ax, [bp+@@bottom]
mov _graph_r_last_line_end.y, ax
mov ax, [bp+@@left]
mov [bp+@@x_cur], ax
mov [bp+@@y_cur], di
cmp di, [bp+@@bottom]
jge short @@y_up
mov ax, 1
jmp short @@y_direction_set
; ---------------------------------------------------------------------------
@@y_up:
mov ax, -1
@@y_direction_set:
mov [bp+@@y_direction], ax
mov ax, [bp+@@right]
sub ax, [bp+@@left]
mov [bp+@@w], ax
mov ax, [bp+@@bottom]
sub ax, di
imul [bp+@@y_direction]
mov [bp+@@h], ax
mov [bp+@@pixels], 0
mov ax, [bp+@@x_cur]
sar ax, 3
mov [bp+@@x_vram], ax
mov ax, [bp+@@y_cur]
mov [bp+@@y_vram], ax
cmp _graph_r_restore_from_1, 0
jnz short @@select_loop
push [bp+@@col]
call _grcg_setcolor_rmw
pop cx
@@select_loop:
mov ax, [bp+@@w]
cmp ax, [bp+@@h]
jle @@yloop_setup
sar ax, 1
mov [bp+@@error], ax
mov [bp+@@i], 0
jmp @@xloop_more?
; ---------------------------------------------------------------------------
@@xloop:
mov ax, [bp+@@x_cur]
sar ax, 3
cmp ax, [bp+@@x_vram]
jnz short @@xloop_put
mov ax, [bp+@@y_vram]
cmp ax, [bp+@@y_cur]
jz @@xloop_advance_cur
@@xloop_put:
mov ax, [bp+@@y_vram]
imul ax, ROW_SIZE
add ax, [bp+@@x_vram]
mov si, ax
cmp _graph_r_restore_from_1, 0
jnz short @@xloop_restore
les bx, _VRAM_PLANE_B
add bx, si
mov ax, [bp+@@pixels]
mov es:[bx], ax
mov [bp+@@pixels], 0
jmp @@xloop_advance_vram
; ---------------------------------------------------------------------------
@@xloop_restore:
dec si
push 1
call _graph_accesspage_func
les bx, _VRAM_PLANE_B
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_B], eax
les bx, _VRAM_PLANE_R
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_R], eax
les bx, _VRAM_PLANE_G
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_G], eax
les bx, _VRAM_PLANE_E
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_E], eax
push 0
call _graph_accesspage_func
add sp, 4
les bx, _VRAM_PLANE_B
add bx, si
mov eax, [bp+@@page1_B]
mov es:[bx], eax
les bx, _VRAM_PLANE_R
add bx, si
mov eax, [bp+@@page1_R]
mov es:[bx], eax
les bx, _VRAM_PLANE_G
add bx, si
mov eax, [bp+@@page1_G]
mov es:[bx], eax
les bx, _VRAM_PLANE_E
add bx, si
mov eax, [bp+@@page1_E]
mov es:[bx], eax
@@xloop_advance_vram:
mov ax, [bp+@@y_cur]
mov [bp+@@y_vram], ax
mov ax, [bp+@@x_cur]
sar ax, 3
mov [bp+@@x_vram], ax
@@xloop_advance_cur:
mov cl, byte ptr [bp+@@x_cur]
and cl, 7
mov ax, _graph_r_pattern
shr ax, cl
or [bp+@@pixels], ax
mov al, byte ptr [bp+@@x_cur]
and al, 7
mov cl, 16
sub cl, al
mov ax, _graph_r_pattern
shl ax, cl
or [bp+@@pixels], ax
mov ax, [bp+@@h]
sub [bp+@@error], ax
inc [bp+@@x_cur]
cmp [bp+@@error], 0
jge short @@xloop_next
mov ax, [bp+@@w]
add [bp+@@error], ax
mov ax, [bp+@@y_direction]
add [bp+@@y_cur], ax
@@xloop_next:
inc [bp+@@i]
@@xloop_more?:
mov ax, [bp+@@i]
cmp ax, [bp+@@w]
jle @@xloop
cmp _graph_r_restore_from_1, 0
jz @@grcg_off?
jmp @@restore_last
; ---------------------------------------------------------------------------
@@yloop_setup:
mov ax, [bp+@@h]
sar ax, 1
mov [bp+@@error], ax
mov [bp+@@i], 0
jmp @@yloop_more?
; ---------------------------------------------------------------------------
@@yloop:
mov ax, [bp+@@x_cur]
sar ax, 3
cmp ax, [bp+@@x_vram]
jnz short @@yloop_put
mov ax, [bp+@@y_vram]
cmp ax, [bp+@@y_cur]
jz @@yloop_advance_cur
@@yloop_put:
mov ax, [bp+@@y_vram]
imul ax, ROW_SIZE
add ax, [bp+@@x_vram]
mov si, ax
cmp _graph_r_restore_from_1, 0
jnz short @@yloop_restore
les bx, _VRAM_PLANE_B
add bx, si
mov ax, [bp+@@pixels]
mov es:[bx], ax
mov [bp+@@pixels], 0
jmp @@yloop_advance_vram
; ---------------------------------------------------------------------------
@@yloop_restore:
dec si
push 1
call _graph_accesspage_func
les bx, _VRAM_PLANE_B
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_B], eax
les bx, _VRAM_PLANE_R
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_R], eax
les bx, _VRAM_PLANE_G
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_G], eax
les bx, _VRAM_PLANE_E
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_E], eax
push 0
call _graph_accesspage_func
add sp, 4
les bx, _VRAM_PLANE_B
add bx, si
mov eax, [bp+@@page1_B]
mov es:[bx], eax
les bx, _VRAM_PLANE_R
add bx, si
mov eax, [bp+@@page1_R]
mov es:[bx], eax
les bx, _VRAM_PLANE_G
add bx, si
mov eax, [bp+@@page1_G]
mov es:[bx], eax
les bx, _VRAM_PLANE_E
add bx, si
mov eax, [bp+@@page1_E]
mov es:[bx], eax
@@yloop_advance_vram:
mov ax, [bp+@@y_cur]
mov [bp+@@y_vram], ax
mov ax, [bp+@@x_cur]
sar ax, 3
mov [bp+@@x_vram], ax
@@yloop_advance_cur:
mov cl, byte ptr [bp+@@x_cur]
and cl, 7
mov ax, _graph_r_pattern
shr ax, cl
or [bp+@@pixels], ax
mov al, byte ptr [bp+@@x_cur]
and al, 7
mov cl, 16
sub cl, al
mov ax, _graph_r_pattern
shl ax, cl
or [bp+@@pixels], ax
mov ax, [bp+@@w]
sub [bp+@@error], ax
mov ax, [bp+@@y_direction]
add [bp+@@y_cur], ax
cmp [bp+@@error], 0
jge short @@yloop_next
mov ax, [bp+@@h]
add [bp+@@error], ax
inc [bp+@@x_cur]
@@yloop_next:
inc [bp+@@i]
@@yloop_more?:
mov ax, [bp+@@i]
cmp ax, [bp+@@h]
jle @@yloop
cmp _graph_r_restore_from_1, 0
jz @@grcg_off?
@@restore_last:
mov ax, [bp+@@x_cur]
sar ax, 3
mov dx, [bp+@@y_cur]
shl dx, 6
add ax, dx
mov dx, [bp+@@y_cur]
shl dx, 4
add ax, dx
dec ax
mov si, ax
push 1
call _graph_accesspage_func
les bx, _VRAM_PLANE_B
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_B], eax
les bx, _VRAM_PLANE_R
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_R], eax
les bx, _VRAM_PLANE_G
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_G], eax
les bx, _VRAM_PLANE_E
add bx, si
mov eax, es:[bx]
mov [bp+@@page1_E], eax
push 0
call _graph_accesspage_func
add sp, 4
les bx, _VRAM_PLANE_B
add bx, si
mov eax, [bp+@@page1_B]
mov es:[bx], eax
les bx, _VRAM_PLANE_R
add bx, si
mov eax, [bp+@@page1_R]
mov es:[bx], eax
les bx, _VRAM_PLANE_G
add bx, si
mov eax, [bp+@@page1_G]
mov es:[bx], eax
les bx, _VRAM_PLANE_E
add bx, si
mov eax, [bp+@@page1_E]
mov es:[bx], eax
@@grcg_off?:
cmp _graph_r_restore_from_1, 0
jnz short @@ret
call _grcg_off_func
@@ret:
pop di
pop si
leave
retf
_graph_r_line endp

View File

@ -7,8 +7,7 @@
// Graphics
// --------
void egc_copy_rect_1_to_0(int x, int y, int w, int h);
#include "th01/hardware/egc.h"
#include "th01/hardware/graph.h"
// --------

View File

@ -6836,7 +6836,6 @@ loc_D7E6:
retf
sub_D77C endp
include th01/hardware/graph_r.asm
extern _graph_putsa_fx:proc
extern _graph_move_byterect_interpage:proc
extern _z_respal_set:proc

View File

@ -3176,7 +3176,6 @@ loc_C022:
leave
retf
include th01/hardware/graph_r.asm
extern _graph_putsa_fx:proc
extern _z_respal_set:proc
op_06_TEXT ends
@ -3262,7 +3261,7 @@ EGC_START_COPY_DEF 1, far
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
public _egc_copy_rect_1_to_0
_egc_copy_rect_1_to_0 proc far
var_A = word ptr -0Ah

View File

@ -6439,7 +6439,10 @@ loc_F11D:
retf
sub_F0B3 endp
include th01/hardware/graph_r.asm
extern _graph_r_vline:proc
extern _graph_r_line_from_1:proc
extern _graph_r_line_patterned:proc
extern _graph_r_line:proc
extern _text_extent_fx:proc
extern _graph_putsa_fx:proc
extern _graph_move_byterect_interpage:proc