📄 images.cpp
字号:
// appears to be sliding onto the screen. This is done by starting with very
// narrow slices, which are grabbed from the center of the source, and disp-
// layed at the outside edges of the screen. As the slices get wider they re-
// main rooted to the edges of the screen, so that they appear to slide into
// the center. The outer loop iterates 160 times, or half the screen width.
// On each iteration the width of the frame (i_wid) is increased by one, and
// es:di, ds:si point to the top left corner of the source frame.
// **************************************************************************
void doSlideVerticalWipe(void far *pic_buf)
{
int i_wid, x0, putx;
char ctrl; // controls branching
asm {
mov i_wid, 0 // zero out the outer loop counter
push ds // save the data segment
mov es, GRAPH_SEG // get the video segment into es
}
lefthalf:
asm {
mov ax, 160 // get center line into ax
sub ax, i_wid // i_wid is the offset from center
mov x0, ax // x0 is the top left of the source block
mov putx, 0 // putx is the top left of the dest block
mov ctrl, 0
jmp doframe // display the frame
}
righthalf:
asm {
mov ax, 160 // mostly same as above except for
mov x0, ax // right side
mov ax, 319
sub ax, i_wid
mov putx, ax
mov ctrl, 1
jmp doframe
}
checkloop:
asm {
inc i_wid
cmp i_wid, 160 // have 160 iterations
jna lefthalf
pop ds // restore data segment
}
return; // ** exit point **
doframe:
asm {
mov di, putx // di == top left corner of destination
mov dx, input_status_1 // used to test for vbi below
lds si, pic_buf // get picture pointe into ds:si
add si, x0 // set si == top left corner of source block
}
test_1: // these lines test for the vbi
asm {
in al, dx // first test, out of vbi
test al,0x8
jnz test_1
}
test_2:
asm {
in al, dx // second test, in vbi
test al,0x8
jz test_2
mov dx, 200 // set dx up as loop counter
cld // clear the direction flag
}
mainloop: // frame drawing loop
asm {
mov cx, i_wid // i_wid is equal to the block width
push si // save the offsets
push di
shr cx, 1 // optimized copy technique, cx==number of
rep movsw // number of bytes/2
rcl cx, 1 // now, if cx was odd, cx == 1, else cx ==0
rep movsb // catches any odd byte (thanks to Gus S.)
pop di // restore the offsets
pop si
add di, 320 // point to the next line
add si, 320
dec dx // adjust the outer loop counter
jnz mainloop
cmp ctrl, 0 // if last copy was lefthalf do righthalf
je righthalf
jmp checkloop
}
}
// **************************************************************************
// doSlideHorizWipe operates almost exactly like doSlideVerticalWipe above,
// except that the image slides in from top and bottom instead of from left
// and right. Like the other wipes it uses the wipe to clear the screen if
// called with pic_buf == NULL.
//
// This function operates almost exactly like the vertical version directly
// above.
// **************************************************************************
void doSlideHorizWipe(void far *pic_buf)
{
int i_wid, y0, puty;
char ctrl; // controls branching
asm {
mov i_wid, 1 // zero out the outer loop counter
push ds // save the data segment
mov es, GRAPH_SEG // get the video segment into es
}
tophalf:
asm {
mov ax, 100 // get center line into ax
sub ax, i_wid // i_wid is the offset from center
mov bx, 320
mul bx
mov y0, ax // x0 is the top left of the source block
mov puty, 0 // putx is the top left of the dest block
mov ctrl, 0
jmp doframe // display the frame
}
bottomhalf:
asm {
mov ax, 99 // mostly same as above except for
mov bx, 320
mul bx
mov y0, ax // right side
mov ax, 199
sub ax, i_wid
mul bx
mov puty, ax
mov ctrl, 1
jmp doframe
}
checkloop:
asm {
inc i_wid
cmp i_wid, 100 // have 160 iterations
jna tophalf
pop ds // restore data segment
}
return; // ** exit point **
doframe:
asm {
mov di, puty // di == top left corner of destination
mov dx, input_status_1 // used to test for vbi below
lds si, pic_buf // get picture pointe into ds:si
add si, y0 // set si == top left corner of source block
}
test_1: // these lines test for the vbi
asm {
in al, dx // first test, out of vbi
test al,0x8
jnz test_1
}
test_2:
asm {
in al, dx // second test, in vbi
test al,0x8
jz test_2
mov dx, i_wid // set dx up as loop counter
cld // clear the direction flag
}
mainloop: // frame drawing loop
asm {
mov cx, 160 // i_wid is equal to the block width
push si // save the offsets
push di
rep movsw // number of bytes/2
pop di // restore the offsets
pop si
add di, 320 // point to the next line
add si, 320
dec dx // adjust the outer loop counter
jnz mainloop
cmp ctrl, 0 // if last copy was lefthalf do righthalf
je bottomhalf
jmp checkloop
}
}
// *************************************************************************
// doVerticalDissolve causes the image stored in pic_buf to be displayed by
// fading in multiple vertical slices. It is the vertical equivalent of the
// doHorizDissolve function. When called with a null pointer it clears the
// screen.
//
// The function moves the image data to the screen by iterating through
// 16 vertical slices. On each iteration two lines are drawn, at an equal
// distance on either side of the center mark for that section. The outer-
// most loop counts the lines; it takes 10 iterations to fill one slice. The
// innermost loop cycles through the 16 slices. So, the first slice gets two
// lines, the second gets two, on up to the 16th, and then the first gets
// two more, and so on. Keep an eye on si and di.
// *************************************************************************
void doVerticalDissolve(void far *pic_buf)
{
int base_row; // base_row stores the line offset from x
asm {
mov es, GRAPH_SEG // get the video segment into es
mov base_row, 0 // start out drawing on the x pixel
mov cx, 11 // outer loop, 11 pixels to each side of
cld // the x pixel (in si and di) will be drawn
push ds // save the ds register value
lds si, pic_buf // get the picture pointer into ds:si
mov ax, ds // check for a NULL pointer and jmp to
cmp ax, 0 // clearscr if found
je clearscr
}
mainloop:
asm {
push cx // save the outer loop counter
push si // save original offset to byte 0 of pic
mov cx, 16 // process 16 vertical slices
add si, 9 // first x mark is on 9,0
mov di, 9
}
drawloop:
asm {
push cx // save the inner loop counter
push si // and the x mark, source and dest
push di
add di, base_row // add in the offset from x for first line
add si, base_row
mov cx, 200 // plot 200 pixels
}
lineloop1: // this loop draws a vertical line
asm {
movsb // move one byte
add si, 319 // move to next row
add di, 319
loop lineloop1 // do another
pop di // restore the starting points
pop si
push si // save them again
push di
sub di, base_row // drawing on the other side this time
sub si, base_row
mov cx, 200 // plot 200 pixels
}
lineloop2:
asm {
movsb // same as above
add si, 319
add di, 319
loop lineloop2
pop di // restore the starting point
pop si
pop cx // restore the inner loop counter
add si, 20 // adjust pointer to the next slice
add di, 20
loop drawloop // process it
inc base_row // increment the drawing offset
pop si // restore the offset to byte 0 of pic
pop cx // restore the outer loop counter
loop mainloop // do it all again
jmp done
}
clearscr: // this block functions exactly as the
asm { // previous one but clears the screen using
push cx // palette register 0
mov cx, 16
mov di, 9
}
drawloop2:
asm {
push cx
push di
add di, base_row
xor ax, ax
mov cx, 200
}
lineloop21:
asm {
stosb
add di, 319
loop lineloop21
pop di
push di
sub di, base_row
xor ax, ax
mov cx, 200
}
lineloop22:
asm {
stosb
add di, 319
loop lineloop22
pop di
pop cx
add di, 20
loop drawloop2
inc base_row
pop cx
loop clearscr
}
done:
asm pop ds; // restore the data segment
}
// **************************************************************************
// doHorizDissolve causes the image in pic_buf to be displayed by dissolving
// it in in 10 horizontal bands. If called with pic_buf==NULL it clears the
// screen by the same method.
//
// This function processes the data much like the Vertcal Dissolve funtion
// above. The screen in this case is divided into 10 horizontal slices. The
// center line starting points of these slices begin at 2880 bytes into the
// video buffer, and every 6400 bytes after that. Like the function above it
// cycles through the slices drawing two lines at each, progressively further
// from the center line with each iteration of the outer loop. Like the func-
// tion above, you have to keep a carefull eye on di and si to understand it.
// **************************************************************************
void doHorizDissolve(void far *pic_buf)
{
int base_line;
asm {
mov base_line, 0 // base_line is an offset from each line
mov es, GRAPH_SEG // get video segment into es
mov bx, 320 // bx * base_line == adjust value for si,di
mov cx, 20 // outer loop 20 iterations
cld // clear the direction flag
push ds // save the ds register value
lds si, pic_buf // get pic_buf into ds:si
mov ax, ds // if pic_buf == NULL jump to clearscr
cmp ax, 0
je clearscr
}
mainloop1: // main drawing loop, 20 iterations...
asm { // the number of offset lines to draw
push cx // save the counter
mov cx, 10 // inner loop, 10 iterations, draws lines
push si // save the offset of the pic_buf pointer
add si, 60480 // 60480, address of first line processed
mov di, 60480
mov dx, input_status_1 // used below to test for vbi
}
test_11: // these lines test for the vbi
asm {
in al, dx // first test, out of vbi
test al,0x8
jnz test_11
}
test_12:
asm {
in al, dx // second test, in vbi
test al,0x8
jz test_12
}
drawloop1: // drawloop processes the 10 base lines,
asm { // drawing 2 lines at offset ax from base
push cx // save the counter
push si // save the offset to the current base
push di
mov ax, base_line // calculate the pointer offset from base
mul bx // by multiplying base_line * 320
sub si, ax // subtract the offset from source and
sub di, ax // dest base pointers, and
mov cx, 160 // draw the first line
rep movsw
pop di // restore the base pointers
pop si
push si // save em again
push di
add si, ax // add the offset to the source and dest
add di, ax // base pointers and
mov cx, 160 // draw the second line
rep movsw
pop di // restore the base pointers
pop si
pop cx // restore the inner loop counter
sub si, 6400 // adjust base pointers to point to the
sub di, 6400 // next base, 20 lines up the screen
loop drawloop1 // process the next section
inc base_line // increment the base offset factor
pop si // restore the original pic_buf offset
pop cx // restore the outer loop counter
loop mainloop1 // do it all over again
jmp done // finished
}
clearscr: // this section executes if pic_buf==NULL
asm {
push cx // save the outer loop counter
mov cx, 10
mov di, 60480 // we can ignore ds:si since no source
mov dx, input_status_1 // used to test for vbi below
}
test_21: // these lines test for the vbi
asm {
in al, dx // first test, out of vbi
test al,0x8
jnz test_21
}
test_22:
asm {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -