You may also want to load GIF images in this extended mode. Basically, you can use the normal loader because it functions independently of the screen format. In other words, the loader unpacks the compressed data in the order read: In main memory first and then to the video memory. To load an image in 640-pixel mode, it simply must exist as a 640 pixel wide image. Otherwise, every other line will be stored in the right half of the screen (not our goal).
You can also load extremely large images the same way. These images, such as the header, canbe loaded in a single step by generating an image of size 320 x 800 and then loading it, for example. If you check the image size, you will notice that these images are larger than 64K and therefore cannot be stored in the variable VScreen^. Turbo Pascal does no allow fields larger than 64K segment size.
Here are a few suggestions to help you overcome this problem:
1. Partitioning the image from the start into 64K portions. This results in an image size of 640 x 100 at double-width. This solution is neither practical nor efficient.
2. Divide the image among several pointers as you are loading it, so when one segment overflows you switch to the next variable. The programming involved here is quite complex, however.
PC
PCunderground
The procedure Double is part of the MODEXLIB.ASM file on the companion CD-ROM
3. Bypass the Turbo Pascal memory management completely and allocate the memory through DOS. In this case, when you have a segment overflow, all you need to do is increment the corresponding segment register by 1000h.
Solutions #2 and #3 have the same problem: Where will you get the necessary memory? A two-page image already requires 128K, while 64K is just barely manageable.
The best solution is found in the procedure ReadGIF in ModeXLib. Immediately following the two stosb instructions, which write the newly decoded pixel, the procedure tests for an overflow. When an overflow has occurred, the image built-up to that point is simply copied to video RAM. Since large video pages make sense only in Mode X anyway, the procedure calls up p13_2_ModeX, which copies VScreen to video RAM at the position defined by VRAM_Pos and resets the destination pointer to 0. The variable VRAM_pos is then moved to the end of the copied area in video RAM, so a possible second overflow will be added here. At the end, the procedure ReadGIF assigns the current fill-status of VScreen (located in di) to the variable
Rest. VScreen returns the number of copied bytes because Pascal always places allocated variables at even segment addresses. This way, by using Rest as the number of bytes to be copied, the main program can again call p13_2_ModeX to copy the rest into video RAM.
This process may not be the optimum algorithm but it does have two important advantages:
1. The procedure ReadGIF is 100% compatible with the old one. So, an image size doesn't have to be determined by passing a parameter or reading the GIF header. Theoretically, any image format is possible (even Super-VGA resolutions are no problem).
2. The procedure saves a great deal of memory because only one segment in memory is occupied. This segment can be removed from the heap after loading and created again when the next image is loaded.
Now that you have loaded a large image into video RAM, we'll start the actual scrolling. You'll need the Linear Starting Address Register again. Since it can now be modified by any desired value, vertical, horizontal and even diagonal scrolling are possible. The procedure is almost identical for vertical scrolling as that described in the previous section. The Linear Starting Address Register is incremented or decremented by one line length each time. You only need to consider the changed line length since vertical scrolling requires 160 byte steps.
Horizontal scrolling is done by increasing or decreasing the register by units of one, whereby one byte always represents four pixels. Scrolling is, therefore, possible only in four-pixel increments (for another option, see Pixel-Panning Register 13h of the Attribute Controller.
Diagonal scrolling simply combines these two directions. For example, to scroll four pixels up and to the left, increase the Linear Starting Address by 641 (160 bytes per line x 4 lines + 1 byte). This program demonstrates the capabilities of this register:
Uses Crt,Gif,ModeXLib;
Var x, {current offset in x-direction} x_dir, {specifies scroll direction for x} y, {current offset for y-direction} y_dir:word; {specifies scroll direction for y} Begin
Init_ModeX; {enable Mode X}
PC
PCunderground
You can find SCROLL4.PAS on the companion CD-ROM
double; {160 byte mode on (640*400 pixels total} LoadGif('640400'); {load image}
p13_2_ModeX(vram_pos,rest div 4); {rest of image in video RAM} x:=1; {x-beginning with column 1} x_dir:=1; {x-direction 1 byte per pass} y:=160; {y-beginning with line 1} y_dir:=160; {y-direction +160 bytes per pass} Repeat
Inc(x,x_dir); {x-movement} Inc(y,y_dir); {y-movement} WaitRetrace; {wait for retrace}
SetStart(y+x); {and write new start in register}
if (x >= 80) {x-border reached -> turn x-direction around} or (x <= 1) Then x_dir:=-x_dir;
if (y >= 200*160) {y-border reached -> turn y-direction around} or (y <= 160) Then y_dir:=-y_dir;
Until KeyPressed; {run until key is pressed} TextMode(3);
End.
In addition to the familiar position and direction variables for the y-direction, similar variables are also needed for the x-direction. These are called x and x_dir and have the same purpose as their y-counterparts:
x indicates the current position in the x-direction.
Note an increase or decrease of 1 represents a shift of four pixels because of the four parallel planes . x_dir
describes the x-scrolling direction. A 1 shifts the image contents four pixels to the left for each pass through the loop and a -1 shifts four pixels to the right.
After initialization, the program switches on 160-byte VGA mode by calling the double routine. This creates a virtual doubling of the screen to enable horizontal scrolling. The image is then loaded with LoadGIF. Note that a portion of the oversized image (640 x 400 pixels = 256,000 bytes) is copied to video RAM during the actual load process (you could also say it is paged out due to insufficient memory).
Since this paging occurs only with an overflow past the 64K limit, the procedure call to p13_2_ModeX
copies the rest to video RAM, starting at the position after the last byte copied (vram_pos), and using the length variable Rest, whose value is entered by LoadGIF. The number of bytes must now be divided by four since p13_2_ModeX works with main memory data - because of the four planes, a length of 1 means that four bytes are copied and the contents of the variable Rest are given as real bytes (corresponding to the number of pixels).
As we mentioned, the x-direction is initialized to 1 so scrolling initially proceeds to the left. The position is likewise set to 1 so it starts at Column 1 (prior to entering the loop the screen still starts at Column 0, Line 0). The doubling of both values to 160 occurs in the y-direction variables which accounts for the doubled line length of 160 bytes.
Very little changes in the loop itself. To create movement in the x-direction another Inc command is used. In addition, the starting screen location is set to the sum of the x-offset and y-offset, so both directions are established (see above). Furthermore, a reversal in x-direction must occur upon reaching the right or left border, so combined with a similar reversal in the y-direction, the scroll area always stays within the rectangular virtual screen defined in video RAM.