Learn Multi platform
6502 Assembly Programming... For
Monsters!
Super
Simple Series
Logical Units and clipping
To allow us to crop our sprites, we'll need to move our sprite
around 'logical space' - only a portion of this will be the visible
screen.
We'll use this to crop the sprite. |
 |
We're designing our code for screens of 256x192 - and we'll use
'Logical Co-ordinates' which define a visible screen of 192x96 (2
pixels per logical unit)
The visible logical screen is in the center of the logical space
area to allow the sprite to be 'partially offscreen' on any side. |
 |
We need to crop any offscreen part to
get to the first visible pixel of the sprite.
After each line We also need to crop the unused
pixels to the next visible pixel
|
 |
We can now move our
sprite in pixels, but our sprites are still 16x16 pixel ' blocks',
we'll need to combine lots of hardware sprites to make our
character (3*3=9 hsprites)
|
 |
Our Sprite Routine
Before we draw our sprite we need to crop it with "DoCrop"
Zeropage pair z_bc is the X,Y co-ordinate in logical units
Zeropage pair z_hl is the Width,Height in logical units
Zeropage pair z_iy is the first tile pattern
If there is nothing onscreen, 'DoCrop' will return the Carry set.
|
 |
We need to select the VRAM address of our sprite - the sprites are
stored in address $7F00+
Each sprite uses 4 addresses |
 |
