Jump to content

Photo

Intellivision Tutorials


10 replies to this topic

#1 mphokie OFFLINE  

mphokie

    Star Raider

  • 95 posts
  • Location:Charlotte, NC, USA

Posted Fri Feb 4, 2011 3:01 PM

Could someone direct me to some simple Intellivision "Hello World"-type tutorials that show how to get graphics onto the screen? I've been messing around w/the SDK-1600 from JoeZ and checking around the net for more info, but I seem to be missing something.

I've downloaded the source for Ryan Kinnen's Minehunter from his site and have the Space Patrol teaser code, but what I'm looking for is the most bare-bones code I'd need to place graphics are background tiles, animate MOBs, etc. Mainly this is due to my complete inexperience w/assembly programming.

Also, is the "running man" graphics part of the GROM? It seems like it would be (assuming I'm understanding the underlying hardware/architecture), since it's used in so many games.

#2 GroovyBee OFFLINE  

GroovyBee

    7800 Developer

  • 7,741 posts
  • Busy bee!
  • Location:North, England

Posted Fri Feb 4, 2011 3:10 PM

There are several examples in the sdk1600\examples subdirectory. Have you looked at them? There is also an examples directory in the jzintv package.

Have you joined the Yahoo intvprog group?

As far as I'm aware the running man isn't part of the GROM.

#3 mphokie OFFLINE  

mphokie

    Star Raider

  • Topic Starter
  • 95 posts
  • Location:Charlotte, NC, USA

Posted Fri Feb 4, 2011 3:47 PM

There are several examples in the sdk1600\examples subdirectory. Have you looked at them? There is also an examples directory in the jzintv package.

Have you joined the Yahoo intvprog group?

As far as I'm aware the running man isn't part of the GROM.


I have been working w/some of the examples from the sdk1600 (and jzintv), but it hasn't been real clear to me (again, it's probably me, since I can't "read" ASM too well yet).

I've found it's easier for me to start w/the "Hello World" and gradually build up from there. In this case, I've found a number of title screen tutorials, and I think I have a handle on how ISRs work, how to do the controller scanning, etc., even creating the DECLEs for the different GRAM cards you'd want to use, but I just haven't been able to find that bit of code that sets the lightbulb off regarding the background graphics stuff. There seems to be a lot of samples w/MOBs, but the only one I'd seen so far w/other graphics was Tagalong Todd 2b (the cans you collect). There's just so much other stuff going on in that sample that it's hard at the moment to separate what's needed just for background stuff and what's other game engine-related code.

I've been a member of the Yahoo intvprog group since the beginning (or close to it), but haven't tried to delve into the programming end until recently.

#4 GroovyBee OFFLINE  

GroovyBee

    7800 Developer

  • 7,741 posts
  • Busy bee!
  • Location:North, England

Posted Fri Feb 4, 2011 4:47 PM

How about posting some of your code and then we can see what you are trying to do.

#5 DZ-Jay OFFLINE  

DZ-Jay

    River Patroller

  • 4,984 posts
  • Ranger Elf: Saviour of Christmas!
  • Location:NC, USA

Posted Sat Feb 5, 2011 9:19 AM


There are several examples in the sdk1600\examples subdirectory. Have you looked at them? There is also an examples directory in the jzintv package.

Have you joined the Yahoo intvprog group?

As far as I'm aware the running man isn't part of the GROM.


I have been working w/some of the examples from the sdk1600 (and jzintv), but it hasn't been real clear to me (again, it's probably me, since I can't "read" ASM too well yet).

I've found it's easier for me to start w/the "Hello World" and gradually build up from there. In this case, I've found a number of title screen tutorials, and I think I have a handle on how ISRs work, how to do the controller scanning, etc., even creating the DECLEs for the different GRAM cards you'd want to use, but I just haven't been able to find that bit of code that sets the lightbulb off regarding the background graphics stuff. There seems to be a lot of samples w/MOBs, but the only one I'd seen so far w/other graphics was Tagalong Todd 2b (the cans you collect). There's just so much other stuff going on in that sample that it's hard at the moment to separate what's needed just for background stuff and what's other game engine-related code.

I've been a member of the Yahoo intvprog group since the beginning (or close to it), but haven't tried to delve into the programming end until recently.


Let me see if I can offer a bit of high-level insight into the graphics that may help.

First, as you may know, the graphics are divided into two types: Background and Sprites. Each one is handled differently, so understanding these differences helps.

Background Graphics:
The background is simply a grid of tiles (called "cards" in the Intellivision parlance). The grid is 20 columns by 12 rows, and each tile is 8x8 pixels. It is defined by a contiguous block of memory that is called the Background Table (BACKTAB). Each cell in the BACKTAB represents a tile in the grid and contains information on how to draw it. These tiles are merely an index into graphics memory that contains the actual pixel data.

There are two types of graphics memory that you can use: Graphics ROM (GROM) and Graphics RAM (GRAM). GROM contains all the built-in graphics used by many games, including the recognizable Intellivision fonts, and various basic graphic elements and shapes. GRAM is an array of 64 slots, fully open for you to fill with whatever graphic tiles you want.

You "draw" on the screen by configuring each cell in the BACKTAB to point to the "card" you want it to use, along with the foreground and background colors and other attributes. There are two main color modes that influence the way you define tile attributes, but we'll deal with those later. The "card" information includes not only the index to memory, but whether that index is in GROM or GRAM.

GROM and GRAM are themselves just a contiguous block of 8-bit memory, so the pixel data for each 8x8 card is stored as a series of eight bytes representing the bit patterns of the tile. It seems you already understand how to store the tile data into GRAM, so I will skip that information. You should consult the SDK documentation for further details on this subject.

Now, let's walk through the steps of drawing on the screen. Suppose you already have composed a nice image that is easily broken into 8x8 tiles. Your program needs to do the following, assuming that you have already defined your 8x8 tiles as "DECLE" data:

  • Load all tiles into GRAM
  • Set the global display color mode
  • For each of the cells in BACKTAB define the tile information:
    • Set whether it is GROM or GRAM
    • Specify the card index into the appropriate graphics memory
    • Set color mode (more on this in a bit)
    • Set appropriate Forground and Background colors
  • Continue until you fill the entire BACKTAB

Sometimes you do not need to draw into the entire BACKTAB, and you just need to "draw" on a specific tile on the screen. In that case, you first find the BACKTAB address for the specific tile you want to draw, and define its card information as described above.

In many games, it is common to have a full, static background defined for a game "screen" and draw it once onto the BACKTAB, and be done with it. In such case, since you already know all the tiles and where they go, it is typical to define the data for the entire BACKTAB as "DECLE" data, and just copy directly from ROM to the BACKTAB memory. Obviously this requires a lot of preparation into building this metadata before hand, but who said making video games was easy or quick? :)

