Assembly Language Fundamentals

Intermediate
Version:
1.0

Combining Sprites to Form Larger Shapes

Introduction

While the Tatung Einstein’s VDP supports both 8×8 and 16×16 sprites, sometimes you’ll want more flexibility. For example, you might need a tall, narrow object like a rocket or flying saucer that doesn’t fit neatly into a square sprite.

A simple way to achieve this is to place two (or more) sprites next to each other and move them together. By synchronising their X and Y positions, they appear as one continuous shape — for instance, creating an 8×16 sprite by stacking two 8×8 sprites vertically or placing them side by side horizontally.

This approach lets you build custom sprite sizes (8×16, 16×24, 24×24, etc.) without enabling 16×16 mode, while keeping control over each sprite individually.

How It Works

Each sprite on the TMS9129 is independent, with its own position and pattern data. By defining two consecutive sprite patterns and assigning them adjacent coordinates, the VDP will draw them close enough that they appear to merge seamlessly into one image.

You simply need to:

  1. Define two patterns — one for each half of the composite sprite.
  2. Define two sprite attribute blocks with matching Y coordinates and adjacent X coordinates.
  3. Move both sprites together during animation so they maintain their relative spacing.

This method is particularly useful when building multi-part objects that may need to animate or change components separately later on.

Full Program

The following example program creates a simple 8×16 flying saucer by combining two separate 8×8 sprites side by side. Each sprite uses its own pattern, and both are positioned together to appear as one unified craft.

ORG 256

      ; -----------------------
      ; Enable Graphics Mode II
      ; ----------------------

       ; Set Register 0 values

       LD   A,2
       OUT  (9),A
       LD   A,128
       OUT  (9),A

       ; Set Register 1 values

       LD   A,224
       OUT  (9),A
       LD   A,129
       OUT  (9),A


      ; ---------------------------
      ; Set Foreground / Background
      ; ---------------------------

      LD   A, 240        ; 11110000 (white foreground, black background)
      OUT  (9), A
      LD   A, 135        ; 128 (bit 7 set) + 7 (register 7)
      OUT  (9), A

      ; -----------------
      ; Write Blank Tiles
      ; -----------------

      ; Top Third Blank Tile

      LD   A, 0
      OUT  (9), A
      LD   A, 64
      OUT  (9), A

      LD A, 0
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A

      ; Middle Third Blank Tile

      LD   A, 0
      OUT  (9), A
      LD   A, 72
      OUT  (9), A

      LD A, 0
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A

      ; Bottom Third Blank Tile

      LD   A, 0
      OUT  (9), A
      LD   A, 80
      OUT  (9), A

      LD A, 0
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A
      OUT (8), A


      ; --------------------------------
      ; Clear Name Table with Blank Tile
      ; --------------------------------

      LD A, 0
      OUT (9), A
      LD A, 120
      OUT (9), A

      LD BC, 768

ClearLoop:
      LD A, 0
      OUT (8), A
      DEC BC
      LD A, B
      OR C
      JR NZ, ClearLoop


       ; ---------------------
       ; Define Sprite Pattern
       ; ---------------------

       ; Flying Saucer - Left Half
       LD A,0
       OUT (9),A
       LD A,88
       OUT (9),A

       LD A,%00001111 : OUT (8),A
       LD A,%00011111 : OUT (8),A
       LD A,%00111000 : OUT (8),A
       LD A,%11111111 : OUT (8),A
       LD A,%11111111 : OUT (8),A
       LD A,%00111111 : OUT (8),A
       LD A,%00011111 : OUT (8),A
       LD A,%00001111 : OUT (8),A

       ; Flying Saucer - Right Half
       LD A,%11110000 : OUT (8),A
       LD A,%11111000 : OUT (8),A
       LD A,%00011100 : OUT (8),A
       LD A,%11111111 : OUT (8),A
       LD A,%11111111 : OUT (8),A
       LD A,%11111100 : OUT (8),A
       LD A,%11111000 : OUT (8),A
       LD A,%11110000 : OUT (8),A

       ; ------------------------
       ; Define Sprite Attributes
       ; ------------------------

       LD A,0
       OUT (9),A
       LD A,123
       OUT (9),A

       ; Sprite 0 (Left half)
       LD A,100
       OUT (8),A
       LD A,120
       OUT (8),A
       LD A,0
       OUT (8),A
       LD A,15
       OUT (8),A

       ; Sprite 1 (Right half)
       LD A,100
       OUT (8),A
       LD A,128
       OUT (8),A
       LD A,1
       OUT (8),A
       LD A,15
       OUT (8),A


       JP $            ; Loop indefinitely

Result

When you run this program, you’ll see a white flying saucer-shaped sprite composed of two 8×8 sprites side by side. Together, they form a continuous 8×16 object that appears as a single graphic.

Both halves are drawn independently by the VDP but appear merged thanks to their matching Y coordinates and adjacent X positions.

If you later animate the saucer, be sure to update both sprite coordinates simultaneously to maintain the illusion of a single object.

Why This Technique Is Useful

Combining sprites gives you greater control and flexibility than simply using fixed 16×16 mode. You can:

It’s a powerful technique that allows for custom sizes, colours, and animation effects while staying within the hardware limits of the TMS9129.

Summary

Previous Module
Next Module