fseipel@hpuxa.ircc.ohio-state.edu (Frank E. Seipel) (03/03/91)
UN-SPRITES: Copy & Paste Graphics by Jason Leigh Sprites (Player/Missile Graphics) has always been the easiest method of animating objects on Atari computers. But what about computers like the Apple IIs and IBM PCs that do not have Sprites? They achieve animation by actually moving parts of the graphics screen. Although this is a less efficient method, it does have capabilities that Sprites does not; that is, they are not limited to the 8/255 resolution that Sprites has, and they can have as many colors as a graphics mode will allow. Un-sprites is a machine language program that will allow you to paste or copy windows to or from any of the 16 Atari graphics modes. Setting Un-sprites Up Type in Listing 1 using BASIC Editor II found elsewhere in this issue, and save it to disk or cassette. Executing this program will cause it to POKE the machine-language program directly into memory. For cassette users, append listing 1 to the end of your program that will use Un-sprites and call a GOSUB to load in the data. Disk users should save the data at address $6000 to $6300 using the "save binary" command in DOS. Two demonstration programs have been included (Listing 2 and 3) to give you an idea of how Un-sprites can be used for animation. Listing 4 is the BASIC equivalent of Unsprites; the BASIC program should make it easier for you to understand the assembly listing. Using Un-sprites in BASIC Copying a window The command in BASIC to copy a window is: COPY=USR(24842,Screen Start, StartX, StartY, EndX, EndY, Buffer Address, Graphics Mode) Screen Start is the address of the start of the screen memory. This can easily be computed by entering the desired graphics mode and reading memory locations $58 (88) and $59 (89). Here's an example: 10 GRAPHICS 7 20 SCRNSTART=PEEK(88)+PEEK(89)*256 You ae not limited to just that screen area; you may also specify a totally different memory address and copy a window from that by assigning the appropriate values for Screen Start. StartX, StartY & EndX, EndY These specify the boundaries of the copy window. Although there is no limit to the size of the window you can copy, it is advisable to keep the coordinates within the limits of the declared graphics mode. +-----------------------------------------------------------+ | | | (StartX,StartY) | | *------------------------+ | | | | | | | | | | | | | | | | | | +------------------------* | | (EndX,EndY) | | | +-----------------------------------------------------------+ Figure 1 Buffer Address The window you copy must be stored somewhere in memory, and so a storage buffer is needed. The advantage of having a user-definable buffer is that several windows can be copied, saved, pasted and repasted as needed by specifying the same buffer address. A buffer space can be declared at any address where nothing else occupies the memory. This can safely be done by dimensioning a relatively large string and using that as a buffer pool for many windows or just one window. The alternative is to dimension many little strings and store only one window in each of them. The short program segment below dimensions a string 8K in size and assigns zeros to it. BUFFADRS holds the starting address of the string buffer. 10 DIM BUFFER$(8192) 20 BUFFADRS=ADR(BUFFER$) 30 BUFFER$(1)=" ":BUFFER$(8192)=" ":BUFFER$(2)=BUFFER$(1) Graphics Mode These correspond exactly to those of the XL and XE Ataris. Graphics modes 0 to 11 are the same for all 8-bit machines, but graphics modes 12 to 15 are defined as follows: Graphics Mode 12: ANTIC Mode 4 (four color text mode 40/24) Graphics Mode 13: ANTIC Mode 5 (four color text mode 40/12) Graphics Mode 14: ANTIC Mode 12 (two color graphics mode 160/192) Graphics Mode 15: ANTIC Mode 14 (four color graphics mode 160/192) Pasting a Window The command in BASIC to paste a window is: PASTE=USR(25077,Screen Start, StartX, StartY, Buffer Address) Screen Start is the address of the screen memory in which you wish to paste the window. StartX, StartY specify the position to place the top-left corner of the window. Buffer Address is the address of the buffer that holds data from a previously copied window. It is assumed that you will past a window in the same graphics mode it was cut from. You may, however, choose to paste it in a different graphics mode; the effects can be quite interesting (or disasterous). Warning: If you accidentally omit a parameter or put them in incorrect order, you could experience a serious lockup that will result in the loss of your program. Explanation Listing 4 is the BASIC equivalent of Unsprites. It would probably be a good idea to flip between the BASIC and assembly listings while reading the following explanation. Copying When start and end coordinates are specified, Un-sprites will find the closest byte that encloses those coordinates (See Figure 2). DX holds the width of the window and DY, the height. Before the window is saved, these are used as headers in the buffer, as shown in Figure 3. The number of bytes user per window can therefore be calculated as: (DX * DY). After DX and DY have been calculated, the top-left memory (TLMEM) location of the window is computed. When all this is done, DX and DY will be saved to the buffer followed by the data in the window. Pasting Whereas Copy saved the entire byte that enclosed StartX and StartY, Paste allows exact alignment. Un-sprites will automatically shift the required number of bits to place the window at the exact StartX and StartY position. There are two methods of performing these shifts: Method 1. a. Calculate TLMEM b. Find from the shift table, the number of shifts needed c. Shift to the right Byte a i{ shifted the required number of bits to the right. Shift Store 1 acts as a bit bucket that collects all the bits that have shifted out of a. The data in the shift store is then ORed with shifted byte b. But in order to shift b, a separate shift store (Shift Store 2) is needed. This method therefore requires two shift-storage registers that alternate in use, plus it needs registers to keep track of the address of the next byte. There isn't (at least not to me) an obvious way to alternate the use of two registers efficiently, so I came up with an alternative method. Method 2. (figure 5) a. Calculate TLMEM b. Add 1 to TLMEM (TLMEM+1). c. Find from shift table the number of shifts needed d. Shift to the left Instead of shifting to the right, we move to TLMEM+1 and shift the required number of bits to the left. This is much easier, as only one shift-storage register is needed; there is no intriguing alternation between two shift registers, as in method 1. Calculating the Shift The code needed to do this is: Shift_Pointer = STX -(INT(STX/Pixels_Per_Byte)*Pixelx_Per_Byte) With the shift pointer computed, the number of shifts is then found from SHFTABLE. An example of calculating the shift is shown below: Let Pixelx_Per_Byte (PPB) = 4 and STX = 9; STX/PPB = 00001001 / 100 = 10 = 2 (all binary #'s); then 2*4 = 8 and (STX-8) = (9-8) = 1 Look up 1 in SHFTABLE4 and we get 6. That means we need to do six left- shifts from byte to byte 1. (Figure 6) Note: Two PPB graphics modes (GTIA modes 9, 10, 11) need four shifts per pixel, four PPB modes (Graphics Modes 3,5,7,15) need two shifts per pixel, eight PPB modes (Graphics Modes 4,6,8,14) need one shift and one PPB modes (the text modes) need no shifts. That should be enough information for you to tailor the Unsprites assembly listing to your own needs. If $6000 is not a convenient location for this program, you could always move the start of the program to another location. The .OPT LIST command has been included so that it will always display the new location of COPY and PASTE routines. Note that for larger windows that program could get rather slow, but if you are page flipping, the window canbe made to appear instantaneously by pasting on one screen while displaying another. There are many applications for windowing: animating frames, editing graphics screens and manipulating GEM-like windows are just a few. Sprites and Un-sprites should be the complete pair that will allow you to perform the graphics manipulation you've always wanted on that Atari. Enjoy. Saved Window (StartX, StartY) \/ +----------+----------+----------+----------+----------+ / | Enclosing| | | | | | | Byte | | | | | | | | | | | | | +----------+----------+----------+----------+----------+ | | | | | | | | | | | | | | | | | | | | | DY +----------+----------+----------+----------+----------+ | | | | | | | | | | | | | | | | | | | | | | +----------+----------+----------+----------+----------+ | | | | | | | | | | | | | | \ | | | | | | +----------+----------+----------+----------+----------+ (EndX, EndY) \_______________________DX__________________________/ Figure 2. +----------+----------+----------+ +----------+----------+ | Start | | | | | | | of | | | * * * | | | | BUFFER$ | | | | | | +----------+----------+----------+ +----------+----------+ Dx Dy \______________window data______________/ Figure 3. Sorry, I haven't the patience to key in the other figures; you'll have to 'figure' them out on your own!