Software Sprites MSX (Assembly)

By Chilly Willy

Expert (66)

Chilly Willy's picture

05-01-2021, 06:35

Can someone direct me to some code to manipulate software based sprites around the 768 8 bit tiles.

I know that sounds like a lot but before I move on to MSX2 or better I really want to hone my programing skills.
I can set up patters and display them on a basic level but I have never moved objects around the screen as a pattern.

Is there an article on this somewhere with example code?
Please Z80 assembly language.

Login or register to post comments

By Grauw

Ascended (10068)

Grauw's picture

05-01-2021, 11:45

I think you will have the most luck searching for some article created by the ZX Spectrum scene. In MSX1 games that are not speccy ports, typically the hardware sprites are used. And software sprites in MSX2 bitmap modes are typically done with VDP copy commands.

By theNestruo

Champion (317)

theNestruo's picture

05-01-2021, 11:44

This ancient code may be an example of what you are looking for:
http://karoshi.auic.es/index.php?topic=1456.0

By thegeps

Paladin (863)

thegeps's picture

05-01-2021, 11:46

Software sprites (if you aren't planning to use monochrome gfx) can't be moved pixel by pixel without messing with the background gfx, due to 8x1 pixel/2color limit on msx1 screen2 mode... but you can move them fast 8pixel per frame using similar background colors. If they move fast enough you shouldn't have problems...

Like this:
https://youtu.be/CFMFds-yQ9A

By Chilly Willy

Expert (66)

Chilly Willy's picture

05-01-2021, 19:18

I could always move them frame by frame and have a choppy look or even better move them every 4 bytes and use two patterns per movement. One whole and one Half in each direction.

I am beginning to see why hardware sprites were invented.
However so, software type sprites or whatever they were called have been used for years but calculating offsets and what not between tiles.

How about this.
Who can share the z80 formula to plot a single point on the screen because the tiles do add up to somewhere x and y on a 256x192 screen?

I can then add something like x, x+1
y, y+1
which would look like a 4x4 square.

By Grauw

Ascended (10068)

Grauw's picture

05-01-2021, 19:56

The 256×192 pixels of screen 2 are organised as 8×8 patterns in a grid of 32×24. Each 8×8 pattern is made of 8 bytes. By default the name table is set up so that the patterns patterns follow each other in sequence from left to right top to bottom.

You need to first calculate the address of the byte in the pattern table: base address | ((y & 248) << 5) | (x & 248) | (y & 7). Then you read that byte from VRAM, set bit x & 7, and write it back.

Hopefully that provides enough of a starting point to get the grasp of it.

| = or
& = and
<< = left shift

Note that add a,a and add hl,hl are quick alternatives to sla r.

By PingPong

Prophet (3767)

PingPong's picture

05-01-2021, 20:36

Addressing a single pixel in screen 2 is very slow.
I will try to discourage to to this, however i will try to point you to the right direction with a little z80 pseudo code for doing part of the operation that is done by two operations:
a) the bit mask calculation needed to turn on/off a pixel in the pattern_byte

b) vram byte address_calculation. here there is no assembly example, but a bunch of formulas, as you will see is somewhat cpu/consuming, so there is no assembler code to do this.

STEP (A)

Assuming the default nametable arrangement you need to calculate a bit mask that is given from X & 7 using this value the mask could be obtained by bit shift operation and a loop ma it is horribly slow. i suggest to have a ram area of precalculated 8 bytes mask in this way 128,64,32,16,8,4,2,1
so the mask is by this formula (this is a proposal not necessarily the fastest code, there is room for optimization, but is only to let you understand how things work):

get_mask:
ld a,  ; x screen coordinate in a
and 7 ; get the bit mask
le e,a 
ld d, 0
ld hl, mask_address
add hl,de
; here hl contains the mask address 
ld a,(hl) ; this is the bit mask
ret

STEP (B)
as said , you need to calculare the vram pattern address table where to plot the point. this is a little tricky

first calculate the address from Y value:
; charater_row = int(y/8)
; byte_ofs_in_charater_row = y and 7
; vram_addrs = charater_row*256+byte_ofs_in_charater_row

then we need to add the address component that comes from X value:
; x_additional_ofs = int (x / 8)

so the final address is for pattens something like this: pattern_vram_addrs = pattern_base_addr + vram_addrs+x_additional_ofs
but may be you also need to change color informations. so you need also to calculate the color_attribute_address in this way:
color_attribute_vram_addrs = color_attribute_base_addr + vram_addrs+x_additional_ofs

now comes the tricky part. when you plot a pixel in screen 2 the same displayed data could be given by two different byte value in vram attribute and pattern attibute. For example a white pixel under black background could be the result of two different bytes value

pattern = 128, color = 241
pattern = 127, color = 31

they do the same in terms of what you see on screen.

there is also an additional trick. if the pattern byte is 255 to plot a pixel you need to mask this byte with the inverted (complement to one) mask bit we calculate above, then write back the value, nevertheless you also to swap the right nibble in the color attribute byte. all those operations are bit mask operations / shift / set vram memory ptr that on msx are somewhat the slowest thing i can imagine.