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.
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:
This method is particularly useful when building multi-part objects that may need to animate or change components separately later on.
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
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.
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.