What's left is now is to describe the BACKTAB cell information. The SDK contains some excellent reference material on this. In particular you should look into the "stic.txt" and "graphics_mem.txt" documents; both in the "docs" directory.

The quick "low-down" is this: Each BACKTAB cell is defined by a 16-bit word, where each bit or group of bits represent attributes that describe the tile. As I mentioned before, there are two main color modes, each one with its own set of advantages and limitations. The entire display can only be on a specific color mode at a time, and the format of the BACKTAB word depends on the color mode selected. For more information on features of each color mode, I suggest you review the aforementioned SDK documentation.

As an example, consider the following format for Color Stack mode:

    13   12    11   10    9    8    7    6    5    4    3    2    1    0   
  +----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
  |Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
  |col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
  |stck|     |    |                                       |              | 
  +----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 

In Color Stack mode, instead of defining a background color for each tile, you define a circular "stack" of four background colors. You then switch background colors as you need by setting the Advance Color Stack flag (bit #13) for a tile, which causes the stack to advance to the next color. The foreground color in Color Stack mode can be any of the 16 colors for GRAM cards. For GROM cards only the first 8 "primary" colors are available.

Note also that the 4-bit foreground color is split: while the three low-order bits reside in bits #0 through #2, the high-order bit of the color is in bit #12 of the BACKTAB word.

Bits #3 through #10 define the index in graphics memory of the card, and bit #11 specifies whether this is from GROM or GRAM.

Finally, the upper two bits of the word are not used, so you can use them as you please to store game information, or ignore them completely.

Now, let's work through an example. Suppose you have a background of 4 individual tiles, described as follows:

+-----------+-----------+-----------+-----------+
| MEM: GRAM | MEM: GRAM | MEM: GRAM | MEM: GRAM |
| CARD: #1  | CARD: #2  | CARD: #3  | CARD: #4  |
|           |           |           |           |
| FG: White | FG: Red   | FG: Green | FG: White |
| BG: Black | BG: Black | BG: Yellow| BG: Red   |
+-----------+-----------+-----------+-----------+

As you can see, each tile uses a different card from GRAM, and the background colors change depending on the tile. We'll stick with Color Stack mode for this example, so we'll define a color stack of,
  • Black
  • Yellow
  • Red
  • Green

and have our BACKTAB cycle through it. Note that in Color Stack mode the stack must be cycled in order. This is a limitation of the mode, but it provides enough flexibility in other areas for backgrounds that do not require many colors.

The stack starts at the first color, so all tiles will have a background color of Black until the stack is advanced.

Tile #1:
Memory: 1 (GROM = 0, GRAM = 1)
Card #1: 00000001
FG White: 0111 ($07)
BG Black: 0 (This is the first color in the stack, so we do not need to advance the color stack)

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  0 |   0 | 1  |  0 |  0 |  0 |  0 |  0 |  0 |  0 | 1  |  1 |  1 |  1 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


Tile #2:
Memory: 1 (GROM = 0, GRAM = 1)
Card #15: 00001111
FG Red: 0010 ($02)
BG Black: 0 (Same color as before, so we do not need to advance the color stack)

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  0 |   0 | 1  |  0 |  0 |  0 |  0 |  1 |  1 |  1 | 1  |  0 |  1 |  0 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


Tile #3:
Memory: 1 (GROM = 0, GRAM = 1)
Card #42: 00101010
FG Green: 0101 ($05)
BG Yellow: 1 (We advance the stack to the next color, Yellow)

Note that from now on all tiles will have a background color of Yellow, until the stack is advanced again.

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  1 |   0 | 1  |  0 |  0 |  1 |  0 |  1 |  0 |  1 | 0  |  1 |  0 |  1 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


Tile #4:
Memory: 1 (GROM = 0, GRAM = 1)
Card #2: 00000010
FG Orange: 1010 ($0A)
BG Red: 1 (We advance the stack to the next color, Red)

Note that from now on all tiles will have a background color of Red, until the stack is advanced again. Also note that since the foreground color has the high-order bit set, it needs to be split as explained above.

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  1 |   1 | 1  |  0 |  0 |  0 |  0 |  0 |  0 |  1 | 0  |  0 |  1 |  0 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


We can now encode our BACKTAB data for the background tiles in ROM. All we do here is take the encoded 16-bit words described above and treat them as a 16-bit binary value. It is common to write them out as Hexadecimal, but you can use binary or decimal or whatever notation the Assembler accepts.

BG_DATA PROC
                            ;   FE D C B A9876543 210
                            ;   ---------------------
        DECLE   $080F       ; % 00 0 0 1 00000001 111
        DECLE   $087A       ; % 00 0 0 1 00001111 010
        DECLE   $2955       ; % 00 1 0 1 00101010 101
        DECLE   $3812       ; % 00 1 1 1 00000010 010
        ENDP

And to copy this into our BACKTAB, we just loop through the number of tiles, and move the data from ROM to the address in BACKTAB that we are going to use:

DRAW_BG PROC
        BEGIN                               ; Save return address

        MVII    #BG_DATA,           R4      ; Source:      Point to the background data
        MVII    #$0200,             R5      ; Destination: Point to the BACKTAB
        MVII    #4,                 R1      ; How many tiles to copy

@@nxt:  MVI@    R4,     R0                  ; Get the current BTAB word from ROM
        MVO@    R0,     R5                  ;   and store it in the BACKTAB.

        DECR    R1                          ; \_ Loop for all words in BACKTAB
        BNZE    @@nxt                       ; /

        RETURN                              ; Return to caller
        ENDP

Note that using R4 and R5 is convenient because they automatically advance one word when they are used to access memory. Thus, by just using,
        MVI@    R4,     R0

The CPU retrieves the data pointed to by R4 (from ROM in this case), stores it in R0, and automatically advances R4 to point to the next address.

I know that the example above is a bit contrived, but it is just out of the top of my head to illustrate the concepts of composing the BACKTAB word and advancing the color stack. Please feel free to ask any specific questions or to post any code that you are having problems with.

I hope that this helps.
-dZ.

Edited by DZ-Jay, Sat Feb 5, 2011 9:36 AM.


#6 mphokie OFFLINE  

mphokie

    Star Raider

  • Topic Starter
  • 95 posts
  • Location:Charlotte, NC, USA

Posted Sat Feb 5, 2011 10:48 AM



There are several examples in the sdk1600\examples subdirectory. Have you looked at them? There is also an examples directory in the jzintv package.

Have you joined the Yahoo intvprog group?

As far as I'm aware the running man isn't part of the GROM.


I have been working w/some of the examples from the sdk1600 (and jzintv), but it hasn't been real clear to me (again, it's probably me, since I can't "read" ASM too well yet).

I've found it's easier for me to start w/the "Hello World" and gradually build up from there. In this case, I've found a number of title screen tutorials, and I think I have a handle on how ISRs work, how to do the controller scanning, etc., even creating the DECLEs for the different GRAM cards you'd want to use, but I just haven't been able to find that bit of code that sets the lightbulb off regarding the background graphics stuff. There seems to be a lot of samples w/MOBs, but the only one I'd seen so far w/other graphics was Tagalong Todd 2b (the cans you collect). There's just so much other stuff going on in that sample that it's hard at the moment to separate what's needed just for background stuff and what's other game engine-related code.

I've been a member of the Yahoo intvprog group since the beginning (or close to it), but haven't tried to delve into the programming end until recently.


Let me see if I can offer a bit of high-level insight into the graphics that may help.

First, as you may know, the graphics are divided into two types: Background and Sprites. Each one is handled differently, so understanding these differences helps.

Background Graphics:
The background is simply a grid of tiles (called "cards" in the Intellivision parlance). The grid is 20 columns by 12 rows, and each tile is 8x8 pixels. It is defined by a contiguous block of memory that is called the Background Table (BACKTAB). Each cell in the BACKTAB represents a tile in the grid and contains information on how to draw it. These tiles are merely an index into graphics memory that contains the actual pixel data.

There are two types of graphics memory that you can use: Graphics ROM (GROM) and Graphics RAM (GRAM). GROM contains all the built-in graphics used by many games, including the recognizable Intellivision fonts, and various basic graphic elements and shapes. GRAM is an array of 64 slots, fully open for you to fill with whatever graphic tiles you want.

You "draw" on the screen by configuring each cell in the BACKTAB to point to the "card" you want it to use, along with the foreground and background colors and other attributes. There are two main color modes that influence the way you define tile attributes, but we'll deal with those later. The "card" information includes not only the index to memory, but whether that index is in GROM or GRAM.

GROM and GRAM are themselves just a contiguous block of 8-bit memory, so the pixel data for each 8x8 card is stored as a series of eight bytes representing the bit patterns of the tile. It seems you already understand how to store the tile data into GRAM, so I will skip that information. You should consult the SDK documentation for further details on this subject.

Now, let's walk through the steps of drawing on the screen. Suppose you already have composed a nice image that is easily broken into 8x8 tiles. Your program needs to do the following, assuming that you have already defined your 8x8 tiles as "DECLE" data:

  • Load all tiles into GRAM
  • Set the global display color mode
  • For each of the cells in BACKTAB define the tile information:
    • Set whether it is GROM or GRAM
    • Specify the card index into the appropriate graphics memory
    • Set color mode (more on this in a bit)
    • Set appropriate Forground and Background colors
  • Continue until you fill the entire BACKTAB

Sometimes you do not need to draw into the entire BACKTAB, and you just need to "draw" on a specific tile on the screen. In that case, you first find the BACKTAB address for the specific tile you want to draw, and define its card information as described above.

In many games, it is common to have a full, static background defined for a game "screen" and draw it once onto the BACKTAB, and be done with it. In such case, since you already know all the tiles and where they go, it is typical to define the data for the entire BACKTAB as "DECLE" data, and just copy directly from ROM to the BACKTAB memory. Obviously this requires a lot of preparation into building this metadata before hand, but who said making video games was easy or quick? :)