Our sprites are 16x16 pixels, and our screen is 256x239... but
there's a problem! the first visible pixel for the hardware sprites
is (X,Y) co-ordinate (32,64)!
We need to use 16 bit co-ordinates for our X and Y position.
To allow our sprites to be almost entirely cropped, We also need to
have one full sprite completely off the screen
We use z_c as our Y-pos, we need to multiply this by 2 and add 48
(64 pixels - the one offscreen 16 pixel sprite)
We use z_b as our X-pos and the X register as the sprite offset (we
need multiple sprites per line , we need to multiply this by 2 and
add 16 (32 pixels - the one offscreen 16 pixel sprite)
We need to write the 4 words that define our sprite in the table.
The first is the Ypos
The second is the Xpos
The third is the sprite pattern number
The fourth is the attribute (zero)
we add two to our source pattern address in z_IYL, and repeat until
the line is done.
After each sprite, we add 8 to z_c (16 pixels after the doubling) |
 |
After we've done a line we may need to remove some patterns to
handle the horizontal cropping, we then repeat until the image is
done.
|
 |
We use the DMA to transfer the sprite cache during NMI...
but it has a lot of settings we need to configure to transfer the
data!
|
|
our Chibiko usually uses 9 sprites, but if it goes partially
offscreen it will use less,
We need to zero the unused sprites to clear these. |
 |
Transferring our settings isn't enough, we need to send the data
to the SATB sprite attribute table.
we use a DMA to do this. |

|
Logical Cropping
Our cropping routine will work out the X,Y pos in bytes, and width
and height + any skipped pixels from the source data
Zeropage pair z_bc is the X,Y co-ordinate in logical units
Zeropage pair z_hl is the Width,Height in logical units
Zeropage pair z_iy is the source bitmap address of the sprite data
First we zero z_DE - it's used for temp values, and spritehclip
which is used for the horizontally skipped bytes after each line |
 |
Ok... lets crop the top of the sprite...
First we remove the ypos of the first visible pixel... if the result
is greater than zero, then nothing is off the screen at the top.
if the result is less than zero we need to crop...
we convert the negative to a positive and compare to the height of
our sprite, if the amount to crop is not less than the height then
the sprite is completely offscreen.
If the top line is partially off the screen we need to convert the
ypos so the sprite starts partially offscreen, we do this with EOR
#%00000111
|
|
Next we do the same for the bottom,
We add the height to the Ypos, and subtract the height of the
logical screen, if it's over the screen height (greater than zero)
we need to crop again - the result is the amount to crop
We need to convert it to a number of sprites (8 logical units) with
AND #%11111000
|
|
We've calculated the top and bottom crop... we now use these to
calculate the new height of the sprite. |
 |
We then skip over any bytes in the source (z_iy) based on the
number of lines we need to remove from the top.
We add 8 to the amount to remove, as we're overstating the size of
the screen by 8 logical units to allow for the 'partially offscreen'
sprites drawn at the top.
|
|
now we do the same for the X axis
First we remove the xpos of the first visible pixel... if the result
is greater than zero, then nothing is off the screen at the left.
if the result is less than zero we need to crop... we convert the
negative to a positive and compare to the width of our sprite, if
the amount to crop is not less than the width then the sprite is
completely offscreen.
Anything else is the number of lines we need to remove from the
left, we store this in z_e and adjust the starting draw with an EOR
#%00000111 to correct the starting position to adjust for the
removed sprites
|
|
Next we do the same for the right,
We add the width to the Xpos, and subtract the width of the logical
screen, if it's over the screen width (greater than zero) we need to
crop again - the result is the amount to crop |
 |
We've calculated the left and right crop... we now use these to
calculate the new width of the sprite.
We then skip over any bytes in the source (z_iy) based on the number
of bytes we need to remove from the left. |
 |
We've finished cropping our sprite!... but we need to convert our
co-ordinates from logical units to a sprite count -
effectively dividing Width and Height by 8
We leave the X,Y pos in logical units, we convert these later.
We clear the carry to tell the calling routine we cropped the sprite
successfully (it needs drawing) and return. |
 |
If the sprite is completely offscreen, there's no point trying to
draw, so we set the carry and return |
|
 |
Here we're
using a set of 16x16 sprites, as we wanted to try out our software
clipping code, but the PC Engine can actually define a single
sprite of up to 32x64!
We would still need to use multiple sprites to make our 48x48
pixel graphic though!
|
Logical Units and clipping
To allow us to crop our sprites, we'll need to move our sprite
around 'logical space' - only a portion of this will be the visible
screen.
We'll use this to crop the sprite. |
 |
We're designing our code for screens of 256x192 - and we'll use
'Logical Co-ordinates' which define a visible screen of 192x96 (2
pixels per logical unit)
The visible logical screen is in the center of the logical space
area to allow the sprite to be 'partially offscreen' on any side. |
 |
We need to crop any offscreen part to
get to the first visible pixel of the sprite.
After each line We also need to crop the unused
pixels to the next visible pixel
|
 |
Although each
character block only has 2x2 pixels, we'll treat each as 4x4
logical units to give a large virtual screen of 160x100 like other
systems.
Our graphic is 4x4 chars, which is 16x16 logical units
|
 |
Our Sprite Routine
Before we draw our sprite we need to crop it with "DoCrop"
Zeropage pair z_bc is the X,Y co-ordinate in logical units
Zeropage pair z_hl is the Width,Height in logical units
Zeropage pair z_iy is the first tile pattern
If there is nothing onscreen, 'DoCrop' will return the Carry set.
|
 |
GetVDPScreenPos will calculate the VRAM destination into zero page
pair z_de
We then transfer bytes from z_IY to z_DE
to move the VRAM destination down one line we add 40
after each line we update the source bitmap, adding the transferred
bytes, and any bytes that need to be skipped at the end of a line |
 |
GetVDPScreenPos will calculate the VRAM destination from X,Y pos
(b,c)
The formula is $8000 + Ypos *40 + Xpos
Multiplying by 40 is hard!... but multiplying by 32 and 8 is easier,
so we do this and add the two results together.
|
|
Logical Cropping
Our cropping routine will work out the X,Y pos in bytes, and width
and height + any skipped pixels from the source data
Zeropage pair z_bc is the X,Y co-ordinate in logical units
Zeropage pair z_hl is the Width,Height in logical units
Zeropage pair z_iy is the source bitmap address of the sprite data
First we zero z_DE - it's used for temp values, and spritehclip
which is used for the horizontally skipped bytes after each line |
 |
Ok... lets crop the top of the sprite...
First we remove the ypos of the first visible pixel... if the result
is greater than zero, then nothing is off the screen at the top.
if the result is less than zero we need to crop... we convert the
negative to a positive and compare to the height of our sprite, if
the amount to crop is not less than the height then the sprite is
completely offscreen.
We need to mask the count to a whole number of characters, we do
this with AND #%11111100
Anything else is the number of lines we need to remove from the top,
we store this in z_e and set the new 'draw position' to Ypos (z_c)
=0
|
|
Next we do the same for the bottom,
We add the height to the Ypos, and subtract the height of the
logical screen, if it's over the screen height (greater than zero)
we need to crop again - the result is the amount to crop
|
|
We've calculated the top and bottom crop... we now use these to
calculate the new height of the sprite. |
 |
We then skip over any bytes in the source (z_iy) based on the
number of lines we need to remove from the top.
|
|
now we do the same for the X axis
First we remove the xpos of the first visible pixel... if the result
is greater than zero, then nothing is off the screen at the left.
if the result is less than zero we need to crop... we convert the
negative to a positive and compare to the width of our sprite, if
the amount to crop is not less than the width then the sprite is
completely offscreen.
Anything else is the number of lines we need to remove from the
left, we store this in z_e and set the new 'draw position' to Xpos
(z_c) =0
|
|
Next we do the same for the right,
We add the width to the Xpos, and subtract the width of the logical
screen, if it's over the screen width (greater than zero) we need to
crop again - the result is the amount to crop |
 |
We've calculated the left and right crop... we now use these to
calculate the new width of the sprite.
We then skip over any bytes in the source (z_iy) based on the number
of bytes we need to remove from the left. |
 |
We've finished cropping our sprite!... but we need to convert our
co-ordinates from logical units (pairs of pixels) to a tile count -
effectively dividing Xpos,Ypos, Width and Height by 4
We clear the carry to tell the calling routine we cropped the sprite
successfully (it needs drawing) and return. |
 |
If the sprite is completely offscreen, there's no point trying to
draw, so we set the carry and return |
|
| |
Buy my Assembly programming book on Amazon in Print or Kindle!


Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
Buy my Assembly programming book on Amazon in Print or Kindle!


Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
Buy my Assembly programming book on Amazon in Print or Kindle!


Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
|