Jump to content
  • entries
    39
  • comments
    57
  • views
    124,711

7800 Sprites


DanBoris

2,350 views

One of the trickier parts of the 7800’s MARIA graphics chip is understanding how to setup the display lists and display list list (DL and DLL). Even trying to put a single sprite on the screen can be tricky. In this article I will explain how to setup these data structures to get a simple sprite on the screen.

 

In this example we will take a very narrow scenario just to explain the basics of how to get a sprite on the screen. I will show how to display a single 16 line high by 1 byte wide sprite. If you want to see complete code on how to do this take a look at my 7800 Sprite Demo source code. For more details on the DLL and DL structure see the 7800 Software Guide. Both these files are available on my site http://www.atarihq.com/danb/a7800.shtml.

 

The first step is to setup the Display List List (DLL). Since we will be using 16 line high sprites the zones will also be 16 lines high, so this will give us 12 zones for a total of 192 lines. The first byte of each DLL entry will be $4F. This will enable 16 line holey DMA (I will explain this later) and an offset of 15 which corresponds to the 16 line height of the zone. The second and third bytes of the DLL are just a pointer to the Display List (DL) for this zone. For the purpose of this discussion we won’t worry about this address.

 

Before we move onto how to setup the DL entries lets first have a refresher on how graphics data is setup in memory on the 7800. The graphics data for a sprite is NOT stored in sequential bytes in memory. Each line of graphics data for a sprite is stored on sequential pages (a page is 256 bytes) of memory, and it’s stored upside down. Let’s say we want to store our sprite data in the memory block between $A000 and $AFFF. For our first sprite the data for the first line of the sprite would be stored at location $AF00, the second line and $AE00, the third at $AD00, and so on until the last line is in location $A000. If we wanted to define a second sprite we would just move up one location in each page, so the first line would be in $AF01, the second in $AE01, and so on until the last line is in location $A001.

 

Now let’s talk about how the DL entries would be setup. We will look at two scenarios, the first being where the sprite starts on the first line of a zone so it’s entirely in one zone, and the second scenario where it starts on the second line of a zone so it spans two zones. I am just going show how to use 5 byte DL entries, not the 4 byte entries.

 

We start with the first scenario where the sprite in entirely in a single zone. The first thing we need to do it determine which zone the sprite is in. This is done simply by dividing the vertical position by 16 which is the same as taking the top 4 bits of the position. Once we know what zone the sprite is in we can start building the DL entry.

 

The first byte of the DL entry is the low byte of the address of the sprite data. The data for the first sprite starts at location $A000 (even though it’s upside down we still say it starts at the lowest address), so this byte would be $00. The second byte will be $40. This just sets up the display mode and is not important for the purposes of this article. The third byte is the high byte of the sprite data, so it would be $A0 in this case. The fourth byte specifies the palette and the width, we will make this $1F and again the details are not important. Finally the fifth byte is the horizontal position of the sprite.

 

The second scenario is a little more complicated. Since the sprite doesn’t fall entirely in one zone there will have to be a DL entry in two different zones. Both of these entries will be the same as the first scenario with the exception of the high byte of the graphics data (byte 3).

 

To understand how these values will be determines you need to understand how the MARIA chip draws the screen. At the start of each DLL entry the offset value is loaded into a register in the chip. When MARIA goes to fetch graphics data it adds the offset value to the high byte of the graphics data. When it completes a line and moves to the next one it de-increments the offset value. So in the first scenario, on the first line the offset will be $0F which will get added to the high byte $A0, making an address of $AF00. This is why the graphics data is stored upside down.

 

To have our sprite start on the second line of a zone instead of the first we would set the upper address to $A1. We are getting this by taking the lower 4 bits of the vertical position and adding it to $A0. When MARIA draws the first line it will add the offset of $0F to $A1 to get an address of $B000 for the first byte, when it draws the second line the offset of $0E will be added to $A1 so the second line of the zone would come from $AF00 which is the first line of the sprite data. But if we are taking the first line from $B000 wouldn’t this cause ‘garbage’ to be displayed at the top of the zone? No, because this is where holey DMA comes in to play. When 16 line holey DMA is enabled and MARIA fetches data from memory, if address bit 12 is high then zero is returned instead of data that is in memory. $B000 has bit 12 high so the graphics data will be zero for the first line of the zone.

 

The first zone will contain the first 15 lines of the sprite, but the final line of the sprite will appear in the next zone. Again, the only difference from the first DL entry will be the high address of the graphics data. In this case we would set the high byte to $91. When the first line of this zone is drawn the offset will be $0F added to $91 = $A000 which is the last line of our sprite data. On the second line of the zone the offset will be $0E added to $91 = $9F00. Once again holey DMA will take effect since bit 12 is high so the graphics data will be zero. This will continue to the end of the zone.

 

That is the basics of how to setup sprite data in the display lists. If we were doing more then one sprite we would iterate through each sprite repeating the process above and appending the DL entries to the end of each DL. Finally, once we have finished creating all the DL entires we would need to go back and terminate each DL. This is done by adding a final entry where the 2nd byte is zero.

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...