What's left is now is to describe the BACKTAB cell information. The SDK contains some excellent reference material on this. In particular you should look into the "stic.txt" and "graphics_mem.txt" documents; both in the "docs" directory.

The quick "low-down" is this: Each BACKTAB cell is defined by a 16-bit word, where each bit or group of bits represent attributes that describe the tile. As I mentioned before, there are two main color modes, each one with its own set of advantages and limitations. The entire display can only be on a specific color mode at a time, and the format of the BACKTAB word depends on the color mode selected. For more information on features of each color mode, I suggest you review the aforementioned SDK documentation.

As an example, consider the following format for Color Stack mode:

    13   12    11   10    9    8    7    6    5    4    3    2    1    0   
  +----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
  |Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
  |col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
  |stck|     |    |                                       |              | 
  +----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 

In Color Stack mode, instead of defining a background color for each tile, you define a circular "stack" of four background colors. You then switch background colors as you need by setting the Advance Color Stack flag (bit #13) for a tile, which causes the stack to advance to the next color. The foreground color in Color Stack mode can be any of the 16 colors for GRAM cards. For GROM cards only the first 8 "primary" colors are available.

Note also that the 4-bit foreground color is split: while the three low-order bits reside in bits #0 through #2, the high-order bit of the color is in bit #12 of the BACKTAB word.

Bits #3 through #10 define the index in graphics memory of the card, and bit #11 specifies whether this is from GROM or GRAM.

Finally, the upper two bits of the word are not used, so you can use them as you please to store game information, or ignore them completely.

Now, let's work through an example. Suppose you have a background of 4 individual tiles, described as follows:

+-----------+-----------+-----------+-----------+
| MEM: GRAM | MEM: GRAM | MEM: GRAM | MEM: GRAM |
| CARD: #1  | CARD: #2  | CARD: #3  | CARD: #4  |
|           |           |           |           |
| FG: White | FG: Red   | FG: Green | FG: White |
| BG: Black | BG: Black | BG: Yellow| BG: Red   |
+-----------+-----------+-----------+-----------+

As you can see, each tile uses a different card from GRAM, and the background colors change depending on the tile. We'll stick with Color Stack mode for this example, so we'll define a color stack of,
  • Black
  • Yellow
  • Red
  • Green

and have our BACKTAB cycle through it. Note that in Color Stack mode the stack must be cycled in order. This is a limitation of the mode, but it provides enough flexibility in other areas for backgrounds that do not require many colors.

The stack starts at the first color, so all tiles will have a background color of Black until the stack is advanced.

Tile #1:
Memory: 1 (GROM = 0, GRAM = 1)
Card #1: 00000001
FG White: 0111 ($07)
BG Black: 0 (This is the first color in the stack, so we do not need to advance the color stack)

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  0 |   0 | 1  |  0 |  0 |  0 |  0 |  0 |  0 |  0 | 1  |  1 |  1 |  1 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


Tile #2:
Memory: 1 (GROM = 0, GRAM = 1)
Card #15: 00001111
FG Red: 0010 ($02)
BG Black: 0 (Same color as before, so we do not need to advance the color stack)

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  0 |   0 | 1  |  0 |  0 |  0 |  0 |  1 |  1 |  1 | 1  |  0 |  1 |  0 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


Tile #3:
Memory: 1 (GROM = 0, GRAM = 1)
Card #42: 00101010
FG Green: 0101 ($05)
BG Yellow: 1 (We advance the stack to the next color, Yellow)

Note that from now on all tiles will have a background color of Yellow, until the stack is advanced again.

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  1 |   0 | 1  |  0 |  0 |  1 |  0 |  1 |  0 |  1 | 0  |  1 |  0 |  1 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


Tile #4:
Memory: 1 (GROM = 0, GRAM = 1)
Card #2: 00000010
FG Orange: 1010 ($0A)
BG Red: 1 (We advance the stack to the next color, Red)

Note that from now on all tiles will have a background color of Red, until the stack is advanced again. Also note that since the foreground color has the high-order bit set, it needs to be split as explained above.

  13   12    11   10    9    8    7    6    5    4    3    2    1    0   
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|Adv.|FG   |GRAM|           GRAM/GROM Card #            |   FG Color   | 
|col |Bit3/|GROM|    (0-255 for GROM, 0-63 for GRAM)    |   Bits 0-2   | 
|stck|     |    |                                       |              | 
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 
|  1 |   1 | 1  |  0 |  0 |  0 |  0 |  0 |  0 |  1 | 0  |  0 |  1 |  0 |
+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+ 


We can now encode our BACKTAB data for the background tiles in ROM. All we do here is take the encoded 16-bit words described above and treat them as a 16-bit binary value. It is common to write them out as Hexadecimal, but you can use binary or decimal or whatever notation the Assembler accepts.

BG_DATA PROC
                            ;   FE D C B A9876543 210
                            ;   ---------------------
        DECLE   $080F       ; % 00 0 0 1 00000001 111
        DECLE   $087A       ; % 00 0 0 1 00001111 010
        DECLE   $2955       ; % 00 1 0 1 00101010 101
        DECLE   $3812       ; % 00 1 1 1 00000010 010
        ENDP

And to copy this into our BACKTAB, we just loop through the number of tiles, and move the data from ROM to the address in BACKTAB that we are going to use:

DRAW_BG PROC
        BEGIN                               ; Save return address

        MVII    #BG_DATA,           R4      ; Source:      Point to the background data
        MVII    #$0200,             R5      ; Destination: Point to the BACKTAB
        MVII    #4,                 R1      ; How many tiles to copy

@@nxt:  MVI@    R4,     R0                  ; Get the current BTAB word from ROM
        MVO@    R0,     R5                  ;   and store it in the BACKTAB.

        DECR    R1                          ; \_ Loop for all words in BACKTAB
        BNZE    @@nxt                       ; /

        RETURN                              ; Return to caller
        ENDP

Note that using R4 and R5 is convenient because they automatically advance one word when they are used to access memory. Thus, by just using,
        MVI@    R4,     R0

The CPU retrieves the data pointed to by R4 (from ROM in this case), stores it in R0, and automatically advances R4 to point to the next address.

I know that the example above is a bit contrived, but it is just out of the top of my head to illustrate the concepts of composing the BACKTAB word and advancing the color stack. Please feel free to ask any specific questions or to post any code that you are having problems with.

I hope that this helps.
-dZ.



Thanks, dZ. That's a big help and gives me quite a bit to go on. I'd gone back last night and was working through some of the other examples and now I feel like I'm getting on the right track.

#7 DZ-Jay OFFLINE  

DZ-Jay

    River Patroller

  • 4,984 posts
  • Ranger Elf: Saviour of Christmas!
  • Location:NC, USA

Posted Sat Feb 5, 2011 10:54 AM

Thanks, dZ. That's a big help and gives me quite a bit to go on. I'd gone back last night and was working through some of the other examples and now I feel like I'm getting on the right track.


No worries. I'll prepare a similar explanation for Sprite handling later on. My experience is limited, for I've only been working on Intellivision games on-and-off for a little over a year; but I've managed to complete my first game already and it is my pleasure to share the knowledge I've acquired with other programmers starting out.

I know that, for me, just reading the Assembly Language samples was not enough; I needed to understand how to put everything together from a higher perspective. So knowing what is the BACKTAB, how it is organized, and how to use it helped me immensely. The rest is just figuring out the Assembly syntax to do what you want, but in my opinion, that's the easy part. :)

-dZ.

Edited by DZ-Jay, Sat Feb 5, 2011 10:57 AM.


#8 intvnut OFFLINE  

intvnut

    Stargunner

  • 1,103 posts
  • Location:@R6 (top of stack)

Posted Sat Feb 5, 2011 9:00 PM


There are several examples in the sdk1600\examples subdirectory. Have you looked at them? There is also an examples directory in the jzintv package.

Have you joined the Yahoo intvprog group?

As far as I'm aware the running man isn't part of the GROM.


I have been working w/some of the examples from the sdk1600 (and jzintv), but it hasn't been real clear to me (again, it's probably me, since I can't "read" ASM too well yet).

I've found it's easier for me to start w/the "Hello World" and gradually build up from there. In this case, I've found a number of title screen tutorials, and I think I have a handle on how ISRs work, how to do the controller scanning, etc., even creating the DECLEs for the different GRAM cards you'd want to use, but I just haven't been able to find that bit of code that sets the lightbulb off regarding the background graphics stuff. There seems to be a lot of samples w/MOBs, but the only one I'd seen so far w/other graphics was Tagalong Todd 2b (the cans you collect). There's just so much other stuff going on in that sample that it's hard at the moment to separate what's needed just for background stuff and what's other game engine-related code.

I've been a member of the Yahoo intvprog group since the beginning (or close to it), but haven't tried to delve into the programming end until recently.


It looks like dZ's posted quite a long description of how background "cards" work. I guess I've never taken much time to discuss them myself since it always seemed like the easiest part. The character graphics on the STIC are very similar to what other video processors of the time offered.

Once you get comfortable with the low level stuff, you might want to abstract some of it away. There are some macros in jzIntv's "examples/macro" directory that help constructing various constants, such as display pointers and so on. "disp_ptr(r,c)" gives back the address you need to access the character card at row 'r', column 'c'. The "gen_cstk_card" and "gen_fgbg_card" macros take a description such as "gen_fgbg_card(13, GRAM, White, Blue)" to generate the constant needed for GRAM card #13 in white-on-blue when the display is in Foreground/Background mode.

Also, the "print.asm" and "print.mac" functions make it very easy to get text on screen. For example, to print "Hello World!" in the center of the screen when it's in color-stack mode, you can say, simply:

PRINT_CSTK 6, 4, White, "Hello World!"


#9 intvnut OFFLINE  

intvnut

    Stargunner

  • 1,103 posts
  • Location:@R6 (top of stack)

Posted Sat Feb 5, 2011 11:30 PM

BTW, one other thought: You mentioned you're not particularly familiar with assembly language. I presume you are familiar with some other language. What language(s) are you familiar with? Sometimes it's easier to explain assembly language constructs in terms of their equivalent code in some other higher level language.

For example, the BACKTAB is roughly equivalent to the C array "uint16_t backtab[12][20]". To format a string and display it, the C code might look like this:

void print(int row, int col, char *string, int format)
{
    uint16_t *disp_ptr = (uint16_t *)(0x200 + row*20 + col);
    uint16_t disp_word, tmp;

    while ((tmp = *string++) != 0)
    {
        tmp -= 32;        /* GROM is in ASCII order, but shifted by 32 characters */
        disp_word = format + (tmp << 3);
        *disp_ptr++ = disp_word;
    }

    return;
}

That same function might looks like this in assembly (with the original C code intermixed as comments):

    ; INPUTS:
    ;    R0 = row
    ;    R1 = col
    ;    R2 = string
    ;    R3 = format
    ;    R5 = return address

    PSHR R5  ; save return address on the stack
 
    ; Original C code:  uint16_t *disp_ptr = (uint16_t *)(0x200 + row*20 + col);
    MVII #$200, R4   ; R4 = 0x200
    SLL  R0, 2       ; R0 = row*4
    MOVR R0, R4      ; R4 = 0x200 + row*4
    SLL  R0, 2       ; R0 = row*16
    ADDR R0, R4      ; R4 = 0x200 + row*4 + row*16 = 0x200 + row*20
    ADDR R1, R4      ; R4 = 0x200 + row*20 + col   (R4 is now "disp_ptr")

    ; Original C code:  while ((tmp = *string++) != 0)
    MOVR R2, R5      ; Copy string to R5 for "auto-increment" behavior
@@loop:
    ; Note: Indirect accesses through R5 auto-increment R5
    MVI@ R5, R0      ; tmp = *string++
    TSTR R0          ; \_ Exit loop if tmp == 0
    BEQ  @@done      ; /

    ; Original C code:  tmp -= 32;
    SUBI #32, R0

    ; Original C code:  disp_word = format + (tmp << 3);
    SLL  R0, 2       ; R0 = tmp << 2
    SLL  R0, 1       ; R0 = tmp << 3
    ADDR R3, R0      ; R0 = format + (tmp << 3) (R0 is now "disp_word")

    ; Original C code:  *disp_ptr++ = disp_word; 
    ; Note: Indirect accesses through R4 auto-increment R4
    MVO@ R0, R4      ; *R4++ = R0

    ; Now close the "while" loop:
    B    @@loop

@@done:
    ; Original C code:  return;
    PULR PC          ; pop return address off stack into the program counter

Hopefully seeing how the C code maps to assembly code helps you to understand the assembly code. (Assuming, of course, you know C or a C-like language.)

Edited by intvnut, Sat Feb 5, 2011 11:31 PM.


#10 mphokie OFFLINE  

mphokie

    Star Raider

  • Topic Starter
  • 95 posts
  • Location:Charlotte, NC, USA

Posted Sun Feb 6, 2011 8:42 AM

BTW, one other thought: You mentioned you're not particularly familiar with assembly language. I presume you are familiar with some other language. What language(s) are you familiar with? Sometimes it's easier to explain assembly language constructs in terms of their equivalent code in some other higher level language.

For example, the BACKTAB is roughly equivalent to the C array "uint16_t backtab[12][20]". To format a string and display it, the C code might look like this:

void print(int row, int col, char *string, int format)
{
    uint16_t *disp_ptr = (uint16_t *)(0x200 + row*20 + col);
    uint16_t disp_word, tmp;

    while ((tmp = *string++) != 0)
    {
        tmp -= 32;        /* GROM is in ASCII order, but shifted by 32 characters */
        disp_word = format + (tmp << 3);
        *disp_ptr++ = disp_word;
    }

    return;
}

That same function might looks like this in assembly (with the original C code intermixed as comments):

    ; INPUTS:
    ;    R0 = row
    ;    R1 = col
    ;    R2 = string
    ;    R3 = format
    ;    R5 = return address

    PSHR R5  ; save return address on the stack
 
    ; Original C code:  uint16_t *disp_ptr = (uint16_t *)(0x200 + row*20 + col);
    MVII #$200, R4   ; R4 = 0x200
    SLL  R0, 2       ; R0 = row*4
    MOVR R0, R4      ; R4 = 0x200 + row*4
    SLL  R0, 2       ; R0 = row*16
    ADDR R0, R4      ; R4 = 0x200 + row*4 + row*16 = 0x200 + row*20
    ADDR R1, R4      ; R4 = 0x200 + row*20 + col   (R4 is now "disp_ptr")

    ; Original C code:  while ((tmp = *string++) != 0)
    MOVR R2, R5      ; Copy string to R5 for "auto-increment" behavior
@@loop:
    ; Note: Indirect accesses through R5 auto-increment R5
    MVI@ R5, R0      ; tmp = *string++
    TSTR R0          ; \_ Exit loop if tmp == 0
    BEQ  @@done      ; /

    ; Original C code:  tmp -= 32;
    SUBI #32, R0

    ; Original C code:  disp_word = format + (tmp << 3);
    SLL  R0, 2       ; R0 = tmp << 2
    SLL  R0, 1       ; R0 = tmp << 3
    ADDR R3, R0      ; R0 = format + (tmp << 3) (R0 is now "disp_word")

    ; Original C code:  *disp_ptr++ = disp_word; 
    ; Note: Indirect accesses through R4 auto-increment R4
    MVO@ R0, R4      ; *R4++ = R0

    ; Now close the "while" loop:
    B    @@loop

@@done:
    ; Original C code:  return;
    PULR PC          ; pop return address off stack into the program counter

Hopefully seeing how the C code maps to assembly code helps you to understand the assembly code. (Assuming, of course, you know C or a C-like language.)



Thanks Joe. I'm familiar with C. Right now, I work daily with Delphi/Object Pascal, PL/SQL, Perl, and PHP (and VB.NET when I'm forced to <g>). This is how I've learned new languages: first translate from my "original" one into the new until I become familiar enough w/the new one to start thinking in that language (similar, I guess, to learning a new spoken language). I think the biggest obstacle to the assembly portion is just getting familiar w/the different commands (and the order of parameters, etc.).

#11 vprette OFFLINE  

vprette

    Stargunner

  • 1,126 posts

Posted Tue Jun 21, 2011 7:46 AM

Could someone direct me to some simple Intellivision "Hello World"-type tutorials that show how to get graphics onto the screen? I've been messing around w/the SDK-1600 from JoeZ and checking around the net for more info, but I seem to be missing something.

I've downloaded the source for Ryan Kinnen's Minehunter from his site and have the Space Patrol teaser code, but what I'm looking for is the most bare-bones code I'd need to place graphics are background tiles, animate MOBs, etc. Mainly this is due to my complete inexperience w/assembly programming.

Also, is the "running man" graphics part of the GROM? It seems like it would be (assuming I'm understanding the underlying hardware/architecture), since it's used in so many games.


check that
http://www.intellivi...85Cs21SRm6Pw63m

at http://www.intellivi...ist.asp?iwCat=8




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users