Learn Multi platform 6502 Assembly Programming... For Monsters!

Super Simple Series

Lesson S31 - Hardware Sprite Clipping on the PC-Engine
Using the Tilemap isn't so useful for moving objects, as we can't shift the co-ordinates at the pixel level,

This time, lets do the same as last time, but we'll make our 48x48 pixel sprite out of 3x3 hardware sprites (16 pixel square) for smooth moves!

PCE_Bitmap_Clipping_Hsprite.asm

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!


Lesson S32 - Char Block clipping on the Commodore PET!
Lets alter our previous bitmap drawing routine, and allow it to be clipped so it can be partially offscreen.

PET_keys.asm

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



 

View Options
Default Dark
Simple (Hide this menu)
Print Mode (white background)

Top Menu
***Main Menu***
Youtube channel
Patreon
Merch Store
Amazon Affiliate Link
Forum
AkuSprite Editor
Dec/Bin/Hex/Oct/Ascii Table

Alt Tech
Archive.org
Bitchute
Odysee
Rumble
DailyMotion
Please note: I wlll upload more content to these alt platforms based on the views they bring in

Z80 Content
***Z80 Tutorial List***
Learn Z80 Assembly
Hello World
Advanced Series
Multiplatform Series
Platform Specific Series
ChibiAkumas Series
Grime Z80
Z80 Downloads
Z80 Cheatsheet
Sources.7z
DevTools kit
Z80 Platforms
Amstrad CPC
Elan Enterprise
Gameboy & Gameboy Color
Master System & GameGear
MSX & MSX2
Sam Coupe
TI-83
ZX Spectrum
Spectrum NEXT
Camputers Lynx

6502 Content
***6502 Tutorial List***
Learn 6502 Assembly
Advanced Series
Platform Specific Series
Hello World Series
Grime 6502
6502 Downloads
6502 Cheatsheet
Sources.7z
DevTools kit
6502 Platforms
Apple IIe
Atari 800 and 5200
Atari Lynx
BBC Micro
Commodore 64
Commander x16
Super Nintendo (SNES)
Nintendo NES / Famicom
PC Engine (Turbografx-16)
Vic 20

68000 Content
***68000 Tutorial List***
Learn 68000 Assembly
Hello World Series
Platform Specific Series
Grime 68000
68000 Downloads
68000 Cheatsheet
Sources.7z
DevTools kit
68000 Platforms
Amiga 500
Atari ST
Neo Geo
Sega Genesis / Mega Drive
Sinclair QL
X68000 (Sharp x68k)

8086 Content
Learn 8086 Assembly
Platform Specific Series
Hello World Series
8086 Downloads
8086 Cheatsheet
Sources.7z
DevTools kit
8086 Platforms
Wonderswan
MsDos

ARM Content
Learn ARM Assembly
Platform Specific Series
ARM Downloads
ARM Cheatsheet
Sources.7z
DevTools kit
ARM Platforms
Gameboy Advance
Nintendo DS
Risc Os

Risc-V Content
Learn Risc-V Assembly
Risc-V Downloads
Risc-V Cheatsheet
Sources.7z
DevTools kit

PDP-11 Content
Learn PDP-11 Assembly
PDP-11 Downloads
PDP-11 Cheatsheet
Sources.7z
DevTools kit

TMS9900 Content
Learn TMS9900 Assembly
TMS9900 Downloads
TMS9900 Cheatsheet
Sources.7z
DevTools kit
TMS9900 Platforms
Ti 99

6809 Content
Learn 6809 Assembly
6809 Downloads
6809/6309 Cheatsheet
Sources.7z
DevTools kit
6809 Platforms
Dragon 32/Tandy Coco
Fujitsu FM7
TRS-80 Coco 3
Vectrex

65816 Content
Learn 65816 Assembly
65816 Downloads
65816 Cheatsheet
Sources.7z
DevTools kit
65816 Platforms
SNES

eZ80 Content
Learn eZ80 Assembly
eZ80 Downloads
eZ80 Cheatsheet
Sources.7z
DevTools kit
eZ80 Platforms
SNES

Work in Progress
ChibiAndroids

Misc bits
Ruby programming









Buy my Assembly programming book
on Amazon in Print or Kindle!


Buy my Assembly programming book

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!


Buy my Assembly programming book

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